Xlinx相关原语讲解导航页面,想要了解更过原语,可以点击该链接跳转。
1、概括OSERDESE2
OSERDESE2(Output Parallel-to-Serial Logic Resources是7系列FPGA器件中的专用并串转换器,具有特定的时钟和逻辑资源。 图1是OSERDESE2的框图,每个OSERDESE2模块都包含一个用于数据和三态控制的专用串行器。数据和三态串行器输出都可以配置为SDR(在时钟的单沿传输数据)和DDR(在时钟的双沿传输数据)模式。数据序列化最高可达 8:1(如果使用OSERDESE2宽度扩展,则为10:1或14:1)。
OSERDESE2在FPGA中其实是和OLOGIC复用资源的,如图2所示,图中标注的是OLOGICE3,但是很多引脚都是OSERDESE2的,而OSERDESE2和OLOGICE3中的ODDR功能有相似的地方,都支持在时钟信号的双沿输出数据。所以这两个器件共用了资源,在使用时,同一个IO不能同时使用OLOGICE3和OSERDESE2的功能。
OSERDESE2模块是将并行数据转换为串行数据进行输出,一般并行转串行的时序如图3所示。在第二个时钟上升沿采集到clk_div输入4bit并行数据,在一个clk_div时钟周期内需要将并行数据转换为串行数据输出,那么使用clk与clk_div相位对齐(同一锁相环输出两个相位相同的时钟即可),clk频率是clk_div四倍。然后在clk的上升沿从低位到高位依次输出din的数据。
因此OSERDESE2也有两个时钟信号,一个与输出数据对齐CLK,一个与输入数据对齐的CLKDIV,CLK和CLKDIV的相位必须一致。此外OSERDESE2内部还有一个计数器,用来计数当前dout输出的是输入信号的第几位数据了,所以在使用OSERDESE2前,必须对OSERDESE2进行复位,复位信号可以是同步复位,也可以是异步复位,但是复位信号无效边沿必须与CLKDIV同步(即使用异步复位时,要考虑同步释放复位)。
上述转换关系可知,时钟clk与clk_div的时钟频率之比与输入数据和输出数据的位宽之比一致。如果要将10bit并行输入数据转换为串行数据输出,那么clk频率为clk_div的10倍。HDMI传输1024*768,60Hz刷新率图像时,并行数据时钟clk_div为65MHz,那么clk的时钟频率为650MHz,这在FPGA内部还可以实现。但需要传输1920*1080分辨率,60Hz刷新率图像时,需要时钟clk_div频率达到148.5MHz,而clk需要1485MHz,这在7系列FPGA内部显然无法实现。
如图4所示的DDR模式传输数据,在时钟clk上升沿和下降沿都输出数据,数据传输的速度提升一倍,传输同样的数据,相比SDR模式,DDR模式的时钟频率可以降低一半。
在DDR模式下,两个时钟频率相差为输入数据位宽除以2。当然在DDR模式输入数据的位宽就不能是单数,时钟clk的频率不好处理。
OSERDESE2模块还包含一个用于IOB的三态控制的并串转换器,最多只能把4位并行数据转换为串行数据且不能级联。
2、OSERDESE2原语信号及参数
2.1、OSERDESE2原语端口
图5是OSERDESE2的原语框图,时钟CLK与输出串行数据对齐的高频时钟信号,而CLKDIV是与输入并行信号对齐的低频时钟信号。
D1~D8是并行输入数据端口,单个OSERDESE2最多配置8位输入并行输入数据,两个OSERDESE2模块级联可以配置10位或14位并行输入数据。注意D1最先转换为串行数据输出。
OQ是串行输出信号,直接与IOB相连,该信号只能输出到FPGA管脚。 如果要将信号输出到ODELAYE2或者ISERDESE2,那么使用OFB端口,OFB和OQ两个端口的信号一模一样,只是数据走向不同。
OSERDESE2原语还有三态控制输出的功能,那么T1~T4是三态控制信号,与D1~D4数据对应。使用三态功能时,TQ作为串行输出的管脚,用于判断OQ信号此时是作为输入引脚(TQ为高电平)还是输出引脚(TQ为低电平),而TFB与TQ原理类似。
OCE就是数据转换的时钟使能信号,而TCE是三态转换的时钟使能信号,均是高电平有效。
SHIFTIN1、SHIFTIN2、SHIFTOUT1、SHIFTOUT2用于OSERDESE2转换数据时的位扩展,单个OSERDESE2最多只能将8bit并行数据转换位串行数据输出,而两个OSERDESE2级联最多可以将14bit并行数据转换位串行数据输出。如图6所示,是两个OSERDESE2将10bit并行输入转换为串行输出的连接框图。从OSERDESE2的SHIFTOUT1、SHIFTOUT2连接到主OSERDESE2的SHIFTIN1、SHIFTIN2实现扩展。从模块的输入数据从D3开始连接,D1和D2不能使用。
扩展OSERDESE2位宽时,如果是差分输出,主OSERDESE2必须位于差分输出对的正极(P 引脚)侧。表1列出了SDR和DDR模式的数据宽度可用取值。
模式 | 位宽(bit) |
---|---|
SDR | 2、3、4、5、6、7、8 |
DDR | 4、6、8、10、14 |
RST是一个异步的高电平复位,RST拉高时,会将CLK和CLKDIV时钟域下的所有触发器清零输出低电平。当设计中存在多个OSERDESE2模块时,推荐所有OSERDESE2均使用同一个复位信号,并且RST拉高应该与CLKDIV信号同步,确保所有OSERDESE2模块能够同时退出复位状态。
2.2、OSERDESE2原语参数
该原语总共存在11个参数,INIT_OQ用于表示OQ信号的初始状态,默认为1’b0。INIT_TQ用于表示TQ的初始状态,默认为1’b0。SRVAL_OQ用于表示OQ信号复位时的值,默认也为1’b0。SRVAL_TQ用于表示TQ信号复位时的值,默认也为1‘b0。在使用原语时,可以不对这四个参数进行修改,默认即可。
参数SERDES_MODE定义使用宽度扩展时OSERDESE2模块是主模块还是从模块。可以为MASTER或SLAVE,默认为MASTER。
参数DATA_RATE_OQ定义数据是以单数据速率(SDR)还是双数据速率(DDR)进行串行化处理,默认值为DDR。
参数DATA_WIDTH定义并串转换器的并行数据输入宽度。当 DATA_RATE_OQ设置为SDR时,DATA_WIDTH可能取值为2、3、4、5、6、7和8。当DATA_RATE_OQ设置为DDR时,DATA_WIDTH属性的可能值为 4、6、8 、10 和 14。
参数DATA_RATE_TQ定义是否将三态控制作为单数据速率(SDR)还是双数据速率(DDR)进行处理。该属性允许的值为SDR、DDR或BUF,默认为DDR。在SDR和DDR模式下,使用T1~T4输入,并且可以使用TRISTATE_WIDTH配置三态输入宽度。在BUF模式下,SDR和DDR模式寄存器被旁路,使用T1输入。
参数TRISTATE_WIDTH定义三态控制并串转换器的并行三态输入宽度。当DATA_RATE_TQ设置为SDR或BUF时,TRISTATE_WIDTH属性只能设置为1。当DATA_RATE_TQ设置为DDR时,TRISTATE_WIDTH属性的可能值为1和4。
图7显示了使用OSERDESE2的有效设置和组合。
OSERDESE2块的输入到输出延迟指的是当CLKDIV的上升沿把输入数据D1~D8端口的数据寄存到OSERDESE2内部时 到 OSERDESE2的OQ端口输出第一位数据的时间间隔。当CLK和CLKDIV的相位对齐时,延迟可能相差一个CLK周期,如果CLK和CLKDIV的相位没有对齐时,延迟的值取决于DATA_RATE和DATA_WIDTH的值,如图8所示。
2.3、OSERDESE2模式时序
如图9所示,OSERDESE2采用SDR模式将2位并行数据转换为串行数据输出,时钟CLK和CLKDIV的相位是对齐的,在CLKDIV第二个上升沿时,采集到两位并行输入数据2’bBA,经过一个CLK延迟后,在CLK的第一个上升沿输出A,第二CLK上升沿输出B,完成并行到串行数据的转换。
如图10所示,OSERDESE2采用DDR模式将8位并行数据转换为串行数据输出,在CLKDIV第二个上升沿时,OSERDESE2采样D1~D8的输入数据ABCDEFGH到内部,经过四个CLK周期后,在CLK的上升沿OQ输出第一个数据A,在CLK下降沿OQ输出第二个数据B,依次在双沿输出所有数据。
在CLKDIV第三个时钟周期内输出完第二个CLKDIV时钟采集的数据,在CLKDIV第四个时钟开始输出在CLKDIV第三个时钟采集到D1~D8的数据。
如图11是使用三态传输时的时序图,此时最多将4位并行数据转为串行数据输出,在时钟CLKDIV第三个上升沿处,采集到D1D4的数据位EFGH,与此时T1T4的数据0010对应。
经过一个CLK时钟周期后,OQ输出第一个串行数据E,而TQ开始输出对应三态数据0,当TQ数据为0时,才会将OQ的数据输出到IOB模块,当TQ为1时,FPGA管脚作为输入,此时不会把OQ的数据输出到IOB。因此图11中当TQ为低电平时,OBUFT.O才输出OQ对应的数据EFH,否则不输出OQ的数据。
3、OSERDESE2原语仿真
在Vivado中获取OSERDESE2原语模板,获取方式在讲解IDDR原语时已经详细讲过,不再赘述,获取原语模板如下所示:
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 );
3.1 SDR模式并串转换
首先来一个SDR模式的串并转换,输入5位并行数据,输出1位串行数据,高速时钟CLK的频率是输入数据时钟CLKDIV的5倍,对应的设计代码如下所示:
module oserdese2_ctrl( input clk ,//系统时钟信号; input clk_div , input rst ,//系统复位信号,高电平有效; input [4 : 0] din ,//输入数据; output oq //输出数据 ); //例化主OSERDESE2原语 OSERDESE2 #( .DATA_RATE_OQ ( "SDR" ),// DDR, SDR .DATA_RATE_TQ ( "DDR" ),// DDR, BUF, SDR .DATA_WIDTH ( 5 ),// 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 ( .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 ( ), .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 (din[0] ), .D2 (din[1] ), .D3 (din[2] ), .D4 (din[3] ), .D5 (din[4] ), .D6 ( ), .D7 ( ), .D8 ( ), .OCE (1'b1 ),// 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 ( ), .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
对应的TestBench文件如下所示:
`timescale 1 ns/1 ns module test(); parameter CYCLE = 70 ;//系统时钟周期,单位ns,默认70ns; reg clk ;//系统时钟,默认100MHz; reg rst ;//系统复位,默认高电平有效; reg clk_div ; reg [4 : 0] din ; wire oq ; oserdese2_ctrl u_oserdese2_ctrl ( .clk ( clk ), .clk_div ( clk_div ), .rst ( rst ), .din ( din ), .oq ( oq ) ); //生成周期为CYCLE数值的系统时钟; initial begin clk_div = 1; forever #(CYCLE/2) clk_div = ~clk_div; end initial begin clk = 1; forever #(CYCLE/10) clk = ~clk; end //生成复位信号; initial begin rst = 0; #2; rst = 1;//开始时复位10个时钟; #(10*CYCLE); rst = 0; repeat(120) @(posedge clk); $stop;//停止仿真; end initial begin #1; din = 5'd0; forever begin #(CYCLE); din = ({$random} % 32); end end endmodule
运行仿真得到部分仿真截图,如图12所示,如果不注意分析,会以为仿真结果错误。复位信号rst复位完成(拉低)后,clk在760ns之后采集到第一个输入数据5’b01101,什么时候OQ才输出数据?通过查阅图8可知,在SDR模式,输入数据位宽:输出数据位宽之比等于5:1时,延迟4个clk时钟后OQ输出数据,所以在图12中820ns后的第一个时钟上升沿开始输出采集到的最低位数据1’b1,下个时钟上升沿输出1’b0,依次完成数据转换。注意OQ输出开始输出的clk时钟边沿并没有与clk_div的时钟边沿对齐。
特别注意:OQ输出数据与采集到数据的时间间隔要与图8表中的间隔一致,不然会错误分析。
然后把该工程的引脚进行分配,综合、实现工程,查看OQ信号在FPGA中的位置,如图13所示。
把OQ信号前面的OSERDESE2放大,如图14所示,OSERDESE2占据OLOGICE3的位置,因此OLOGICE3与OSERDESE2是复用一些资源的。
3.2 DDR模式并串转换
图12中,clk频率是clk_div频率的5倍,同样的时钟关系,OSERDESE2使用DDR模式,可以把输入的10位并行数据转换为串行数据输出,单个OSERDESE2最多只能把8位并行数据转换位串行数据,因此需要两个OSERDESE2级联使用,对应的代码如下所示:
module oserdese2_ctrl( input clk ,//系统时钟信号; input clk_div , input rst ,//系统复位信号,高电平有效; input [9 : 0] din ,//输入数据; output oq //输出数据 ); wire shiftou1; wire shiftou2; //例化主OSERDESE2原语 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) ) u_OSERDESE2_M ( .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 ( ), .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 (din[0] ), .D2 (din[1] ), .D3 (din[2] ), .D4 (din[3] ), .D5 (din[4] ), .D6 (din[5] ), .D7 (din[6] ), .D8 (din[7] ), .OCE (1'b1 ),// 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 (shiftou1 ), .SHIFTIN2 (shiftou2 ), // 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 ); //例化从OSERDESE2原语 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) ) u_OSERDESE2_S ( .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 (shiftou1 ), .SHIFTOUT2 (shiftou2 ), .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 ( ), .D2 ( ), .D3 (din[8] ), .D4 (din[9] ), .D5 ( ), .D6 ( ), .D7 ( ), .D8 ( ), .OCE (1'b1 ),// 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 ( ), .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
TestBench只需要把第8行代码的输入数据位宽改为10位,第46行输入数据的赋值改成下面代码就行了。
din = ({$random} % 1024);
仿真结果如图15所示,与SDR的区别在于DDR的oq信号在clk的上升沿和下降沿都会传输数据。clk_div采集到数据与oq输出数据的间隔由图8表中查得为4个clk周期,所以图15中clk_div采集到10’b0100001101,经过四个clk周期后,oq开始输出最低位数据,之后依次输出剩余数据。
对新加入的几个管脚进行分配,对工程综合、实现,查看最后两个OSERDESE2的布局如图16所示,OQ的管脚直接与主OSERDESE2的输出连接,从OSERDESE2的SHIFTOUT1、SHIFTOUT2分别与主OSERDESE2的SHIFTIN1、SHIFTIN2连接。
将主从OSERDESE2分别放大后如图17所示。
综上就是OSERDESE2原语的常用模式,DDR模式在HDMI接口中比ODDR更适用,效果也更好,在HDMI驱动模块设计时,将会使用OSERDESE2的DDR模式将10位数据转化为双沿传输的数据输出。
需要本文所使用工程的在公众号后台回复” OSERDESE2”(不包括引号)即可,工程中的代码为最初模式,其余模式按照文中描述修改即可。
您的支持是我更新的最大动力!将持续更新工程,如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!