如下图为LMK04821时钟芯片的配置模块输入输出信号,主要分为三部分,
图1
1、模块的系统时钟和复位信号,cfg_clk时钟频率<=10MHz,频率的设置是根据LMK04821的SPI总线的spi_sck来确定的,具体可见LMK04821数据手册,内部有详细的介绍。cfg_rst模块高电平复位;
2、第二部分信号主要用于测试,因为我们配置时钟芯片时,如果只是按照规定的配置寄存器顺序完成寄存器配置,仅仅完成写操作,不进行读操作,这样一来我们没办法知道LMK04821内部的寄存器到底有没有配置正确,芯片如果输出的时钟频率不正确的话,也不知道具体原因,所以我们加入了一组vio控制信号,这组信号的功能就是,完成对LMK04821的寄存器的读操作,通过读寄存器来验证我们写入寄存器值得正确性。
一般来说,许多芯片都有一个固定的IC version寄存器,这个寄存器是只读寄存器,我们可以最先通过访问IC version寄存器来确定,芯片的供电有没有问题。比如LMK04821的IC version为0X 006,IC 信息为0X36;如图2所示。
图2
vio_cfg_en:进行寄存器读写操作时,通过vio拉高该信号;
vio_cfg_wr:0写,1读,通过vio控制读写操作;
vio_cfg_addr:寄存器地址,操作哪个寄存器就通过vio进行设置即可;
vio_cfg_wdata:寄存器配置数据,往指定的寄存器内写入的数据值;
addr_118_data:预留信号,暂无作用。
sel0、sel1配置 模式0;
设置需要配置的寄存器个数。
在配置寄存器之前我们需要注意到配置寄存器的顺序到底是怎么样的?如果没有经验可以参考手册中的建议的寄存器配置顺序。
根据以上的官方建议寄存器配置顺序,配置代码如下。举例说明:
data_reg<={r_w,23'h0000_80};r_w指读写标志,高16位表示地址,低8位表示配置数据。cnt_reg表示配置寄存器个数寄存器。
//data_reg:VCO0,1930~2075;VCO1,2920~3080;
always @(posedge cfg_clk or posedge cfg_rst)
begin
if(cfg_rst==1'b1)
begin
data_reg <= 24'h80_0000;
end
else
begin
case(cnt_reg)//VCO_2Ghz;
// Serial Port Configuration
8'd1 : data_reg <= {r_w,23'h0000_80} ;//soft reset
8'd2 : data_reg <= {r_w,23'h0000_00} ;//
8'd3 : data_reg <= {r_w,23'h0100_04} ;//500Mhz;DCLKout0: input and output drive level;device clock out divider values
8'd4 : data_reg <= {r_w,23'h0101_55} ;//controls the digital delay high and low count values for the device clock outputs
8'd5 : data_reg <= {r_w,23'h0103_00} ;//registers control the analog delay properties for the device clocks
8'd6 : data_reg <= {r_w,23'h0104_22} ;//set the half step for the device clock, the SYSREF output MUX, the SYSREF clock digital delay,and half step
8'd7 : data_reg <= {r_w,23'h0105_00} ;//set the analog delay parameters for the SYSREF outputs
8'd8 : data_reg <= {r_w,23'h0106_70} ;//controls the power down functions for the digital delay, glitchless half step
8'd9 : data_reg <= {r_w,23'h0107_15} ;//configure the output polarity, and format:11:LVDS;15:LVPECL16;
8'd10 : data_reg <= {r_w,23'h0108_10} ;//125Mhz;DCLKout2;V7_IO_CLK2;
8'd11 : data_reg <= {r_w,23'h0109_55} ;
8'd12 : data_reg <= {r_w,23'h010B_00} ;
8'd13 : data_reg <= {r_w,23'h010C_22} ;//bit[5]:SDCLKoutY_MUX;0, Device clock output;
8'd14 : data_reg <= {r_w,23'h010D_00} ;
8'd15 : data_reg <= {r_w,23'h010E_70} ;//bit[3]:0,enable;bit[4]:powerdown;
8'd16 : data_reg <= {r_w,23'h010F_11} ;//11:LVDS;15:LVPECL16
8'd17 : data_reg <= {r_w,23'h0110_10} ;//125Mhz;DCLKout4;
8'd18 : data_reg <= {r_w,23'h0111_55} ;
8'd19 : data_reg <= {r_w,23'h0113_00} ;
8'd20 : data_reg <= {r_w,23'h0114_22} ;//bit[5]:SDCLKoutY_MUX;0, Device clock output;
8'd21 : data_reg <= {r_w,23'h0115_00} ;
8'd22 : data_reg <= {r_w,23'h0116_70} ;//bit[3]:0,enable;bit[4]:powerdown;
8'd23 : data_reg <= {r_w,23'h0117_11} ;//11:LVDS;15:LVPECL16
8'd24 : data_reg <= {r_w,23'h0118_04} ;//500Mhz;DCLKout6,FPGA;V7_IO_CLK0;
8'd25 : data_reg <= {r_w,23'h0119_55} ;
8'd26 : data_reg <= {r_w,23'h011B_00} ;
8'd27 : data_reg <= {r_w,23'h011C_22} ;//bit[5]:SDCLKoutY_MUX;0, Device clock output;
8'd28 : data_reg <= {r_w,23'h011D_00} ;
8'd29 : data_reg <= {r_w,23'h011E_70} ;
8'd30 : data_reg <= {r_w,23'h011F_11} ;//11:LVDS;15:LVPECL16
8'd31 : data_reg <= {r_w,23'h0120_10} ;//125Mhz;DCLKout8,FPGA MGT114 CLOCK;
8'd32 : data_reg <= {r_w,23'h0121_55} ;
8'd33 : data_reg <= {r_w,23'h0123_00} ;
8'd34 : data_reg <= {r_w,23'h0124_02} ;//bit[5]:SDCLKoutY_MUX;0, Device clock output;
8'd35 : data_reg <= {r_w,23'h0125_00} ;
8'd36 : data_reg <= {r_w,23'h0126_70} ;
8'd37 : data_reg <= {r_w,23'h0127_11} ;//11:LVDS;15:LVPECL16
8'd38 : data_reg <= {r_w,23'h0128_10} ;//125Mhz;DCLKout10,FPGA MGT116 CLOCK;
8'd39 : data_reg <= {r_w,23'h0129_55} ;
8'd40 : data_reg <= {r_w,23'h012B_00} ;
8'd41 : data_reg <= {r_w,23'h012C_02} ;//bit[5]:SDCLKoutY_MUX;0, Device clock output;
8'd42 : data_reg <= {r_w,23'h012D_00} ;
8'd43 : data_reg <= {r_w,23'h012E_70} ;
8'd44 : data_reg <= {r_w,23'h012F_11} ;//11:LVDS;15:LVPECL16
8'd45 : data_reg <= {r_w,23'h0130_04} ;//500Mhz;DCLKout12;
8'd46 : data_reg <= {r_w,23'h0131_55} ;
8'd47 : data_reg <= {r_w,23'h0133_00} ;
8'd48 : data_reg <= {r_w,23'h0134_22} ;
8'd49 : data_reg <= {r_w,23'h0135_00} ;
8'd50 : data_reg <= {r_w,23'h0136_70} ;
8'd51 : data_reg <= {r_w,23'h0137_15} ;//11:LVDS;15:LVPECL16
8'd52 : data_reg <= {r_w,23'h0138_00} ;//selects the clock distribution source, and OSCout parameters;VCO0;
8'd53 : data_reg <= {r_w,23'h0139_03} ;//sets the source for the SYSREF outputs
8'd54 : data_reg <= {r_w,23'h013A_00} ;//SYSREF_DIV[12:8] DIV register 1;sysref 2000M/160=12.5Mhz;
8'd55 : data_reg <= {r_w,23'h013B_A0} ;//SYSREF_DIV[7:0] DIV register 0;
8'd56 : data_reg <= {r_w,23'h013C_08} ;//set the delay of the SYSREF digital delay value[12:8]
8'd57 : data_reg <= {r_w,23'h013D_00} ;//set the delay of the SYSREF digital delay value[7:0]
8'd58 : data_reg <= {r_w,23'h013E_03} ;//sets the number of SYSREF pulses if SYSREF is not in continuous mode;
8'd59 : data_reg <= {r_w,23'h013F_04} ;//controls the feedback feature
8'd60 : data_reg <= {r_w,23'h0140_01} ;//13-OSCin PD; powerdown controls for OSCin and SYSREF functions;bit[0]:Powerdown SYSREF pulse generator;
8'd61 : data_reg <= {r_w,23'h0141_FF} ;//enables dynamic digital delay for enabled device clocks
8'd62 : data_reg <= {r_w,23'h0142_00} ;//sets the number of dynamic digital delay adjustments occur
8'd63 : data_reg <= {r_w,23'h0143_91} ;//sets general SYNC parameters such as polarization, and mode
8'd64 : data_reg <= {r_w,23'h0144_00} ;//prevent a clock output from being synchronized or interrupted by a SYNC event or when outputting SYSREF
8'd65 : data_reg <= {r_w,23'h0145_7F} ;//Always program this register to value 127
8'd66 : data_reg <= {r_w,23'h0171_AA} ;//
8'd67 : data_reg <= {r_w,23'h0172_02} ;//
8'd68 : data_reg <= {r_w,23'h0173_00} ;//bit[6]PLL2_PRE_PD; bit[5]PLL2_PD;
8'd70 : data_reg <= {r_w,23'h017C_15} ;//OPT_REG_1:21;
8'd71 : data_reg <= {r_w,23'h017D_33} ;//OPT_REG_2:51;
8'd72 : data_reg <= {r_w,23'h0182_00} ;
8'd73 : data_reg <= {r_w,23'h0183_00} ;
8'd74 : data_reg <= {r_w,23'h0184_00} ;
8'd75 : data_reg <= {r_w,23'h0185_00} ;
8'd76 : data_reg <= {r_w,23'h0188_00} ;
8'd77 : data_reg <= {r_w,23'h0146_38} ;//CLKin enable and type controls.
8'd78 : data_reg <= {r_w,23'h0147_02} ;//CLKin_SEL_MODE. pin select mode;
8'd79 : data_reg <= {r_w,23'h0148_02} ;//CLKin_SEL0 controls
8'd80 : data_reg <= {r_w,23'h0149_42} ;//CLKin_SEL1 controls and register readback SDIO pin type
8'd81 : data_reg <= {r_w,23'h014A_02} ;//contains control of the RESET pin
8'd82 : data_reg <= {r_w,23'h014B_16} ;//contains the holdover functions:start;
8'd83 : data_reg <= {r_w,23'h014C_00} ;//
8'd84 : data_reg <= {r_w,23'h014D_00} ;//
8'd85 : data_reg <= {r_w,23'h014E_C0} ;//
8'd86 : data_reg <= {r_w,23'h014F_7F} ;//
8'd87 : data_reg <= {r_w,23'h0150_03} ;//
8'd88 : data_reg <= {r_w,23'h0151_02} ;//
8'd89 : data_reg <= {r_w,23'h0152_00} ;//contains the holdover functions:end;
8'd90 : data_reg <= {r_w,23'h0153_00} ;//CLKin0_R[13:8]
8'd91 : data_reg <= {r_w,23'h0154_01} ;//CLKin0_R[7:0]
8'd92 : data_reg <= {r_w,23'h0155_00} ;//CLKin1_R[13:8]
8'd93 : data_reg <= {r_w,23'h0156_40} ;//CLKin1_R[7:0]
8'd94 : data_reg <= {r_w,23'h0157_00} ;//CLKin2_R[13:8]
8'd95 : data_reg <= {r_w,23'h0158_40} ;//CLKin2_R[7:0]
8'd96 : data_reg <= {r_w,23'h0159_00} ;//PLL1_N[13:8]
8'd97 : data_reg <= {r_w,23'h015A_01} ;//PLL1_N[7:0]
8'd98 : data_reg <= {r_w,23'h015B_D4} ;//PLL1 phase detector
8'd99 : data_reg <= {r_w,23'h015C_20} ;//PLL1_DLD_CNT[13:8]
8'd100 : data_reg <= {r_w,23'h015D_00} ;//PLL1_DLD_CNT[7:0]
8'd101 : data_reg <= {r_w,23'h015E_00} ;//contains the delay value for PLL1 N and R delays.
8'd102 : data_reg <= {r_w,23'h015F_0B} ;//configures the PLL1 LD pin
8'd103 : data_reg <= {r_w,23'h0160_00} ;//PLL2_R[11:8]
8'd104 : data_reg <= {r_w,23'h0161_01} ;//PLL2_R[7:0]
8'd105 : data_reg <= {r_w,23'h0162_44} ;//sets other PLL2 functions:[7:5]:PLL2_P;[4:2]:OSCin_FREQ;[1]:PLL2_XTAL_EN;[0]:PLL2_REF_2X_EN;
8'd106 : data_reg <= {r_w,23'h0163_00} ;//PLL2_N_CAL[17:16]
8'd107 : data_reg <= {r_w,23'h0164_00} ;//PLL2_N_CAL[15:8]
8'd108 : data_reg <= {r_w,23'h0165_0C} ;//PLL2_N_CAL[7:0]
8'd109 : data_reg <= {r_w,23'h0166_00} ;//PLL2_N[17:16],MSB;
8'd110 : data_reg <= {r_w,23'h0167_00} ;//PLL2_N[15:8],---;
8'd111 : data_reg <= {r_w,23'h0168_0A} ;//PLL2_N[7:0],LSB;
8'd112 : data_reg <= {r_w,23'h0169_59} ;//controls the PLL2 phase detector
8'd113 : data_reg <= {r_w,23'h016A_60} ;//
8'd114 : data_reg <= {r_w,23'h016B_00} ;//
8'd115 : data_reg <= {r_w,23'h016C_00} ;//
8'd116 : data_reg <= {r_w,23'h016D_00} ;//
8'd117 : data_reg <= {r_w,23'h016E_13} ;//
8'd118 : data_reg <= {r_w,23'h0143_90} ;//
8'd119 : data_reg <= {r_w,23'h0139_00} ;//
8'd120 : data_reg <= {r_w,23'h0143_B0} ;//
8'd121 : data_reg <= {r_w,23'h0143_90} ;//
8'd122 : data_reg <= {r_w,23'h0144_FF} ;//
8'd123 : data_reg <= {r_w,23'h0143_10} ;//
8'd124 : data_reg <= {r_w,23'h0143_11} ;//
8'd125 : data_reg <= {r_w,23'h0139_03} ;//
8'd126 : data_reg <= {1'b1,23'h0002_00} ;//
default : data_reg <= 24'h80_0000 ;
endcase
end
end
以下代码属于SPI三线模式,
//spi_sdo/spi_cs_n/mid_data_o/mid_csn_o/mid_data_o/vio_cfg_cnt
always @(posedge cfg_clk or posedge cfg_rst)
begin
if(cfg_rst==1'b1)
begin
spi_sdo <= 1'b0;
spi_cs_n <= 1'b1;
mid_data_o <= 36'h0;
mid_csn_o <= 36'hFFFFFFFFF;
sdo_cnt <= 6'b0 ;
end
else
begin
if(load_p_d0==1'b1)
begin
spi_sdo <= 1'b0;
mid_data_o <= {data_reg[23:0],12'hfff};//r_w:0 write;1 read;
spi_cs_n <= 1'b1;
mid_csn_o <= {24'h0,12'hFFF};
sdo_cnt <= 6'h1 ;
end
else if(vio_cfg_en_d1==1'b1 && vio_cfg_en_d2==1'b0)
begin
spi_sdo <= 1'b0;
mid_data_o <= {vio_cfg_wr,2'b00,vio_cfg_addr,vio_cfg_wdata,12'hfff};//r_w:0 write;1 read;
spi_cs_n <= 1'b1;
mid_csn_o <= {24'h0,12'hFFF};
sdo_cnt <= 6'h1 ;
end
else
begin
spi_sdo <= mid_data_o[35];
mid_data_o <= {mid_data_o[34:0],1'b0};
spi_cs_n <= mid_csn_o[35];
mid_csn_o <= {mid_csn_o[34:0],1'b1};
if(sdo_cnt<6'h3f)
begin
sdo_cnt <= sdo_cnt + 6'h1 ;
end
else
begin
sdo_cnt <= sdo_cnt ;
end
end
end
end
//regdatareadvalid/regdataread
always @(posedge cfg_clk or posedge cfg_rst)
begin
if(cfg_rst==1'b1)
begin
regdatareadvalid <= 1'b0 ;
regdataread <= 8'b0 ;
end
else
begin
if(spi_cs_n==1'b0)
begin
if(data_reg[23]==1'b1)
begin
if(sdo_cnt>6'd18 && sdo_cnt<6'd25)//2-17;18-25;
begin
regdatareadvalid <= 1'b0 ;
regdataread <= {regdataread[6:0],spi_sdi};
end
else if(sdo_cnt==6'd25)
begin
regdatareadvalid <= 1'b1 ;
regdataread <= {regdataread[6:0],spi_sdi};
end
else
begin
regdatareadvalid <= 1'b0 ;
regdataread <= regdataread ;
end
end
else
begin
regdatareadvalid <= 1'b0 ;
regdataread <= regdataread ;
end
end
else
begin
regdatareadvalid <= 1'b0 ;
regdataread <= regdataread ;
end
end
end
配置完成标志。
//lmk_cfgdone
always @(posedge cfg_clk or posedge cfg_rst)
begin
if(cfg_rst)
begin
lmk_cfgdone <= 1'b0 ;
end
else
begin
if(cnt_reg>=NUM_REG)
begin
lmk_cfgdone <= 1'b1 ;
end
else
begin
lmk_cfgdone <= 1'b0 ;
end
end
end
本文主要对基于JESD204B开发的AD时钟芯片的配置代码做了一个解析,LMK04821的具体配置代码做了描述,参考者可根据自己的实际运用需求,修改配置的寄存器的数值,得到不同的时钟频率。寄存器具体的数据值,可参考下面的链接,里面讲述了辅助开发软件的使用,通过软件配置出自己所需的时钟频率,导出寄存器的具体参数,然后再修改对应寄存器配置数据即可。JESD204B高速AD开发(一)基于FPGA的LMK04821时钟芯片设计_芒果*爸爸的博客-CSDN博客_lmk04828中文手册https://blog.csdn.net/FDL_AQ/article/details/122445918?spm=1001.2014.3001.5502下一章,咱们开始jesd204b IP核的基础知识讲解。