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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/375690.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

maven插件docker-maven-plugin打包镜像并发布到dockerHub

文章目录 前言一、使用maven插件制作docker镜像二、发布到dockerHub总结 前言 如果我们的项目要在docker中运行&#xff0c;那么就必须要把我们的项目生成docker镜像&#xff0c;如果要实现远程安装&#xff0c;也就必须要把镜像发布到远程仓库里&#xff0c;如果我们没有自己…

旭华智能水文遥测终端机RTU

SV-RT8588低功耗测控终端&#xff0c;可采集、存储监测点传感器/仪表数据&#xff0c;通过4G/网口等通讯方式上传至监管平台&#xff0c;产品采用高性能32位处理器和工业级无线模块&#xff0c;接口类型丰富配置灵活&#xff0c;能满足不同场景下的各种需求&#xff1b;低功耗设…

JavaEE企业级应用软件开发—Spring框架入门学习笔记(一)

一、认识框架 实际开发中&#xff0c;随着业务的发展&#xff0c;软件系统变得越来越复杂&#xff0c;如果所有的软件都从底层功能开始开发&#xff0c;那将是一个漫长而繁琐的过程。此外&#xff0c;团队协作开发时&#xff0c;由于没有统一的调用规范&#xff0c;系统会出现大…

Vue3.4+element-plus2.5 + Vite 搭建教程整理

一、 Vue3Vite 项目搭建 说明&#xff1a; Vue3 最新版本已经基于Vite构建&#xff0c;关于Vite简介&#xff1a;Vite 下一代的前端工具链&#xff0c;前端开发与构建工具-CSDN博客 1.安装 并 创建Vue3 应用 npm create vuelatest 创建过程可以一路 NO 目前推荐使用 Vue R…

Django前后端分离之后端实践2

小实践&#xff1a;实现用户登录、注销及ORM管理功能、事务开启小实践 models.py class Books(models.Model):id models.CharField(primary_keyTrue,max_length20,verbose_name"图书ID")name models.CharField(max_length20,verbose_name图书名称)status models…

MySQL 小技巧:利用 xtrabackup 完全备份,增量备份及还原

案例&#xff1a;利用 xtrabackup 8.0 完全备份,增量备份及还原 MySQL8.0 在面对海量数据时&#xff0c;我们无法做到每天全量备份&#xff0c;因此 只能每周做一次全量备份。 而每天的话则进行增量备份&#xff0c;确保数据安全。 注意点&#xff1a;MySQL 8.0.26 版本对应需要…

基于Springboot的考编论坛网站的设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的考编论坛网站的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

Netty重点——ByteBuf特别篇(十五)

ByteBuf为什么好用 在网络编程中&#xff0c;基本都是基于TCP报文的字节流的操作&#xff0c;所以Java的NIO又新增了ByteBuffer&#xff0c;只不过Java原生的ByteBuffer&#xff0c;非常难操作&#xff0c;也不能扩容缩容&#xff0c;所以Netty又重新封装了自己的Bytebuf&#…

力扣经典题:相交链表

题目分析&#xff1a;两个链表如果相交且不存在环&#xff0c;那么这两个链表从相交节点往后的节点都相同&#xff0c;所以&#xff0c;遍历一个链表&#xff0c;在遍历时不断遍历另一个链表&#xff0c;只要相等就可以返回了 struct ListNode *getIntersectionNode(struct Li…

2024智慧城市新纪元:引领未来,重塑都市生活

随着科技的飞速发展和数字化转型的不断深入&#xff0c;2024年智慧城市领域迎来了全新的发展格局。 这一年&#xff0c;智慧城市的建设更加注重人性化、可持续性和创新性&#xff0c;为城市居民带来了前所未有的便捷与舒适。以下将重点关注智慧城市的几个核心内容&#xff0c;…

LeetCode:14.最长公共前缀

14. 最长公共前缀 - 力扣&#xff08;LeetCode&#xff09; 目录 题目&#xff1a; 思路&#xff1a; 代码有限注释&#xff1a; 每日表情包&#xff1a; 题目&#xff1a; 思路&#xff1a; 仅有一种&#xff0c;LeetCode的四种解法&#xff0c;三种都是来水的&#…

单片机学习笔记---串口通信(1)

目录 通信的基本概念 通信的方式 1.按照数据传送的方式&#xff0c;可分为串行通信和并行通信。 1.1串行通信 1.2并行通信 2.按照通信的数据同步方式&#xff0c;又可以分为异步通信和同步通信。 2.1 异步通信 2.2同步通信 3.按照数据的传输方向&#xff0c;又可以分为…

C#(C Sharp)学习笔记_If条件判断语句【五】

前言&#xff1a; 本期学习的是编程语言中的主要语句&#xff1a;if-条件判断语句。在这里我们会学到&#xff1a;if语法&#xff0c;if-else&#xff0c;和if嵌套。话不多说&#xff0c;我们开始吧&#xff01; 什么是条件判断语句&#xff1f; 条件语句是用来判断给定的条件…

数据库学习案例20240206-ORACLE NEW RAC agent and resource关系汇总。

1 集群架构图 整体集群架构图如下&#xff1a; 1 数据库启动顺序OHASD层面 操作系统进程init.ohasd run启动ohasd.bin init.ohasd run 集群自动启动是否被禁用 crsctl enable has/crsGIHOME所在文件系统是否被正常挂载。管道文件npohasd是否能够被访问&#xff0c; cd /var/t…

Android14音频进阶:MediaPlayerService如何启动AudioTrack 下篇(五十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘

因为PIL版本升级 # image image.resize((int(image.size[0] * (64 / image.size[1])), 64), Image.ANTIALIAS).convert(L) image image.resize((int(image.size[0] * (64 / image.size[1])), 64), Image.LANCZOS).convert(L)

Vue源码系列讲解——变化侦测篇【下】(Array的变化侦测)

目录 1. 前言 2. 在哪里收集依赖 3. 使Array型数据可观测 3.1 思路分析 3.2 数组方法拦截器 3.3 使用拦截器 4. 再谈依赖收集 4.1 把依赖收集到哪里 4.2 如何收集依赖 4.3 如何通知依赖 5. 深度侦测 6. 数组新增元素的侦测 7. 不足之处 8. 总结 1. 前言 上一篇文…

Unity类银河恶魔城学习记录3-4 EnemyBattleState P50

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Enemy.cs using System.Collections; using System.Collections.Generic; …

【RT-DETR有效改进】计算训练好权重文件对应的FPS、推理每张图片的平均时间(科研必备)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的改进机制是利用我们训练好的权重文件计算FPS,同时打印每张图片所利用的平均时间,模型大小(以MB为单位),同时支持batch_size功能的选择,对于轻量化模型的读者来说,本文的内容对你一定有…

网络基础(三)

网络层与数据链路层 1.网络层2.IP2.1 基本概念2.2 协议头格式2.3 网段划分2.4 特殊的IP地址2.5IP地址的数量限制2.6 私有IP地址和公网IP地址2.7 路由 3.数据链路层4.以太网&#xff08;MAC帧协议&#xff09;4.1 认识以太网4.2 以太网帧格式4.3 认识MAC地址4.4 对比理解MAC地址…
最新文章