作者:数字站
概括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位并行数据转换为串行数据且不能级联。
OSERDESE2原语信号及参数
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模式的数据宽度可用取值。
RST是一个异步的高电平复位,RST拉高时,会将CLK和CLKDIV时钟域下的所有触发器清零输出低电平。当设计中存在多个OSERDESE2模块时,推荐所有OSERDESE2均使用同一个复位信号,并且RST拉高应该与CLKDIV信号同步,确保所有OSERDESE2模块能够同时退出复位状态。
TBYTE_CTL和TBYTE_SRC信号是用于DDR3控制器使用的,直接关闭即可。
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所示。
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第三个上升沿处,采集到D1~D4的数据位EFGH,与此时T1~T4的数据0010对应。
经过一个CLK时钟周期后,OQ输出第一个串行数据E,而TQ开始输出对应三态数据0,当TQ数据为0时,才会将OQ的数据输出到IOB模块,当TQ为1时,FPGA管脚作为输入,此时不会把OQ的数据输出到IOB。因此图11中当TQ为低电平时,OBUFT.O才输出OQ对应的数据EFH,否则不输出OQ的数据。
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
);
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是复用一些资源的。
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”(不包括引号)即可,工程中的代码为最初模式,其余模式按照文中描述修改即可。
文章来源:数字站