AD9361多片同步设计方法
本文基于ZC706+FMCOMMS5的平台,介绍了多片AD9361同步的方法。并将该设计移植到自行设计的ZYNQ7035+4片AD9361(实现8路同步收发)的电路板上。本设计采用纯逻辑的方式,仅使用了ZYNQ芯片的PL部分。
9361多芯片同步主要包括基带同步和射频同步两大块任务。其中基带采用AD9361自带的MCS功能实现。而射频同步分为两种方法,分别是内部本振法和外部本振法。
在正式介绍同步之前,先做一点准备工作,主要包括SPI驱动、AD9361初始化,外部本振芯片ADF5355的控制等。因为FMCOMMS5上两片9361以及ADF5355共用了SPI_CLK、SPI_DO、SPI_DI信号,所以还涉及到总线如何仲裁的问题。
SPI驱动
下面是FMCOMM5驱动的端口:
module fmcomms5_spi(
input clk,
input rst_n,
//avalon interface
input [2:0] cs, //[0]:AD9361_CHIP A;[1]:AD9361_CHIP B;[2]:ADF5355
input read,
input write,
input [9:0] address,
input [27:0] writedata,
output reg [7:0] readdata,
output reg waitrequest,
//SPI interface
output reg spi_clk,
output reg spi_csn0,//SPI_ENB_A
output reg spi_csn1,//SPI_ENB_B
output reg spi_csn2,//ADF5355_LE
output reg spi_sdo,
input spi_sdi
);
这个模块将SPI总线转换成了Avalon总线,cs[0]选通AD9361-chip0;cs[1]选通AD9361-chip1;cs[2]选通ADF5355。cs[2]具有最高优先级,cs[1]和cs[0]具有相同的优先级。通过控制cs,可以实现分时写ADF5355、以及读写AD9361的寄存器(支持同时写和分时读2片AD9361)。
时序如下图:
avalon_mux:avalon总线多路复用
avalon_mux最大的作用是隔离各个功能代码,使各个模块看起来像是在独占SPI总线一样。这样便于设计代码层次结构以及区分功能模块。使每个想访问SPI的代码块都只需要设计一个avalon master接口,然后接到avalon_mux这个模块的一个avalon slave接口上即可。模块端口定义如下:
module avalon_mux #(parameter ADDR_WIDTH=256,DATA_WIDTH=256)
(
input clk,
input rst_n,
input [2:0] s0_cs,
input s0_read,
input s0_write,
input [ADDR_WIDTH-1:0] s0_address,
input [DATA_WIDTH-1:0] s0_writedata,
output reg [DATA_WIDTH-1:0] s0_readdata,
output reg s0_waitrequest,
input [2:0] s1_cs,
input s1_read,
input s1_write,
input [ADDR_WIDTH-1:0] s1_address,
input [DATA_WIDTH-1:0] s1_writedata,
output reg [DATA_WIDTH-1:0] s1_readdata,
output reg s1_waitrequest,
/*
此
处
有
省
略
*/
input [2:0] s7_cs,
input s7_read,
input s7_write,
input [ADDR_WIDTH-1:0] s7_address,
input [DATA_WIDTH-1:0] s7_writedata,
output reg [DATA_WIDTH-1:0] s7_readdata,
output reg s7_waitrequest,
output reg [2:0] m_cs,
output reg m_read,
output reg m_write,
output reg [ADDR_WIDTH-1:0] m_address,
output reg [DATA_WIDTH-1:0] m_writedata,
input [DATA_WIDTH-1:0] m_readdata,
input m_waitrequest
);
有了这个模块的加持,最终看到的代码结构类似于这样:
ad9361_init ad9361_init_inst0(
.clk (clk ),
.rst_n (rst_n ),
.cs (init0_cs ),
.read (init0_read ),
.write (init0_write ),
.address (init0_address ),
.writedata (init0_writedata ),
.readdata (init0_readdata ),
.waitrequest(init0_waitrequest ));
ad9361_init ad9361_init_inst1(
.clk (clk ),
.rst_n (rst_n ),
.cs (init1_cs ),
.read (init1_read ),
.write (init1_write ),
.address (init1_address ),
.writedata (init1_writedata ),
.readdata (init1_readdata ),
.waitrequest(init1_waitrequest ));
adf5355_init adf5355_init_inst(
.clk (clk ),
.rst_n (rst_n ),
.cs (adf5355_cs ),
.write (adf5355_write ),
.address (adf5355_address ),
.writedata (adf5355_writedata ),
.waitrequest(adf5355_waitrequest ));
avalon_mux avalon_mux_inst(
.clk (clk ),
.rst_n (rst_n ),
.s0_cs (init0_cs ),
.s0_read (init0_read ),
.s0_write (init0_write ),
.s0_address (init0_address ),
.s0_writedata (init0_writedata ),
.s0_readdata (init0_readdata ),
.s0_waitrequest (init0_waitrequest ),
.s1_cs (init1_cs ),
.s1_read (init1_read ),
.s1_write (init1_write ),
.s1_address (init1_address ),
.s1_writedata (init1_writedata ),
.s1_readdata (init1_readdata ),
.s1_waitrequest (init1_waitrequest ),
.s1_cs (adf5355_cs ),
.s1_read (adf5355_read ),
.s1_write (adf5355_write ),
.s1_address (adf5355_address ),
.s1_writedata (adf5355_writedata ),
.s1_readdata (adf5355_readdata ),
.s1_waitrequest (adf5355_waitrequest ),
.m_cs (m_cs ),
.m_read (m_read ),
.m_write (m_write ),
.m_address (m_address ),
.m_writedata (m_writedata ),
.m_readdata (m_readdata ),
.m_waitrequest (m_waitrequest ));
//spi driver
fmcomms5_spi fmcomms5_spi_inst(
.clk (clk ),
.rst_n (rst_n ),
.cs (m_cs ),
.read (m_read ),
.write (m_write ),
.address (m_address ),
.writedata (m_writedata ),
.readdata (m_readdata ),
.waitrequest (m_waitrequest ),
.spi_clk (SPI_CLK ),
.spi_csn0 (SPI_ENB_A ),
.spi_csn1 (SPI_ENB_B ),
.spi_csn2 (ADF5355_LE ),
.spi_sdo (SPI_DI ),
.spi_sdi (SPI_DO ));
其中两片AD9361的初始化、ADF5355的初始化都可以完全独立的设计实现,各个初始化模块只需要设计avalon的接口即可。而avalon接口到SPI就由avalon_mux和fmcomms5_spi 处理。
AD9361初始化
AD9361初始化相关内容见AD9361纯逻辑控制从0到1连载3-初始化模块以及相关文章。
ADF5355
有关ADF5355的配置可以参考下面代码:
/*初始化状态:
1.参数输入为40M,所有参考输入倍频分频器都设置为x1,使PFD = 40M
2.VCO输出3.66G,2分频输出,输出1.83G。对应9361的射频本振为915M
3.
*/
//reg0
parameter [0:0] AUTOCAL = 1; //autocal
parameter [0:0] PRESCALER = 0; //预分频器值;0=4/5;1=8/9;预分频器会限制INT值,当P为4/5时, NMIN为23;当P为8/9时, NMIN为75。
parameter [15:0] INTEGER = 91; //3660/40
//reg1
parameter [23:0] FRAC1 = 8388608; //(3660 mod 40)*2^24 = 0.5*(2^24)
//reg2
parameter [13:0] FRAC2 = 0; //14位辅助小数值(FRAC2)
parameter [13:0] MOD2 = 1; //14位辅助模数值(MOD2),FRAC2为0,MOD2随便取个值
//reg3
parameter [0:0] SD_LOAD_RESET = 0; //禁用写入寄存器0时, Σ-Δ调制器复位。对于相位持续调整的应用,可能不希望这样做。因此,在此类情况下,可将1写入SD1位(DB30)以禁用Σ-Δ复位。
parameter [0:0] PHASE_RESYNC = 0; //要使用相位再同步特性, 必须置1。
parameter [0:0] PHASE_ADJUST = 0; //要在每次寄存器0更新时调整ADF5355的相对输出相位,应将PA1位(DB28)设为1。与再同步特性不同,该特性适用于连续调整相位的应用。
parameter [23:0] PHASE = 0; //不做连续相位调整,相位值设置为0
//reg4
parameter [2:0] MUXOUT = 3'b110; //101:analog lock detect;110:digital lock detect
parameter [0:0] REF_DOUBLER = 0; //当RD2位(DB26)设置为0时,参考频率信号直接馈入10位R计数器,倍频器禁用。当此位设置为1时,参考频率加倍,然后输入10位R计数器。
parameter [0:0] RDIV2 = 0; //当RDIV2位(DB25)设置为1时, R计数器与PFD之间将插入一个二分频触发器,以扩大参考频率最大输入速率。该功能在PFD输入端提供50%占空比信号。
parameter [9:0] R_COUNTER= 1; //10位R计数器,可以细分输入参考频率(REFIN)以产生PFD的参考时钟。分频比范围是1到1023。
parameter [0:0] DOUBLER_BUF = 1; //双缓冲使能(写寄存器0后才生效)
parameter [3:0] CURRENT_SETTING= 4'b0010; //为使杂散最低,推荐设置为0.9 mA。
parameter [0:0] REF_MODE= 1; //ADF5355支持使用差分或单端参考源。对于差分源,应将参考模式位(DB9)设为1;对于单端源,应设为0。
parameter [0:0] MUX_LOGIC = 1; //为了支持逻辑兼容性, MUXOUT可设置两个逻辑电平。U5位(DB8)设为0即选择1.8 V逻辑,设为1即选择3.3 V逻辑。
parameter [0:0] PD_POLARITY= 1; //如果使用无源环路滤波器或同相有源环路滤波器,应将DB7设置为1(正)。如果使用反相有源滤波器,应将其设置为0(负)。
parameter [0:0] POWER_DOWN = 0; //设置为1时,执行关断程序。 DB6设置为0时,频率合成器恢复正常工作。在软件关断模式下, ADF5355会保留寄存器中的所有信息。
parameter [0:0] CP_THREE_STATE= 0; //电荷泵进入三态模式。 DB5设置为0时,正常工作。
parameter [0:0] COUNTER_RESET= 0; //复位ADF5355的R计数器、 N计数器和VCO频段选择。当DB4设为1时, RF频率合成器N计数器、 R计数器和VCO频段选择复位。正常工作时, DB4应设置为0。
//reg5
parameter [27:0] REG5_RESERVED = 28'h0080000;//寄存器5中的这些位保留,必须按照图43所示设置,使用十六进制字0x0080000。
//reg6
parameter [0:0] GATED_BLEED = 0; //渗漏电流可用于改善相位噪声和杂散,但它对锁定时间可能有影响。选通渗漏位BL10 (DB30)设置为1时,可确保渗漏电流直到数字锁定检测置位逻辑高电平时才开启。注意, 此功能要求使能数字锁定检测。
parameter [0:0] NEGATIVE_BLEED = 1; //对于大多数应用,建议使用恒定负渗漏,因为它能改善电荷泵的线性度,从而降低噪声和杂散。要使能负渗漏,应向BL9(位DB29)写入1;要禁用负渗漏,应向BL9(位DB29)写入0。
parameter [0:0] FEED_BACK_SELECT = 1; //D13(位DB24)选择从VCO输出到N计数器的反馈。 D13设置为1时,信号直接从VCO获得。此位设置为0时,信号从输出分频器的输出获得。这些分频器使得输出可涵盖较宽的频率范围(3.4 GHz至6.8 GHz)。当计数器使能且反馈信号从其输出获得时,两个独立配置PLL的RF输出信号同相。分频反馈在需要对信号进行正干涉以提高功率的一些应用中很有用。
parameter [2:0] RF_DIVIDER_SELECT = 1; //初始化为1,2分频输出
parameter [7:0] CHARGE_PUMP_BLEED_CURRENT=7;//IBLEED值,值要确保4/N < IBLEED/ICP < 10/N,可优化器件的相位噪声和杂散水平。ICP前面设置为0.9mA了,N是PFD到VCO的倍频因子
parameter [0:0] MTLD = 0; //设置为1,则切断RF输出级的电源电流,直到数字锁定检测电路检测到器件实现锁定为止。
parameter [0:0] RF_OUTB = 0; //使能或禁用高频RF输出(RFOUTB)。 设置为0时,高频RF输出使能。 设置为1时,辅助RF输出禁用。
parameter [0:0] RF_OUTA = 1; //D3(位DB6)使能或禁用主RF输出(RFOUTA+/RFOUTA−)。 DB6设置为0时,主RF输出禁用。 DB6设置为1时,主RF输出使能。
parameter [1:0] RF_OUT_POWER = 2'b10; //D2和D1(位[DB5:DB4])设置主RF输出功率水平的值(参见图44)。0=-4dBm;1=-1dBm;2=2dBm;3=5dBm
//reg7
parameter [0:0] LE_SYNC = 1; //设置为1时,位DB25确保加载使能(LE)沿与参考输入频率的上升沿内部同步。该同步可防止参考与RF分频器同时在参考频率的下降沿加载的罕见情况(可能导致锁定时间延长)。
parameter [1:0] LD_CYCLE_COUNT = 2'b00; //LD5和LD4(位[DB9:DB8])设置锁定检测电路连续计数多少周期后才将锁定检测置位高电平
parameter [0:0] LOL_MODE = 1; //对于可能会移除参考(REFIN)的固定频率应用,例如定时应用,应将LOL(位DB7)设置为1。标准锁定检测电路假设REFIN始终存在,但对于定时应用,情况可能并非如此。此功能通过将DB7设置为1来使能。
parameter [1:0] FRAC_N_LD_PRECISION = 2'b11;//LD3和LD2(位[DB6:DB5])设置小数N模式下锁定检测电路的精度。 LDP可设置为5 ns、 6 ns、 8 ns或12 ns。使用渗漏电流时,应使用12 ns。
parameter [0:0] LD_MODE = 0; //锁定检测模式(LDM)如果LD1(位DB4)设置为0,则每个参考周期由小数N锁定检测精度设置,如“小数N锁定检测计数(LDC)”部分所述。DB4设置为1时,各参考周期为2.9 ns长,这更适合整数N分频应用。
//reg8
parameter [27:0] REG8_RESERVED = 28'h102D402;//此寄存器中的这些位保留,必须按照图46所示设置,使用十六进制字0x102D402
//reg9
parameter [7:0] VCO_BAND_DIVISION = 17; //VC8至VC1(位[DB31:DB24])设置VCO频段分频时钟的值。用PFD/(频段分频× 16)确定此时钟的值,使得结果小于150 kHz。
parameter [9:0] TIMEOUT = 67; //TL10至TL1(位[DB23:DB14])设置VCO频段选择的超时值。此值用作其他VCO校准设置中的变量。
parameter [4:0] AUTOMATIC_LEVEL_TIMEOUT = 30; //保证(TIMEOUT × AUTOMATIC_LEVEL_TIMEOUT/PFD频率) > 50 µs
parameter [4:0] SYNTHESIZER_LOCK_TIMEOUT = 12; //(TIMEOUT ×SYNTHESIZER_LOCK_TIMEOUT/PFD频率) > 20 µs
//reg10
parameter [7:0] ADC_CLOCK_DIVIDER = 100; //PFD/((ADC_CLK × 4) × 2) < 100 kHz
parameter [0:0] ADC_CONVERSION = 1; //AE2(位DB5)确保对寄存器10执行写操作后, ADC执行转换。建议使能这种模式。
parameter [0:0] ADC_ENABLE = 1; //AE1(位DB4)设置为1时, ADC上电以执行温度相关的VTUNE校准。建议总是使用该功能。
//reg11
parameter [27:0] REG11_RESERVED = 28'h0061300;//此寄存器中的这些位保留,必须按照图49所示设置,使用十六进制字0x0061300
//reg12
parameter [15:0] RESYNC_CLOCK = 0;//When not using phase resync, set these bits to 1 for normaloperation
function [31:0] adf5355_lut;
input [7:0] index;
begin
case(index)
8'd0 :adf5355_lut={4'hc,RESYNC_CLOCK,12'b0000_0100_0001};
8'd1 :adf5355_lut={4'hb,REG11_RESERVED};
8'd2 :adf5355_lut={4'ha,18'b00_0000_0011_0000_0000,ADC_CLOCK_DIVIDER,ADC_CONVERSION,ADC_ENABLE};
8'd3 :adf5355_lut={4'h9,VCO_BAND_DIVISION,TIMEOUT,AUTOMATIC_LEVEL_TIMEOUT,SYNTHESIZER_LOCK_TIMEOUT};
8'd4 :adf5355_lut={4'h8,REG8_RESERVED};
8'd5 :adf5355_lut={4'h7,6'b000100,LE_SYNC,15'd0,LD_CYCLE_COUNT,LOL_MODE,FRAC_N_LD_PRECISION,LD_MODE};
8'd6 :adf5355_lut={4'h6,1'b0,GATED_BLEED,NEGATIVE_BLEED,4'b1010,FEED_BACK_SELECT,RF_DIVIDER_SELECT,CHARGE_PUMP_BLEED_CURRENT,1'b0,MTLD,RF_OUTB,3'b000,RF_OUTA,RF_OUT_POWER};
8'd7 :adf5355_lut={4'h5,REG5_RESERVED};
8'd8 :adf5355_lut={4'h4,2'b00,MUXOUT,REF_DOUBLER,RDIV2,R_COUNTER,DOUBLER_BUF,CURRENT_SETTING,REF_MODE,MUX_LOGIC,PD_POLARITY,POWER_DOWN,CP_THREE_STATE,COUNTER_RESET};
8'd9 :adf5355_lut={4'h3,1'b0,SD_LOAD_RESET,PHASE_RESYNC,PHASE_ADJUST,PHASE};
8'd10:adf5355_lut={4'h2,FRAC2,MOD2};
8'd11:adf5355_lut={4'h1,4'b0000,FRAC1};
8'd12:adf5355_lut={4'hf,28'd0}; //delay
8'd13:adf5355_lut={4'h0,10'b0000000000,AUTOCAL,PRESCALER,INTEGER};
default:adf5355_lut=32'hffffffff;
endcase
end
endfunction
初始化的方法就是依次执行adf5355_lut这个函数列表的指令,比如第一条指令是写{RESYNC_CLOCK,12’b0000_0100_0001}到4’hc这个寄存器。
如果需要动态修改ADF5355的频率,则执行下面的命令列表即可:
function [31:0] cmd;
input [7:0] index;
begin
case(index)
0 :cmd={4'ha,18'h00300,ADC_CLOCK_DIVIDER,ADC_CONVERSION,ADC_ENABLE};
1 :cmd={4'h4,2'b00,MUXOUT,REF_DOUBLER,RDIV2,R_COUNTER,DOUBLER_BUF,CURRENT_SETTING,REF_MODE,MUX_LOGIC,PD_POLARITY,POWER_DOWN,CP_THREE_STATE,1'b1};
2 :cmd={4'h6,1'b0,GATED_BLEED,NEGATIVE_BLEED,4'b1010,FEED_BACK_SELECT,lo_div,CHARGE_PUMP_BLEED_CURRENT,1'b0,MTLD,RF_OUTB,3'b000,RF_OUTA,RF_OUT_POWER};
3 :cmd={4'h2,lo_frac2,lo_mod2};
4 :cmd={4'h1,4'd0,lo_frac1};
5 :cmd={4'h0,10'd0,1'b0,PRESCALER,lo_int};
6 :cmd={4'h4,2'b00,MUXOUT,REF_DOUBLER,RDIV2,R_COUNTER,DOUBLER_BUF,CURRENT_SETTING,REF_MODE,MUX_LOGIC,PD_POLARITY,POWER_DOWN,CP_THREE_STATE,1'b0};
7 :cmd={4'hf,28'd0};
8 :cmd={4'h0,10'd0,AUTOCAL,PRESCALER,lo_int};
default:cmd=32'hffffffff;
endcase
end
endfunction
其中lo_div,lo_int,lo_frac1,lo_frac2,lo_mod2根据频率计算得出,具体计算方法由下面这个模块得到。
module adf5355_freq2param(
input clk,
input rst_n,
input [33:0] lo_freq,
output reg [2:0] lo_div,
output reg [15:0] lo_int,
output reg [23:0] lo_frac1,
output reg [13:0] lo_frac2,
output reg [13:0] lo_mod2,
output reg param_valid
);
写不动了,先贴个顶层在这里,后面有时间再补吧
module zc706_fmcomms5(
// input USRCLK_P, //156.25M
// input USRCLK_N,
input REF_CLK_FMC_P,
input REF_CLK_FMC_N,
//sync pin
output SYNC_IN,
//spi pins
output SPI_ENB_A,
output SPI_ENB_B,
output SPI_CLK,
output SPI_DI,
input SPI_DO,
input ADF5355_LOCK,
output ADF5355_RF_EN,
output ADF5355_LE,
output reg CAL_SW_1,
output reg CAL_SW_2,
output reg CAL_SW_3,
output reg CAL_SW_4,
//fmc power enable
output PG_FMC,
output GPIO_LED_RIGTH,
output GPIO_LED_LEFT,
output GPIO_LED_CENTER,
output GPIO_LED_0,
//chip A
output RESET_A,
output EN_AGC_A,
output ENABLE_A,
output TXNRX_A,
output [3:0] CTRL_IN_A,
input [7:0] CTRL_OUT_A,
output FB_CLK_P_A,
output FB_CLK_N_A,
output [5:0] TX_D_P_A,
output [5:0] TX_D_N_A,
output TX_FRAME_P_A,
output TX_FRAME_N_A,
input DATA_CLK_P_A,
input DATA_CLK_N_A,
input [5:0] RX_D_P_A,
input [5:0] RX_D_N_A,
input RX_FRAME_P_A,
input RX_FRAME_N_A,
//chip B
output RESET_B,
output EN_AGC_B,
output ENABLE_B,
output TXNRX_B,
output [3:0] CTRL_IN_B,
input [7:0] CTRL_OUT_B,
output FB_CLK_P_B,
output FB_CLK_N_B,
output [5:0] TX_D_P_B,
output [5:0] TX_D_N_B,
output TX_FRAME_P_B,
output TX_FRAME_N_B,
input DATA_CLK_P_B,
input DATA_CLK_N_B,
input [5:0] RX_D_P_B,
input [5:0] RX_D_N_B,
input RX_FRAME_P_B,
input RX_FRAME_N_B,
input [3:0] GPIO_DIP_SW
);
zynq_wrapper zynq_wrapper();
assign PG_FMC = 1;
//AD9361 config clock and init states
wire clk_40m;
wire sample_clk;
wire lock_out;
wire vio_mcs_rst;
wire vio_cal_rst;
wire vio_rd_lock;
wire vio_bist_rx;
wire vio_bist_loop;
wire [32:0] vio_lo_freq;
wire [7:0] vio_reg006,vio_reg007;
wire [7:0] vio_mgc1_value,vio_mgc2_value;
wire [8:0] vio_tx1_att,vio_tx2_att;
wire vio_alert;
wire vio_cal_busy;
wire vio_tx_on,vio_rx_on;
wire vio_rst;
wire vio_ext_lo_en;
wire init_done_a,init_done_b;
wire config_done_a,config_done_b;
wire mcs_done;
reg mcs_done_r1,mcs_done_r2;
wire cal_busy;
reg cal_busy_r1,cal_busy_r2;
wire adf5355_config_done;
reg adf5355_config_done_r1,adf5355_config_done_r2;
always @ (posedge clk_40m)
{cal_busy_r2,cal_busy_r1}<={cal_busy_r1,cal_busy};
always @ (posedge sample_clk)
begin
{mcs_done_r2,mcs_done_r1}<={mcs_done_r1,mcs_done};
{adf5355_config_done_r2,adf5355_config_done_r1}<={adf5355_config_done_r1,adf5355_config_done};
end
reg [25:0] alive_cnt;
always @ (posedge clk_40m)
alive_cnt<=alive_cnt+1;
assign GPIO_LED_RIGTH=alive_cnt[25];
assign GPIO_LED_LEFT=alive_cnt[25];
assign GPIO_LED_CENTER=alive_cnt[25];
assign GPIO_LED_0=alive_cnt[25];
clk_wiz_1 clk_wiz_1_inst(
.clk_out1 (clk_40m),
.reset (1'b0),
.locked (locked),
.clk_in1_p (REF_CLK_FMC_P),
.clk_in1_n (REF_CLK_FMC_N));
assign rst_n = locked && !vio_rst;
wire [2:0] s0_cs=3'b001;
wire s0_read;
wire s0_write;
wire [7:0] s0_writedata;
wire [7:0] s0_readdata;
wire [9:0] s0_address;
wire s0_waitrequest;
wire [2:0] s1_cs=3'b010;
wire s1_read;
wire s1_write;
wire [7:0] s1_writedata;
wire [7:0] s1_readdata;
wire [9:0] s1_address;
wire s1_waitrequest;
wire [2:0] mcs_cs;
wire mcs_read;
wire mcs_write;
wire [7:0] mcs_writedata;
wire [7:0] mcs_readdata;
wire [9:0] mcs_address;
wire mcs_waitrequest;
wire [2:0] debug_cs;
wire debug_read;
wire debug_write;
wire [27:0] debug_writedata;
wire [7:0] debug_readdata;
wire [9:0] debug_address;
wire debug_waitrequest;
wire [2:0] adf5355_init_cs = 3'b100;
wire adf5355_init_read;
wire adf5355_init_write;
wire [27:0] adf5355_init_writedata;
wire [3:0] adf5355_init_address;
wire adf5355_init_waitrequest;
wire [2:0] adf5355_config_cs = 3'b100;
wire adf5355_config_read;
wire adf5355_config_write;
wire [27:0] adf5355_config_writedata;
wire [3:0] adf5355_config_address;
wire adf5355_config_waitrequest;
wire [2:0] m_cs;
wire m_read;
wire m_write;
wire [27:0] m_writedata;
wire [7:0] m_readdata;
wire [9:0] m_address;
wire m_waitrequest;
/*****************************************************************/
ad9361_config ad9361_config_inst0 (
.clk (clk_40m ),
.rst_n (rst_n ),
.read (s0_read ),
.write (s0_write ),
.writedata (s0_writedata ),
.readdata (s0_readdata ),
.address (s0_address ),
.waitrequest (s0_waitrequest ),
.txnrx (TXNRX_A ),
.enable (ENABLE_A ),
.chip_rst_n (RESET_A ),
.init_done (init_done_a ),
.config_done (config_done_a ),
.rd_lock (vio_rd_lock ),
.mgc1_value (vio_mgc1_value ),
.mgc2_value (vio_mgc2_value ),
.bist_rx (vio_bist_rx ),
.bist_loop (vio_bist_loop ),
.reg006 (vio_reg006 ),
.reg007 (vio_reg007 ),
.tx1_att (vio_tx1_att ),
.tx2_att (vio_tx2_att ),
.tx_lo_freq (vio_lo_freq ),
.rx_lo_freq (vio_lo_freq ),
.alert (vio_alert ),
.ext_lo_en (vio_ext_lo_en ),
.cal_busy (cal_busy_r2 ),
.tx_on (vio_tx_on ),
.rx_on (vio_rx_on ));
ad9361_config ad9361_config_inst1 (
.clk (clk_40m ),
.rst_n (rst_n ),
.read (s1_read ),
.write (s1_write ),
.writedata (s1_writedata ),
.readdata (s1_readdata ),
.address (s1_address ),
.waitrequest (s1_waitrequest ),
.txnrx (TXNRX_B ),
.enable (ENABLE_B ),
.chip_rst_n (RESET_B ),
.init_done (init_done_b ),
.config_done (config_done_b ),
.rd_lock (vio_rd_lock ),
.mgc1_value (vio_mgc1_value ),
.mgc2_value (vio_mgc2_value ),
.bist_rx (vio_bist_rx ),
.bist_loop (vio_bist_loop ),
.reg006 (vio_reg006 ),
.reg007 (vio_reg007 ),
.tx1_att (vio_tx1_att ),
.tx2_att (vio_tx2_att ),
.tx_lo_freq (vio_lo_freq ),
.rx_lo_freq (vio_lo_freq ),
.alert (vio_alert ),
.ext_lo_en (vio_ext_lo_en ),
.cal_busy (cal_busy_r2 ),
.tx_on (vio_tx_on ),
.rx_on (vio_rx_on ));
wire tx_sel,rx_sel;
always @ (posedge sample_clk)
begin
CAL_SW_1 <= !tx_sel; //tx_sel=0:A selected;tx_sel=1:B selected
CAL_SW_2 <= !rx_sel; //tx_sel=0:A selected;tx_sel=1:B selected
end
vio_top vio_top_inst(
.clk (clk_40m ),
.probe_out0 (vio_mcs_rst ),
.probe_out1 (vio_cal_busy ),
.probe_out2 (vio_bist_rx ),
.probe_out3 (vio_bist_loop ),
.probe_out4 (vio_lo_freq ),
.probe_out5 (vio_rd_lock ),
.probe_out6 (vio_reg006 ),
.probe_out7 (vio_reg007 ),
.probe_out8 (vio_mgc1_value ),
.probe_out9 (vio_mgc2_value ),
.probe_out10(vio_tx1_att ),
.probe_out11(vio_tx2_att ),
.probe_out12(vio_alert ),
.probe_out13(vio_tx_on ),
.probe_out14(vio_rx_on ),
.probe_out15(vio_rst ));
wire adf5355_init_done;
adf5355_init adf5355_init_inst(
.clk (clk_40m ),
.rst_n (rst_n ),
.write (adf5355_init_write ),
.address (adf5355_init_address ),
.writedata (adf5355_init_writedata ),
.waitrequest(adf5355_init_waitrequest ),
.init_done (adf5355_init_done ));
mcs mcs_inst(
.clk (clk_40m ),
.rst_n (rst_n ),
.cs (mcs_cs ),
.write (mcs_write ),
.read (mcs_read ),
.address (mcs_address ),
.writedata (mcs_writedata ),
.readdata (mcs_readdata ),
.waitrequest (mcs_waitrequest ),
.mcs_done (mcs_done ),
.sync_in (SYNC_IN ));
adf5355_config adf5355_config(
.clk (clk_40m ),
.rst_n (rst_n ),
.write (adf5355_config_write ),
.writedata (adf5355_config_writedata ),
.address (adf5355_config_address ),
.waitrequest(adf5355_config_waitrequest ),
.freq ({lo_freq ));
avalon_mux avalon_mux_inst(
.clk (clk_40m ),
.rst_n (rst_n ),
.s0_cs (s0_cs ),
.s0_read (s0_read ),
.s0_write (s0_write ),
.s0_address (s0_address ),
.s0_writedata (s0_writedata ),
.s0_readdata (s0_readdata ),
.s0_waitrequest (s0_waitrequest ),
.s1_cs (s1_cs ),
.s1_read (s1_read ),
.s1_write (s1_write ),
.s1_address (s1_address ),
.s1_writedata (s1_writedata ),
.s1_readdata (s1_readdata ),
.s1_waitrequest (s1_waitrequest ),
.s2_cs (mcs_cs ),
.s2_read (mcs_read ),
.s2_write (mcs_write ),
.s2_address (mcs_address ),
.s2_writedata (mcs_writedata ),
.s2_readdata (mcs_readdata ),
.s2_waitrequest (mcs_waitrequest ),
.s3_cs (debug_cs ),
.s3_read (debug_read ),
.s3_write (debug_write ),
.s3_address (debug_address ),
.s3_writedata (debug_writedata ),
.s3_readdata (debug_readdata ),
.s3_waitrequest (debug_waitrequest ),
.s4_cs (adf5355_init_cs ),
.s4_write (adf5355_init_write ),
.s4_address (adf5355_init_address ),
.s4_writedata (adf5355_init_writedata ),
.s4_waitrequest (adf5355_init_waitrequest ),
.s5_cs (adf5355_config_cs ),
.s5_write (adf5355_config_write ),
.s5_address (adf5355_config_address ),
.s5_writedata (adf5355_config_writedata ),
.s5_waitrequest (adf5355_config_waitrequest ),
.m_cs (m_cs ),
.m_read (m_read ),
.m_write (m_write ),
.m_address (m_address ),
.m_writedata (m_writedata ),
.m_readdata (m_readdata ),
.m_waitrequest (m_waitrequest ));
//spi driver
fmcomms5_spi fmcomms5_spi_inst(
.clk (clk_40m ),
.rst_n (locked ),
.cs (m_cs ),
.read (m_read ),
.write (m_write ),
.address (m_address ),
.writedata (m_writedata ),
.readdata (m_readdata ),
.waitrequest (m_waitrequest ),
.spi_clk (SPI_CLK ),
.spi_csn0 (SPI_ENB_A ),
.spi_csn1 (SPI_ENB_B ),
.spi_csn2 (ADF5355_LE ),
.spi_sdo (SPI_DI ),
.spi_sdi (SPI_DO ));
assign ADF5355_RF_EN = 1;
/**********************数据接口*************************/
data_if_top data_if_top_inst(
.sample_clk (sample_clk ),
.lock_out (lock_out ),
.dac0_data_i1 (dac0_data_i1 ),
.dac0_data_q1 (dac0_data_q1 ),
.dac0_data_i2 (dac0_data_i2 ),
.dac0_data_q2 (dac0_data_q2 ),
.adc0_data_i1 (adc0_data_i1 ),
.adc0_data_q1 (adc0_data_q1 ),
.adc0_data_i2 (adc0_data_i2 ),
.adc0_data_q2 (adc0_data_q2 ),
.dac1_data_i1 (dac1_data_i1 ),
.dac1_data_q1 (dac1_data_q1 ),
.dac1_data_i2 (dac1_data_i2 ),
.dac1_data_q2 (dac1_data_q2 ),
.adc1_data_i1 (adc1_data_i1 ),
.adc1_data_q1 (adc1_data_q1 ),
.adc1_data_i2 (adc1_data_i2 ),
.adc1_data_q2 (adc1_data_q2 ),
.rx0_data_clk_p (DATA_CLK_P_A ),
.rx0_data_clk_n (DATA_CLK_N_A ),
.rx0_frame_in_p (RX_FRAME_P_A ),
.rx0_frame_in_n (RX_FRAME_N_A ),
.rx0_data_in_p (RX_D_P_A ),
.rx0_data_in_n (RX_D_N_A ),
.tx0_clk_out_p (FB_CLK_P_A ),
.tx0_clk_out_n (FB_CLK_N_A ),
.tx0_frame_out_p (TX_FRAME_P_A ),
.tx0_frame_out_n (TX_FRAME_N_A ),
.tx0_data_out_p (TX_D_P_A ),
.tx0_data_out_n (TX_D_N_A ),
.rx1_data_clk_p (DATA_CLK_P_B ),
.rx1_data_clk_n (DATA_CLK_N_B ),
.rx1_frame_in_p (RX_FRAME_P_B ),
.rx1_frame_in_n (RX_FRAME_N_B ),
.rx1_data_in_p (RX_D_P_B ),
.rx1_data_in_n (RX_D_N_B ),
.tx1_clk_out_p (FB_CLK_P_B ),
.tx1_clk_out_n (FB_CLK_N_B ),
.tx1_frame_out_p (TX_FRAME_P_B ),
.tx1_frame_out_n (TX_FRAME_N_B ),
.tx1_data_out_p (TX_D_P_B ),
.tx1_data_out_n (TX_D_N_B ),
.cal_rst_n (ADF5355_LOCK ),
.cal_busy (cal_busy ),
.tx_sel (tx_sel ),
.rx_sel (rx_sel ));
endmodule