Xilinx LVDS Output——原语调用
根据上一篇Xilinx LVDS Output——OSERDESE2说的内容,先例化出OSEREDSE2
模块;
Primitive 调用
调
Vivado
提供了相关的原语程序模板,可以直接调用,按照如下步骤:
先打开语言模板:
选择相应的原语文档:
完整文档如下(务必仔细阅读注释):
// OSERDESE2 : In order to incorporate this function into the design,
// Verilog : the following instance declaration needs to be placed
// instance : in the body of the design code. The instance name
// declaration : (OSERDESE2_inst) and/or the port declarations within the
// code : parenthesis may be changed to properly reference and
// : connect this function to the design. All inputs
// : and outputs must be connected.// <-----Cut code below this line---->// OSERDESE2: Output SERial/DESerializer with bitslip// Kintex-7// Xilinx HDL Language Template, version 2018.3OSERDESE2 #(.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
用
属性
如果使用的是DDR
的方式,属性部分不用改动;如果使用SDR
的方式,就将对应属性修改,其余默认:
- 参数
DATA_WIDTH
修改为为需要使用的串解因子,这里修改为8
; - 参数
DATA_RATE_OQ
修改为SDR
; - 参数
DATA_RATE_TQ
修改为SDR
; - 参数
TRISTATE_WIDTH
修改为1
;
Port
端口部分需要根据使用进行修改:
OQ
连接到输出数据;CLK
连接高频率的时钟;CLKDIV
连接低频率的时钟;D1 ~ D7
连接需要进行并转串的数据(1bit);OCE
,1’b1
,输出数据时钟使能,这里为常高;RST
,~XRST
,Reset
信号,这里系统时钟sys_rst_n
为低有效,所以取反;- 其余
SHIFTOUT1
,2
,TBYTEOUT
,TFB
,TQ
不连接; SHIFTIN1
,2
,T1 ~ T4
,TBYTEIN
,TCE
均连接1’b0
;
OBUFDS
之前说的,都是将并行数据,串行输出的步骤;假设已经获串行的数据,还需要将其使用OBUFDS
输出;
参考手册ug471_7Series_SelectIO.pdf Page45 ~ Page46;
OBUFDS Primitive
观察为,输入Port I
,输出Port O
和OB
;
同样在Language Templates
中找到原语模版:
// OBUFDS : In order to incorporate this function into the design,
// Verilog : the following instance declaration needs to be placed
// instance : in the body of the design code. The instance name
// declaration : (OBUFDS_inst) and/or the port declarations within the
// code : parenthesis may be changed to properly reference and
// : connect this function to the design. All inputs
// : and outputs must be connected.// <-----Cut code below this line---->// OBUFDS: Differential Output Buffer// Kintex UltraScale// Xilinx HDL Language Template, version 2018.3OBUFDS OBUFDS_inst (.O(O), // 1-bit output: Diff_p output (connect directly to top-level port).OB(OB), // 1-bit output: Diff_n output (connect directly to top-level port).I(I) // 1-bit input: Buffer input);// End of OBUFDS_inst instantiation
注意,看到O
和OB Port
需要直接连接到顶层的输出引脚;
通用设计
将OSERDES2
和OBUFDS
联合起来,进行通用设计,这样移植和例化都比较方便;
需要定输出引脚个数,还需要加上CLK
输出信号;
比如说输出引脚个数为16
,串解因子为8
;
与低频时钟CLKDIV
同步的数据tx_data
位宽就是16 * 8 = 128bit
;
这时候需要将数据拆分,分别例化到16
个引脚上;
如果是两个引脚,那就可以直接例化,如果有很多,那么就可以使用generate大法;
CLK
直接上code
:
parameter clk_pattern = 8'b0101_0101;
wire s_OSERDES_CLK ; // tx io clk//---------------------------------------------------------------------
// Clock Output control
//---------------------------------------------------------------------
OSERDESE2 #(.DATA_RATE_OQ ( "DDR" ), // DDR, SDR.DATA_RATE_TQ ( "DDR" ), // DDR, BUF, SDR.DATA_WIDTH ( 8 ), // 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)
)
U_OSERDESE2_CLK0 (.OFB ( ), // 1-bit output: Feedback path for data.OQ ( s_OSERDES_CLK ), // 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 ), // 1-bit input: High speed clock.CLKDIV ( CLK_DIV ), // 1-bit input: Divided clock// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1 ( clk_pattern[0] ),.D2 ( clk_pattern[1] ),.D3 ( clk_pattern[2] ),.D4 ( clk_pattern[3] ),.D5 ( clk_pattern[4] ),.D6 ( clk_pattern[5] ),.D7 ( clk_pattern[6] ),.D8 ( clk_pattern[7] ),.OCE ( 1'b1 ), // 1-bit input: Output data clock enable.RST ( ~XRST ), // 1-bit input: Reset// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each).SHIFTIN1 ( 1'b0 ),.SHIFTIN2 ( 1'b0 ),// 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
);OBUFDS #(.SLEW ( "FAST" ) // Specify the output slew rate
)
U_OBUFDS_CLK0 (.O ( OSERDES_CLK_P ), // Diff_p output (connect directly to top-level port).OB ( OSERDES_CLK_N ), // Diff_n output (connect directly to top-level port).I ( s_OSERDES_CLK ) // Buffer input
);
先通过OSERDES2
将clk_pattern
输出,就有了clk
的波形,接着连接到OBUFDS
上,直接输出到差分引脚。
DATA
依然直接上code
:
parameter DB_W = 16 // data bus width
wire [DB_W-1 :0] s_OSERDES_DAT ; // tx io data//---------------------------------------------------------------------
// Data Output control
//---------------------------------------------------------------------
genvar i;
generatefor (i=0; i<DB_W; i=i+1) begin: data_txoutOSERDESE2 #(.DATA_RATE_OQ ( "SDR" ), // DDR, SDR.DATA_RATE_TQ ( "SDR" ), // DDR, BUF, SDR.DATA_WIDTH ( 8 ), // 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))U_OSERDESE2_TLA0 (.OFB ( ), // 1-bit output: Feedback path for data.OQ ( s_OSERDES_DAT[i] ), // 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 ), // 1-bit input: High speed clock.CLKDIV ( CLK_DIV ), // 1-bit input: Divided clock// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1 ( TX_DATA[i*8+7] ),.D2 ( TX_DATA[i*8+6] ),.D3 ( TX_DATA[i*8+5] ),.D4 ( TX_DATA[i*8+4] ),.D5 ( TX_DATA[i*8+3] ),.D6 ( TX_DATA[i*8+2] ),.D7 ( TX_DATA[i*8+1] ),.D8 ( TX_DATA[i*8+0] ),.OCE ( 1'b1 ), // 1-bit input: Output data clock enable.RST ( ~XRST ), // 1-bit input: Reset// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each).SHIFTIN1 ( 1'b0 ),.SHIFTIN2 ( 1'b0 ),// 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);OBUFDS #(.SLEW ( "FAST" ) // Specify the output slew rate)U_OBUFDS_TLA0 (.O ( OSERDES_DAT_P[i] ), // Diff_p output (connect directly to top-level port).OB ( OSERDES_DAT_N[i] ), // Diff_n output (connect directly to top-level port).I ( s_OSERDES_DAT[i] ) // Buffer input);end
endgenerate
使用generate语句,将16
个引脚,全部一次例化,非常方便;下次使用的时候,直接修改参数DB_W
即可;
至此,LVDS
的输出RTL
已经完成了。
One more thing
需要添加xdc
文件,加入端口的约束和电平规格约束,举例如下:
# DATA
set_property PACKAGE_PIN L16 [get_ports {LVDS_OUTP[0]}]
set_property PACKAGE_PIN K16 [get_ports {LVDS_OUTN[0]}]set_property IOSTANDARD LVDS_25 [get_ports {LVDS_OUTP[0]}]
set_property IOSTANDARD LVDS_25 [get_ports {LVDS_OUTN[0]}]
所有LVDS
输出的引脚进行引脚约束和电平规格约束之后,才算是大功告成。