欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Xilinx中oserdes的原语及IP的使用

程序员文章站 2024-02-23 16:09:34
...

应用场景

在高速应用中,我们经常性的听说serdes的应用,确实serdes是一项重要的应用。serdes又可以分为iserdes与oserdes两个操作分别是串行转并行以及并行转串行,因为FPGA内部跑的频率较低,不能处理那么高的串行频率需要转成并行处理。举两个serdes的例子以供大家明白它的作用:
1、HDMI中的发射端用到了Oserdes接收端用到了Iserdes,因为HDMI是数字串行通信
2、在GTP的应用中,如PCIE、SFP都用到了serdes操作
我们下篇文章会讲解HDMI应用。知道了serdes的作用,那么学习起来这个操作才有意义。

serdes原语的应用

首先从vivado中调出oserdes原语如下
Xilinx中oserdes的原语及IP的使用
接下来对其接口信号进行描述:

 OSERDESE2 #(
    .DATA_RATE_OQ               ("DDR"                  ),   // DDR, SDR
    .DATA_RATE_TQ               ("DDR"                  ),   // DDR, BUF, SDR
    .DATA_WIDTH                 (4                      ),         // Parallel data width (2-8,10,14)
    .INIT_OQ                    (1'b0                   ),         // Initial value of OQ output (1'b0,1'b1)
    .INIT_TQ                    (1'b0                   ),         // Initial value of TQ output (1'b0,1'b1)
    .SERDES_MODE                ("MASTER"               ), // MASTER, SLAVE
    .SRVAL_OQ                   (1'b0                   ),        // OQ output value when SR is used (1'b0,1'b1)
    .SRVAL_TQ                   (1'b0                   ),        // TQ output value when SR is used (1'b0,1'b1)
    .TBYTE_CTL                  ("FALSE"                ),    // Enable tristate byte operation (FALSE, TRUE)
    .TBYTE_SRC                  ("FALSE"                ),    // Tristate byte source (FALSE, TRUE)
    .TRISTATE_WIDTH             (4                      )      // 3-state converter width (1,4)
   )
   OSERDESE2_inst (
      .OFB                      (OFB                    ),             // 1-bit output: Feedback path for data
      .OQ                       (OQ                     ),               // 1-bit output: Data path output
      // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
      .SHIFTOUT1                (SHIFTOUT1              ),
      .SHIFTOUT2                (SHIFTOUT2              ),
      .TBYTEOUT                 (TBYTEOUT               ),   // 1-bit output: Byte group tristate
      .TFB                      (TFB                    ),             // 1-bit output: 3-state control
      .TQ                       (TQ                     ),               // 1-bit output: 3-state control
      .CLK                      (CLK                    ),             // 1-bit input: High speed clock
      .CLKDIV                   (CLKDIV                 ),       // 1-bit input: Divided clock
      // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
      .D1                       (D1                     ),
      .D2                       (D2                     ),
      .D3                       (D3                     ),
      .D4                       (D4                     ),
      .D5                       (D5                     ),
      .D6                       (D6                     ),
      .D7                       (D7                     ),
      .D8                       (D8                     ),
      .OCE                      (OCE                    ),             // 1-bit input: Output data clock enable
      .RST                      (RST                    ),             // 1-bit input: Reset
      // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
      .SHIFTIN1                 (SHIFTIN1               ),
      .SHIFTIN2                 (SHIFTIN2               ),
      // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
      .T1                       (T1                     ),
      .T2                       (T2                     ),
      .T3                       (T3                     ),
      .T4                       (T4                     ),
      .TBYTEIN                  (TBYTEIN                ),     // 1-bit input: Byte group tristate
      .TCE                      (TCE                    )              // 1-bit input: 3-state clock enable
   );

   // End of OSERDESE2_inst instantiation
                    

1、DATA_RATE_OQ:数据模式,DDR代表上升沿和下降沿都发送数据,SDR代表只在上升沿发送数据
2、DATA_RATE_TQ:三态门模式,同上,这里我们不关注三态状态,所有与三态设置相关的信号输入设置成0,输出不关心。
3、INIT_OQ:初始化数据输出端初始值
4、SERDES_MODE:串行的模式,在10,14串行通信的时候用到,如下图:
Xilinx中oserdes的原语及IP的使用
用到两个serdes,上面的选择Master下面的选择Slave
5、SRVAL_OQ:复位时输出电平的状态
6、OFB:反馈输出,这里不关心即可
7、OQ:输出信号
8、SHIFTOUT1:serdes串联时送给上一个serdes用到的信号
9、SHIFTOUT2:serdes串联时送给上一个serdes用到的信号
10、CLK:串行块时钟,在HDMI中是CLKDIV的5倍
11、CLKDIV:并行数据的随路时钟
12、DX:并行输入数据
13、OCE:模块使能信号,默认为1使能
14、RST:模块复位信号,默认为1复位
15、SHIFTIN1:serdes串联时送接收下一个serdes用到的信号
16、SHIFTIN2:serdes串联时送接收下一个serdes用到的信号
我们这里使用典型的10bit数据转串行数据发送。

serdes原语的使用示例

这里将以10bit转成串行输出为例给出相应的代码,注意原语中TRISTATE_WIDTH设置为1,因为手册中的说明如下:
Xilinx中oserdes的原语及IP的使用
所以代码如下:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : aaa@qq.com
// Website      : 
// Module Name  : par2ser.v
// Create Time  : 2020-02-23 14:20:43
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************


module par2ser(
    input                   clk_1x          ,
    input                   clk_5x          ,
    input                   rst_n           ,
    input           [ 9:0]  par_data        ,

    output  wire            ser_data_p      ,
    output  wire            ser_data_n  
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
wire                        shiftout1       ;
wire                        shiftout2       ;
wire                        ser_data        ;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/

OBUFDS #(
    .IOSTANDARD                 ("DEFAULT"              ), // Specify the output I/O standard
    .SLEW                       ("SLOW"                 )           // Specify the output slew rate
) OBUFDS_inst (
    .O                          (ser_data_p             ),     // Diff_p output (connect directly to top-level port)
    .OB                         (ser_data_n             ),   // Diff_n output (connect directly to top-level port)
    .I                          (ser_data               )      // Buffer input
   );

 OSERDESE2 #(
    .DATA_RATE_OQ               ("DDR"                  ),   // DDR, SDR
    .DATA_RATE_TQ               ("DDR"                  ),   // DDR, BUF, SDR
    .DATA_WIDTH                 (10                     ),         // Parallel data width (2-8,10,14)
    .INIT_OQ                    (1'b0                   ),         // Initial value of OQ output (1'b0,1'b1)
    .INIT_TQ                    (1'b0                   ),         // Initial value of TQ output (1'b0,1'b1)
    .SERDES_MODE                ("MASTER"               ), // MASTER, SLAVE
    .SRVAL_OQ                   (1'b0                   ),        // OQ output value when SR is used (1'b0,1'b1)
    .SRVAL_TQ                   (1'b0                   ),        // TQ output value when SR is used (1'b0,1'b1)
    .TBYTE_CTL                  ("FALSE"                ),    // Enable tristate byte operation (FALSE, TRUE)
    .TBYTE_SRC                  ("FALSE"                ),    // Tristate byte source (FALSE, TRUE)
    .TRISTATE_WIDTH             (1                      )      // 3-state converter width (1,4)
   ) OSERDESE2_inst_master (
      .OFB                      (                       ),             // 1-bit output: Feedback path for data
      .OQ                       (ser_data               ),               // 1-bit output: Data path output
      // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
      .SHIFTOUT1                (                       ),
      .SHIFTOUT2                (                       ),
      .TBYTEOUT                 (                       ),   // 1-bit output: Byte group tristate
      .TFB                      (                       ),             // 1-bit output: 3-state control
      .TQ                       (                       ),               // 1-bit output: 3-state control
      .CLK                      (clk_5x                 ),             // 1-bit input: High speed clock
      .CLKDIV                   (clk_1x                 ),       // 1-bit input: Divided clock
      // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
      .D1                       (par_data[0]            ),
      .D2                       (par_data[1]            ),
      .D3                       (par_data[2]            ),
      .D4                       (par_data[3]            ),
      .D5                       (par_data[4]            ),
      .D6                       (par_data[5]            ),
      .D7                       (par_data[6]            ),
      .D8                       (par_data[7]            ),
      .OCE                      (1'b1                   ),             // 1-bit input: Output data clock enable
      .RST                      (~rst_n                 ),             // 1-bit input: Reset
      // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
      .SHIFTIN1                 (shiftout1              ),
      .SHIFTIN2                 (shiftout2              ),
      // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
      .T1                       (1'b0                   ),
      .T2                       (1'b0                   ),
      .T3                       (1'b0                   ),
      .T4                       (1'b0                   ),
      .TBYTEIN                  (1'b0                   ),     // 1-bit input: Byte group tristate
      .TCE                      (1'b0                   )              // 1-bit input: 3-state clock enable
   );

   // End of OSERDESE2_inst instantiation
 OSERDESE2 #(
    .DATA_RATE_OQ               ("DDR"                  ),   // DDR, SDR
    .DATA_RATE_TQ               ("DDR"                  ),   // DDR, BUF, SDR
    .DATA_WIDTH                 (10                     ),         // Parallel data width (2-8,10,14)
    .INIT_OQ                    (1'b0                   ),         // Initial value of OQ output (1'b0,1'b1)
    .INIT_TQ                    (1'b0                   ),         // Initial value of TQ output (1'b0,1'b1)
    .SERDES_MODE                ("SLAVE"               ), // MASTER, SLAVE
    .SRVAL_OQ                   (1'b0                   ),        // OQ output value when SR is used (1'b0,1'b1)
    .SRVAL_TQ                   (1'b0                   ),        // TQ output value when SR is used (1'b0,1'b1)
    .TBYTE_CTL                  ("FALSE"                ),    // Enable tristate byte operation (FALSE, TRUE)
    .TBYTE_SRC                  ("FALSE"                ),    // Tristate byte source (FALSE, TRUE)
    .TRISTATE_WIDTH             (1                      )      // 3-state converter width (1,4)
   ) OSERDESE2_inst_slave (
      .OFB                      (                       ),             // 1-bit output: Feedback path for data
      .OQ                       (                       ),               // 1-bit output: Data path output
      // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
      .SHIFTOUT1                (shiftout1              ),
      .SHIFTOUT2                (shiftout2              ),
      .TBYTEOUT                 (                       ),   // 1-bit output: Byte group tristate
      .TFB                      (                       ),             // 1-bit output: 3-state control
      .TQ                       (                       ),               // 1-bit output: 3-state control
      .CLK                      (clk_5x                 ),             // 1-bit input: High speed clock
      .CLKDIV                   (clk_1x                 ),       // 1-bit input: Divided clock
      // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
      .D1                       (                       ),
      .D2                       (                       ),
      .D3                       (par_data[8]            ),
      .D4                       (par_data[9]            ),
      .D5                       (                       ),
      .D6                       (                       ),
      .D7                       (                       ),
      .D8                       (                       ),
      .OCE                      (1'b1                   ),             // 1-bit input: Output data clock enable
      .RST                      (~rst_n                 ),             // 1-bit input: Reset
      // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
      .SHIFTIN1                 (                       ),
      .SHIFTIN2                 (                       ),
      // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
      .T1                       (1'b0                   ),
      .T2                       (1'b0                   ),
      .T3                       (1'b0                   ),
      .T4                       (1'b0                   ),
      .TBYTEIN                  (1'b0                   ),     // 1-bit input: Byte group tristate
      .TCE                      (1'b0                   )              // 1-bit input: 3-state clock enable
   );                    




endmodule

serdes原语的测试代码

`timescale 1ns / 1ps
`define     CLOCK        20
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/02/23 14:23:39
// Design Name: 
// Module Name: tb_par2ser
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_par2ser;
reg                        clk_1x          ;
reg                        clk_5x          ;
reg                        rst_n           ;
reg                [ 9:0]  par_data        ;
wire                       ser_data_p      ;
wire                       ser_data_n      ;

initial begin
    clk_1x          =       1'b0;
    clk_5x          =       1'b0;
    rst_n           <=      1'b0;
    #(100*`CLOCK)
    rst_n           <=      1'b1;
end
always #(`CLOCK/2)      clk_1x          =           ~clk_1x;
always #(`CLOCK/8)      clk_5x          =           ~clk_5x;

always @(posedge clk_1x or negedge rst_n)
    if(rst_n == 1'b0)
        par_data            <=          10'b11_1111_1111;
    else 
        par_data            <=          par_data - 1'b1; 



par2ser par2ser_inst(
    .clk_1x                 (clk_1x                 ),
    .clk_5x                 (clk_5x                 ),
    .rst_n                  (rst_n                  ),
    .par_data               (par_data               ),

    .ser_data_p             (ser_data_p             ),
    .ser_data_n             (ser_data_n             )
);
endmodule

仿真代码没有任何难度,看一下便明白原理。

serdes原语的仿真结果

Xilinx中oserdes的原语及IP的使用
从上面图形中我们可以验证我们oserdes程序的正确性。

select_io的使用

上面的原语或许不是那么容易理解,那么我们同样完成上面的功能,通过使用IP来完成,该IP的名字叫做select_io,在vivado中调用对应的IP,如下
Xilinx中oserdes的原语及IP的使用
首先的界面设置如下:
Xilinx中oserdes的原语及IP的使用
第二个界面设置如下:
Xilinx中oserdes的原语及IP的使用
第三个默认即可
Xilinx中oserdes的原语及IP的使用
从上面的设置中我们可以发现是与原语的参数设置一致的。

select_io的测试代码

测试代码如下:

`timescale 1ns / 1ps
`define     CLOCK        20
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/02/23 15:39:03
// Design Name: 
// Module Name: tb_select_io
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_select_io;
reg                        clk_1x          ;
reg                        clk_5x          ;
reg                        rst_n           ;
reg                [ 9:0]  par_data        ;
wire                       ser_data_p      ;
wire                       ser_data_n      ;
initial begin
    clk_1x          =       1'b0;
    clk_5x          =       1'b0;
    rst_n           <=      1'b0;
    #(100*`CLOCK)
    rst_n           <=      1'b1;
end
always #(`CLOCK/2)      clk_1x          =           ~clk_1x;
always #(`CLOCK/8)      clk_5x          =           ~clk_5x;
always @(posedge clk_1x or negedge rst_n)
    if(rst_n == 1'b0)
        par_data            <=          10'b11_1111_1111;
    else 
        par_data            <=          par_data - 1'b1; 

selectio_wiz_0 selectio_wiz_0_inst
 (
   .data_out_from_device            (par_data                       ), // input [9:0] data_out_from_device
   .data_out_to_pins_p              (ser_data_p                     ), // output [0:0] data_out_to_pins_p
   .data_out_to_pins_n              (ser_data_n                     ), // output [0:0] data_out_to_pins_n
   .clk_in                          (clk_5x                         ), // input clk_in                            
   .clk_div_in                      (clk_1x                         ), // input clk_div_in                        
   .io_reset                        (~rst_n                         ) // input io_reset
); 

endmodule

测试结果

Xilinx中oserdes的原语及IP的使用
从测试结果上看,IP与原语的作用相同。

总结

创作不易,认为文章有帮助的同学们可以关注点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
Xilinx中oserdes的原语及IP的使用