Xilinx 7系列SERDES应用

来源:互联网 发布:免费源码分享网站 编辑:程序博客网 时间:2024/05/16 10:24

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 / 1psmodule 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
原创粉丝点击