Xilinx 7系列SERDES应用

SERDES是英文SERializer(串行器)/DESerializer(解串器)的简称。它是一种主流的时分多路复用(TDM)、点对点(P2P)的串行通信技术。即在发送端多路低速并行信号被转换成高速串行信号,经过传输媒体(光缆或铜线),最后在接收端高速串行信号重新转换成低速并行信号。这种点对点的串行通信技术充分利用传输媒体的信道容量,减少所需的传输信道和器件引脚数目,提升信号的传输速度,从而大大降低通信成本。xilinx 7系列通过原语调用serdes接口,就可以实现串并(并串)转化的应用。
平台:AT7 Xilinx USB3.0+LVDS+FPGA开发板
语言:SystemVerilog
功能:20M时钟产生8位的数据经serdes串化,由一对LVDS输出,再由另一对LVDS接收,经serdes解串恢复8bit的数据。
这里,在特权的LVDS测试例程上简化,只用调用原语serdes验证数据的传输(说实话,特权同学的例程代码,确实有点凌乱,前后看了两天。可能是对这些其中用到的原语不熟吧)

`timescale 1ns / 1ps

module srdes_test(
        //外部输入时钟和复位接口
        input logic             sys_clk_i,
        input logic             ext_rst_n,    //复位信号,低电平有效
        //LED指示灯接口
        output logic [7:0]      led,    //用于测试的LED指示灯
        //LVDS发送接口
        output logic [1:0]      lvds_txdb_p,
        output logic [1:0]      lvds_txdb_n, //数据
//        output logic            lvds_txclk_p,   
//        output logic            lvds_txclk_n,    //时钟            
        //LVDS接收接口
        input logic [1:0]       lvds_rxdb_p,
        input logic [1:0]       lvds_rxdb_n    //数据
//        input logic             lvds_rxclk_p,
//        input logic             lvds_rxclk_n    //时钟    
    );
    //led 输出
    assign led = 8'hFF;
    wire tx_1 = '0;
    OBUFDS io_lvds_out(
                    .O( lvds_txdb_p[1] ),
                    .OB( lvds_txdb_n[1] ),
                    .I( tx_1 )  );
    localparam DATA_CHECK = 8'hD0; //8'b1101_0000
    /***************************************************************
    * 1,时钟
    ***************************************************************/
    wire sys_rst;
    wire  clk_20M_OUT,clk_160M_OUT,clk_200M_OUT;
     clk_pll20M instance_name
     (
      // Clock out ports
      .clk_20M_OUT(clk_20M_OUT),     // output clk_20M_OUT
      .clk_160M_OUT(clk_160M_OUT),     // output clk_160M_OUT
      .clk_200M_OUT(clk_200M_OUT),     // output clk_200M_OUT
      // Status and control signals
      .reset( !ext_rst_n ), // input reset
      .locked( !sys_rst ),       // output locked
     // Clock in ports
      .clk_50M_IN( sys_clk_i ));      // input clk_50M_IN

    /***************************************************************
    * 2,发送
    ***************************************************************/  
    //数据产生
    logic [7:0] data_out;
    data_gen_module #(
        .DATA_WIDTH(8)    
    )Udata_gen (
        .clk( clk_20M_OUT ),
        .en( !sys_rst ),
        .dout( data_out )
    );   
    logic check;   
    wire [7:0] data_tx = check ? DATA_CHECK:data_out;
    wire        tx_data_out;

    OSERDESE2 #(
        .DATA_WIDTH         (8),             // SERDES word width
        .TRISTATE_WIDTH     (1), 
        .DATA_RATE_OQ       ("SDR"),         // <SDR>, DDR
        .DATA_RATE_TQ       ("SDR"),         // <SDR>, DDR
        .SERDES_MODE        ("MASTER"))      // <DEFAULT>, MASTER, SLAVE
    oserdes_m (
        .OQ               (tx_data_out),
        .OCE             ( 1'b1 ),
        .CLK             ( clk_160M_OUT ),
        .RST             ( sys_rst ),
        .CLKDIV          ( clk_20M_OUT ),
        .D8              (data_tx[7]),
        .D7              (data_tx[6]),
        .D6              (data_tx[5]),
        .D5              (data_tx[4]),
        .D4              (data_tx[3]),
        .D3              (data_tx[2]),
        .D2              (data_tx[1]),
        .D1              (data_tx[0]),
        .TQ              (),
        .T1              (1'b0),
        .T2              (1'b0),
        .T3              (1'b0),
        .T4              (1'b0),
        .TCE             (1'b1),
        .TBYTEIN         (1'b0),
        .TBYTEOUT        (),
        .OFB             (),
        .TFB             (),
        .SHIFTOUT1       (),            
        .SHIFTOUT2       (),            
        .SHIFTIN1        (1'b0),    
        .SHIFTIN2        (1'b0)) ;

    OBUFDS io_data_out(
                    .O( lvds_txdb_p[0] ),
                    .OB( lvds_txdb_n[0] ),
                    .I( tx_data_out )  );  

    /***************************************************************
    * 3,接收
    ***************************************************************/
    wire delay_ready;
    IDELAYCTRL  icontrol (                          
    // Instantiate input delay control block
                 .REFCLK ( clk_200M_OUT ),
                 .RST    ( sys_rst ),
                 .RDY    (delay_ready) );

    wire bslip;  
    wire [7:0] bslip_din;           
    lvds_bitslip#(
           .PATTERN_A(8'hD0)
       )Ubitslip(
           .clk_d( clk_20M_OUT ),  // lvds 数据时钟20M
           .rst_n( 1'b1 ), 
           .din( bslip_din),   
           .bitslip( bslip )
       );  
    wire data_in;
    IBUFDS #(
         .DIFF_TERM("TRUE"),       // Differential Termination
         .IBUF_LOW_PWR("FALSE"),     // Low power="TRUE", Highest performance="FALSE" 
         .IOSTANDARD("DEFAULT")     // Specify the input I/O standard
      ) IBUFDS_inst (
         .O( data_in ),  // Buffer output
         .I( lvds_rxdb_p[0] ),    // Diff_p buffer input (connect directly to top-level port)
         .IB( lvds_rxdb_n[0] )    // Diff_n buffer input (connect directly to top-level port)
      );
    wire data_ind; 
    logic [4:0] delay2_val;  
    IDELAYE2 #(
         .CINVCTRL_SEL("FALSE"),          // Enable dynamic clock inversion (FALSE, TRUE)
         .DELAY_SRC("IDATAIN"),           // Delay input (IDATAIN, DATAIN)
         .HIGH_PERFORMANCE_MODE("FALSE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
         .IDELAY_TYPE("VAR_LOAD"),           // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
         .IDELAY_VALUE(0),                // Input delay tap setting (0-31)
         .PIPE_SEL("FALSE"),              // Select pipelined mode, FALSE, TRUE
         .REFCLK_FREQUENCY(200.0),        // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
         .SIGNAL_PATTERN("DATA")          // DATA, CLOCK input signal
      )
       idelay_d(
         .CNTVALUEOUT( ), // 5-bit output: Counter value output
         .DATAOUT( data_ind ),         // 1-bit output: Delayed data output
         .C( clk_20M_OUT ),                     // 1-bit input: Clock input
         .CE( 1'b0 ),                   // 1-bit input: Active high enable increment/decrement input
         .CINVCTRL(  ),       // 1-bit input: Dynamic clock inversion input
         .CNTVALUEIN( delay2_val ),   // 5-bit input: Counter value input
         .DATAIN( 1'b0 ),           // 1-bit input: Internal delay data input
         .IDATAIN( data_in),         // 1-bit input: Data input from the I/O
         .INC( 1'b0 ),                 // 1-bit input: Increment / Decrement tap delay input
         .LD( 1'b1 ),                   // 1-bit input: Load IDELAY_VALUE input
         .LDPIPEEN( 1'b0 ),       // 1-bit input: Enable PIPELINE register to load data input
         .REGRST  ( 1'b0 )            // 1-bit input: Active-high reset tap-delay input
      );

    logic [7:0] data_rx;
        ISERDESE2 #(
           .DATA_WIDTH          (8),                 
           .DATA_RATE           ("SDR"),             
       //    .SERDES_MODE        ("MASTER"),             
           .IOBDELAY            ("IFD"),             
           .INTERFACE_TYPE      ("NETWORKING"))
        iserdes_rx (
           .O ( ),                       // 1-bit output: Combinatorial output
           // Q1 - Q8: 1-bit (each) output: Registered data outputs
           .Q1(data_rx[7]),
           .Q2(data_rx[6]),
           .Q3(data_rx[5]),
           .Q4(data_rx[4]),
           .Q5(data_rx[3]),
           .Q6(data_rx[2]),
           .Q7(data_rx[1]),
           .Q8(data_rx[0]),
           // SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
           .SHIFTOUT1( ),
           .SHIFTOUT2( ),
           .BITSLIP(bslip),           

           // CE1, CE2: 1-bit (each) input: Data register clock enable inputs
           .CE1( 1'b1 ),
           .CE2( 1'b1 ),
           .CLKDIVP( 1'b0 ),           // 1-bit input: TBD
           // Clocks: 1-bit (each) input: ISERDESE2 clock input ports
           .CLK( clk_160M_OUT ),                   // 1-bit input: High-speed clock
           .CLKB(~clk_160M_OUT),                 // 1-bit input: High-speed secondary clock
           .CLKDIV( clk_20M_OUT ),             // 1-bit input: Divided clock
           .OCLK( 1'b0 ),                 // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY" 
           // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
           .DYNCLKDIVSEL( 1'b0 ), // 1-bit input: Dynamic CLKDIV inversion
           .DYNCLKSEL( 1'b0 ),       // 1-bit input: Dynamic CLK/CLKB inversion
           // Input Data: 1-bit (each) input: ISERDESE2 data input ports
           .D( 1'b0 ),                       // 1-bit input: Data input
           .DDLY( data_ind ),                 // 1-bit input: Serial data from IDELAYE2

           .OCLKB( 1'b0 ),               // 1-bit input: High speed negative edge output clock
           .RST( 1'b0 ),                   // 1-bit input: Active high asynchronous reset
           // SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
           .SHIFTIN1( 1'b0 ),
           .SHIFTIN2( 1'b0 )
        );  
      assign bslip_din =  data_rx;                       
    /***************************************************************
    * 4,监测
    ***************************************************************/      

     vio_1 Uvio_1 (
         .clk( clk_20M_OUT ),                // input wire clk
         .probe_out0( {delay2_val} )         // output wire [9 : 0] probe_out0
       );
    ila_0 Uila_0 (
         .clk(clk_160M_OUT), // input wire clk

         .probe0( data_tx ), // input wire [15:0]  probe0  
         .probe1( data_rx ), // input wire [15:0]  probe1 
         .probe2(bslip) // input wire [1:0]  probe2
        ); 
    vio_0 Uvio_0 (
          .clk( clk_20M_OUT ),                // input wire clk
          .probe_in0( check ),      // input wire [0 : 0] probe_in0
          .probe_out0( check )       // output wire [0 : 0] probe_out0
        ); 

endmodule
  • 6
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Xilinx Spartan-6 FPGA SERDES应用指南是一份详细介绍了如何在Spartan-6 FPGA上使用SERDES(串行器和反串行器)以实现高速数据传输的指南。该指南提供了有关配置和使用SERDES的详细说明,以及一些实际应用案例。 在Spartan-6 FPGA系列中,SERDES被广泛用于高速接口的实现,例如PCI Express(PCIe)、SATA、Ethernet等。这些接口通常需要在芯片之间传输大量数据,而SERDES技术则可以将并行数据转换为串行数据进行传输,从而提供更高的数据传输速率。 该指南首先介绍了Spartan-6 FPGA系列中SERDES的架构和工作原理。它解释了SERDES的主要组成部分,如发送器、接收器、时钟恢复单元和多路复用器等,并说明了它们在数据传输中的作用。 然后,该指南详细介绍了如何使用Xilinx的ISE设计工具对SERDES进行配置和实现。它提供了配置SERDES所需的主要参数和选项,并演示了如何将SERDES集成到设计中以实现各种高速接口。 此外,该指南还列举了一些实际应用案例,包括PCIe接口、SATA接口和Gigabit Ethernet接口等。对于每个应用案例,它提供了详细的步骤和配置说明,并解释了如何进行时序约束和性能优化。 总的来说,Xilinx Spartan-6 FPGA SERDES应用指南是一份非常有用的文档,为使用Spartan-6 FPGA实现高速数据传输的工程师提供了必要的指导和帮助。无论是初学者还是有经验的用户,都可以从中获取关于SERDES技术的深入理解,并加快设计开发的步伐。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值