当前位置:   article > 正文

基于Xilinx的FPGA高速串行接口设计(ADS6445)_fpga设计接口芯片

fpga设计接口芯片

目录

1.器件手册

2.PCB电路板绘制

3.SPI配置

4.程序框架

5.具体程序(原语)

6.测试结果


1.器件手册

        四通道,14bit,采样率为125/105M,ADC采用串行LVDS接口输出,结构图如下所示:

名称

方向

说明

CLK_P

CLK_M

In

FPGA提供给ADC的差分时钟,范围5-125Mhz

DCLK_P

DCLK_M

Out

ADC提供给FPGA的位时钟,位时钟的变化处在数据的中间位置,以保持数据的稳定

FCLK_P

FCLK_M

Out

ADC提供给FPGA的帧时钟,作用是判断完整的14bit数据

DA0_P

DA0_M

DA1_P

DA1_M

Out

LVDS接口的数据输出,采用的是两线制的因此有4个接口

SEN

SDATA

SCLK

RESET

In

通过SPI配置ADC寄存器更改工作模式

SCLK最大20Mhz

SDATA位5bit的寄存器地址+11bit的数据

寄存器配置:

        (1)并行:根据电压的改变(电阻分压的方式)来配置,可简化编程。

        (2)串行:SDATA(数据) 5bit的寄存器地址+11bit的数据

                            SCLK  (时钟)DC<TYP<20MHZ

                            SEN      (使能)        RESET(复位) 

输出方式:

        (1)SDR :只在信号的上升沿进行数据的传输

        (2)DDR:在信号的上升沿和下降沿都进行数据传输,是SDR的双倍

总结:给ADS6445芯片一个时钟,通过内部的PLL锁相环,自己会生成一个位时钟和一个时钟给FPGA,同时4通道(每个通道都有两条线即SDR、DDR可选)将数据传给FPGA

本文采用两线制、DDR的LVDS接口,帧时钟与FPGA给到ADC的时钟频率一致,位时钟是FPGA给到ADC的时钟频率的4倍,数据传输的速率位8倍的时钟频率。具体如图所示:

        从图中可以看出,在时钟变换的上升、下降沿都进行了数据的传输并且处于中间位置,两线传输的数据为16bit其中有效的为14bit。

2.PCB电路板绘制

3.SPI配置

        线性序列机的配置方式,时钟:20MHZ,SCLK工作时钟:10MHZ。

4.程序框架

如果直接采用 ADC 输出的位时钟 DCO±,帧时钟 FCO±驱动 ISERDESE2 对数据进行解串,那么由于 FPGA 内部布局布线所带来的延时,到达 ISERDESE2 相应管脚的帧时钟、位时钟与数据信号可能不再保持初始的相位关系,从而导致无法得到正确的串并转换数据,所以需要利用 SelectIO 资源使时钟与数据恢复对应的相位关系。本系统采用的 LVDS 接口模块电路框图如下图,主要由位对齐控制电路、帧同步控制电路和串并转换控制电路三个部分组成。

由上述的原理可以总结出以下三个问题:

1.因为FPGA内部走线的不同,会使得位时钟(DCO)、帧时钟(FCO)、数据到达每个转换模块ISERDESE的相位发生变化。

2.使用原语ISERDESE时本身的特点要求是DCO和FCO的时钟边沿必须是对齐的,即ISERDESE要求接口的帧、位时钟边沿对齐,而LVDS接口输出的帧、位时钟是不对齐的。

3.:使用BUFIO与BUFR后产生的clkd与clkdiv又会与原时钟有一定的延迟,导致与数据又会产生相位差,因此需要将clkd与clkdiv与原位、帧时钟对齐。

针对上述的三个问题进行解答:

        首先 ADC 输出的 LVDS 信号通过 IOB 中的差分输入缓冲器(IBUFGDS)转化为 FPGA 可以处理的信号,这时由于 IOB 靠近信号的输入端口,所以通过差分输入缓冲器后的时钟与数据之间仍保持对应的相位关系,差分位时钟转成单端时钟 bitclk,帧时钟转成差分的 fcop、fcon,差分的数据信号转成差分的 doutp、doutn。

1:单端时钟bitclk通过 FPGA 的区域时钟资源 BUFIO 和 BUFR,其中 BUFR可以根据配置得到输入时钟的分频时钟输出,并且区域时钟可以保证时钟输出到达区域内每个ISERDESE2 模块之间的延迟相似,将得到的 clkd 以及N分频的 clkdiv 作为 ISERDESE2 的驱动时钟。

        用这两个原语后的时钟可走全局时钟网络,相当于到每个ISERDESE的时间差是一样的,保证了到达每一个ISERDESE的距离是一样的。

2:因为区域时钟资源 BUFIO 和 BUFR 离 I/O 模块有一定的距离,那么 clkd、clkdiv 与源时钟之间就存在延时,无法保持初始的相位关系,从而导致解串错误,所以需要对延时进行一定的补偿。延时补偿也就是使用延时模块 IDELAYE2 对 bitclk 施加一定的延时,将延时后的时钟通过BUFIO 和 BUFR 产生 clkd 和 clkdiv,利用位对齐状态机控制 IDELAYE2 的延时量,直到 clkd,clkdiv重新对齐源时钟 bitclk。

        在此在程序中引入例化VIO模块,并通过VIO对设计进行监控,当观测到bitclk和clkd的输出数据呈现0,1跳变时,此时认为已位对齐。结果由标题6展示。

3:位对齐完成以后,虽然这时 clkd 的上升沿已经对齐了 bitclk 的上升沿或者下降沿,但是由于增加了延时,clkdiv 与帧时钟的相位是未知的,将导致数据的错位,从而无法得到正确的解串数据。此时便引入了帧同步状态机对ISERDESE进行BITSLIP原语模块操作,将数据位置调整顺序(时钟相位不变)从而实现帧同步。

        同上此时引入例化VIO模块,当观测到数据呈现11110000或00001111时表明实现了帧同步,达到了设计的要求。

        BITSILP原语:

        SDR模式:使能一次,数据左移一次,对于8bit并行数据,移动8次完成一个循环。

        DDR模式:使能一次,数据先右移一次,再左移三次,两者交替运行,同样移动8次完成一个循环。

https://img-blog.csdnimg.cn/20200612142231802.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXdlaWxpdWx1,size_16,color_FFFFFF,t_70

如果检测结果是我们想要的数据,则R_bit_slip 拉低,否则R_bit_slip拉高进行上图的移位操作。

5.具体程序(原语)

1.SPI寄存器配置

  1. always@(posedge SPI_20M or negedge rst_n)begin
  2. if(!rst_n)begin
  3. SCLK <= 1'b1;
  4. SEN <= 1'b1;
  5. SDATA <= 1'b1;
  6. spi_data <= 'd0;
  7. end
  8. else if(state_en)begin
  9. case(state_cnt)
  10. 0:begin
  11. SCLK <= 1'b1;
  12. SEN <= 1'b1;
  13. SDATA <= 1'b1;
  14. spi_data <= spi_data;
  15. end
  16. 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31:begin
  17. SCLK <= 1'b1;
  18. SEN <= 1'b0;
  19. SDATA <= spi_data[15];
  20. spi_data <= spi_data;
  21. end
  22. 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32:begin
  23. SCLK <= 1'b0;
  24. SEN <= 1'b0;
  25. SDATA <= SDATA;
  26. spi_data <= spi_data << 1;
  27. end
  28. 33:begin
  29. SCLK <= 1'b1;
  30. SEN <= 1'b1;
  31. SDATA <= 1'b1;
  32. case(data_state)
  33. 0:spi_data <= 16'b01000_0000_00000_00;//Register B 增益设置
  34. 1:spi_data <= 16'b01010_010_000_00000;//Register C 偏移二进制,正常模式16'b01010_010_000_00000/测试模式16'b01010_010_111_00000
  35. 2:spi_data <= 16'b01101_100_0001_0101;//Register F 串行模式,字节,高位在前_2Vpp,上升沿_16X,DDR
  36. default:spi_data <= spi_data;
  37. endcase
  38. end
  39. default:begin
  40. SCLK <= 1'b1;
  41. SEN <= 1'b1;
  42. SDATA <= 1'b1;
  43. spi_data <= spi_data;
  44. end
  45. endcase
  46. end
  47. else begin
  48. SCLK <= 1'b1;
  49. SEN <= 1'b1;
  50. SDATA <= 1'b1;
  51. end
  52. end

2.OBUFDS原语

OBUFDS将标准单端信号转换成差分信号,输出端口需要直接对应到顶层模块的输出信号,和IBUFDS为一对互逆操作。

  1. //FPGA给到ADC的时钟,OBUFDS:差分输出缓存器
  2. OBUFDS #(
  3. .IOSTANDARD("DEFAULT"), // Specify the output I/O standard指定输出I/O标准
  4. .SLEW("SLOW") // Specify the output slew rate指定输出转换率
  5. ) OBUFDS_inst (
  6. .O(clk_out_p), // Diff_p output (connect directly to top-level port)Diff_p输出(直接连接到顶级端口)
  7. .OB(clk_out_n), // Diff_n output (connect directly to top-level port)Diff_n输出(直接连接到顶级端口)
  8. .I(CLK_100M) // Buffer input
  9. );

3.IBUFDS原语

IBUF是输入缓存,一般vivado会自动给输入信号加上,IBUFDS是IBUF的差分形式,支持低压差分信号(如LVCMOS、LVDS等)。在IBUFDS中,一个电平接口用两个独特的电平接口(I和IB)表示。一个可以认为是主信号,另一个可以认为是从信号。主信号和从信号是同一个逻辑信号,但是相位相反。

  1. //差分转单端
  2. IBUFDS #(
  3. .DIFF_TERM("TRUE"), // Differential Termination
  4. .IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
  5. .IOSTANDARD("DEFAULT") // Specify the input I/O standard
  6. ) IBUFDS_DCO (
  7. .O(W0_dc_clk), // Buffer output
  8. .I(DCO_p), // Diff_p buffer input (connect directly to top-level port)
  9. .IB(DCO_n) // Diff_n buffer input (connect directly to top-level port)
  10. );

4. IDELAYE2原语,IDELAYCTRL原语

(1)IDELAYE2 原语:

        每个I/O都包含一个IDELAYE2的可编程的原语。IDELAY可以连接到后续的模块。IDLEAYE2可以根据抽头系数来调整延时。这个抽头系数对应的最小分辨率可以根据7系列的手册上来看。

(2)IDELAYCTRL原语:

一般都是配合着I/ODELAY原语来使用的。如果使用了IDELAYE2或者ODELAYE2原语,那么IDELAYCTRL原语必须被例化。IDLAYCTRL使用用户提供的REFCLK来校准IDELAY和ODELAY。也就是前面说的,具体的延时的值,是根据输入到IDELAYCTRL的参考时钟来确定的。

  1. (* IODELAY_GROUP = "delay1" *)
  2. IDELAYCTRL IDELAYCTRL_DCO (
  3. .RDY(W_delay_rdy), // 1-bit output: Ready output
  4. .REFCLK(REF_CLK_200M), // 1-bit input: Reference clock input
  5. .RST(~rst_n) // 1-bit input: Active high reset input
  6. );
  7. (* IODELAY_GROUP = "delay1" *)
  8. IDELAYE2 #(
  9. .CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE)
  10. .DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN)
  11. .HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
  12. .IDELAY_TYPE("VAR_LOAD"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
  13. .IDELAY_VALUE(0), // Input delay tap setting (0-31)
  14. .PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE
  15. .REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
  16. .SIGNAL_PATTERN("CLOCK") // DATA, CLOCK input signal
  17. )
  18. IDELAYE2_DCO (
  19. .CNTVALUEOUT(), // 5-bit output: Counter value output
  20. .DATAOUT(W1_dc_clk), // 1-bit output: Delayed data output
  21. .C(W_fc_clk), // 1-bit input: Clock input
  22. .CE(1'b0), // 1-bit input: Active high enable increment/decrement input
  23. .CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input
  24. .CNTVALUEIN('d11), // 5-bit input: Counter value input
  25. .DATAIN(1'b0), // 1-bit input: Internal delay data input
  26. .IDATAIN(W0_dc_clk), // 1-bit input: Data input from the I/O
  27. .INC(1'b0), // 1-bit input: Increment / Decrement tap delay input
  28. .LD(1'b1), // 1-bit input: Load IDELAY_VALUE input
  29. .LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input
  30. .REGRST(1'b0) // 1-bit input: Active-high reset tap-delay input
  31. );

5.BUFIO原语

        本地IO时钟缓冲器.使用独立于全局时钟网络的专用时钟网络来驱动纵向IO管脚。非常适合同步数据采集;BUFIO要求时钟和相应的IO必须在同一时钟区域,而不同的时钟网络的驱动需要BUFR原语来实现.由于BUFIO引出的时钟只到达了IO列,所以不能来驱动逻辑资源,比如CLB和BRAM.

  1. BUFIO BUFIO_DCO (
  2. .O(W_dc_clk), // 1-bit output: Clock output (connect to I/O clock loads).
  3. .I(W2_dc_clk) // 1-bit input: Clock input (connect to an IBUF or BUFMR).
  4. );

6.BUFR原语

         本地IO时钟逻辑缓冲器.与BUFIO一样是将驱动时钟引入某一时钟区域的专用时钟网络,而独立于全局时钟网络;不同的是,BUFR不仅可以跨越不同的时钟区域(最多3个),还能够驱动IO逻辑以及自身或邻近时钟区域的逻辑资源.BUFIO的输出和本地内部互联都能驱动BUFR组件.此外,BUFR能完成输入时钟1—8的整数分频.因些BUFR是同步设计中实现跨时钟域以及串并转换的最佳方案.

  1. BUFR #(
  2. .BUFR_DIVIDE("4"), // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8" 分频
  3. .SIM_DEVICE("7SERIES")// Must be set to "7SERIES"
  4. )
  5. BUFR_DCO (
  6. .O(W_fc_clk), // 1-bit output: Clock output port
  7. .CE(1'b1), // 1-bit input: Active high, clock enable (Divided modes only)
  8. .CLR(1'b0), // 1-bit input: Active high, asynchronous clear (Divided modes only)
  9. .I(W2_dc_clk) // 1-bit input: Clock buffer input driven by an IBUF, MMCM or local interconnect
  10. );

7.ISERDESE2原语

      ISERDESE2是FPGA的一个专用的串并联转换器,具有特定的时钟和逻辑特性,旨在促进高速源同步应用的实现。iserdes2避免了在FPGA结构中设计反序列化器时遇到的额外时序复杂性。其具有以下应用:
(1)专用解串器/串并转换器:
  该转换器支持单数据速率(SDR)和双数据速率(DDR)模式。在SDR模式下,串并联转换器创建一个2-、3-、4-、5-、6-、7-或8位宽并行字。在DDR模式下,当使用一个ISERDESE2时,串并联转换器创建4、6、8位宽的并行字模式,当使用两个级联时创建10或14位宽的并行字模式
(2)Bitslip 子模块:
  Bitslip子模块允许设计人员重新排列进入FPGA结构的并行数据流的序列。这可以用于训练包含训练模式的源同步接口。
(3)专用内存接口
  ISERDESE2包含专用电路(包括OCLK输入引脚),在ISERDESE2块中完全处理频闪到fpga的时钟域交叉,更利于提高性能和简化设计。
(4)支持网络接口、DDR3接口、QDR接口、异步接口。

  1. ISERDESE2 #(
  2. .DATA_RATE("SDR"), // DDR, SDR
  3. .DATA_WIDTH(8), // Parallel data width (2-8,10,14)
  4. .DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
  5. .DYN_CLK_INV_EN("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
  6. .INIT_Q1(1'b0),
  7. .INIT_Q2(1'b0),
  8. .INIT_Q3(1'b0),
  9. .INIT_Q4(1'b0),
  10. .INTERFACE_TYPE("NETWORKING"),// MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
  11. .IOBDELAY("IBUF"), // NONE, BOTH, IBUF, IFD
  12. .NUM_CE(2), // Number of clock enables (1,2)
  13. .OFB_USED("FALSE"), // Select OFB path (FALSE, TRUE)
  14. .SERDES_MODE("MASTER"), // MASTER, SLAVE
  15. .SRVAL_Q1(1'b0),
  16. .SRVAL_Q2(1'b0),
  17. .SRVAL_Q3(1'b0),
  18. .SRVAL_Q4(1'b0)
  19. )
  20. ISERDESE2_DCO (
  21. .O(W2_dc_clk), // 1-bit output: Combinatorial output
  22. .Q1(W_allign_word[0]), // Q1 - Q8: 1-bit (each) output: Registered data outputs
  23. .Q2(W_allign_word[1]),
  24. .Q3(W_allign_word[2]),
  25. .Q4(W_allign_word[3]),
  26. .Q5(W_allign_word[4]),
  27. .Q6(W_allign_word[5]),
  28. .Q7(W_allign_word[6]),
  29. .Q8(W_allign_word[7]),
  30. .SHIFTOUT1(),
  31. .SHIFTOUT2(),
  32. .BITSLIP(),
  33. .CE1(1'b1),
  34. .CE2(1'b1),
  35. .CLKDIVP(1'b0), // 1-bit input: TBD
  36. .CLK(W_dc_clk), // 1-bit input: High-speed clock
  37. .CLKB(~W_dc_clk), // 1-bit input: High-speed secondary clock
  38. .CLKDIV(W_fc_clk), // 1-bit input: Divided clock
  39. .OCLK(1'b0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
  40. .DYNCLKDIVSEL(1'b0), // 1-bit input: Dynamic CLKDIV inversion
  41. .DYNCLKSEL(1'b0), // 1-bit input: Dynamic CLK/CLKB inversion
  42. .D(W0_dc_clk), // 1-bit input: Data input
  43. .DDLY(W1_dc_clk), // 1-bit input: Serial data from IDELAYE2
  44. .OFB(1'b0), // 1-bit input: Data feedback from OSERDESE2
  45. .OCLKB(1'b0), // 1-bit input: High speed negative edge output clock
  46. .RST(~rst_n), // 1-bit input: Active high asynchronous reset
  47. .SHIFTIN1(1'b0),
  48. .SHIFTIN2(1'b0)
  49. );

6.测试结果

例化vio模块监控是否位对齐和输出数据达到了设计的要求,结果观测到bitclk和clkd的输出数据呈现0,1跳变,此时已位对齐,同时输出数据呈现11110000的结果:

最终只选择分别采集两路信号,分别为A、D通道和B、C通道

实物如下图所示:

参考博客:

Xilinx FPGA原语总结_obufds原语-CSDN博客

FPGA内部资源(Xilinx) ---- IDELAY(延时)-CSDN博客

xilinx原语使用文献_bufr原语-CSDN博客

Xilinx ISERDESE2应用笔记及仿真实操-CSDN博客

小白也是刚接触该设计,有些地方理解错误,可能有偏差,向大佬们请教!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/907453
推荐阅读
相关标签
  

闽ICP备14008679号