Xilinx原语OSERDESE2的使用和仿真详解

网友投稿 470 2022-11-11

Xilinx原语OSERDESE2的使用和仿真详解

2、理论 Xilinx的原语OSERDESE2是一种专用的并-串转换器,每个OSERDESE2模块都包括一个专用串行化程序用于数据和3状态控制。数据和3状态序列化程序都可以工作在SDR和DDR模式。数据串行化的位宽可以达到8:1(如果使用原语模块级联,则可以到10:1和14:1)。3状态序列化最高可达14:1,有一个专用的DDR3模式可用于支持高速内存应用程序。

OSERDESE2的框图如下:

OSERDESE2的端口说明如下:

需要例化的一些可用属性如下:

TRISTATE_WIDTH的选取见下表:

SDR、DDR输出模式下位宽的选取有如下限制:

3、8位数据的并串转换 接下里例化一个原语来熟悉下用法,8位数据的并串转换,采用DDR输出。

官方手册的8位DDR转化时序图如下:

//------------------------------------------------------------------------ //--OSERDESE2测试模块 //------------------------------------------------------------------------

output ser_data //串行输出数据 );

endmodule

每隔20ns随机生成1个8位2进制数据作为并行输入,观察串行输出,Testbench如下:

`timescale 1ns / 1ps //时间单位/精度

//---------------------------------------------------- module tb_serializer();

reg clk_per ; reg clk_ser ; reg rst_n ; reg [7:0] par_data ; wire ser_data ;

//---------------------------------------------------- initial begin clk_per clk_ser rst_n par_data #180 rst_n end //---------------------------------------------------------- always #10 clk_per = ~clk_per; always #2.5 clk_ser = ~clk_ser;

always #20 par_data

//---------------------------------------------------- serializer serializer_inst( .clk_per (clk_per) , .clk_ser (clk_ser) , .rst_n (rst_n) , .par_data (par_data) , .ser_data (ser_data) );

endmodule

仿真结果如下:

可以看出:

在第1条蓝线处,是复位后并行时钟的第1个上升沿,此时采集到的数据为0000_0001 在第2条蓝线处,也就是4个串行时钟的延迟后,串行输出开始有数据,分别为1-0-0-0-0-0-0-0,可以看出是第1个上升沿采集到的数据输出(0000_0001从低位往高位输出) 在第2条蓝线处,是复位后并行时钟的第2个上升沿,此时采集到的数据为0000_1101 在第3条蓝线处,也就是4个串行时钟的延迟后,串行输出开始有数据,分别为1-0-1-1-0-0-0-0,可以看出是第2个上升沿采集到的数据输出(0000_1101从低位往高位输出)

其他与上述相同,符合官方给出的时序图

4、10位数据的并串转换(级联) OSERDESE2原语还支持例化两次原语级联,以便实现10位、14位位宽的串行化转换。下图是10位位宽的级联框图,其中一个设置位MASTER,另一个设置为SLAVE,通过SHIFTIN与SHIFTOUT连接。

需要注意:数据的输出从MASTER输出,数据的高位输入到SLAVE模块时,需要从D3开始(只能使用D3~D8)

接下里例化一个原语来实现10位数据的并串转换,采用DDR输出。

例化2个原语OSERDESE2级联(打开VIvado--Tools--Language Templates,搜索“OSERDESE2”,可以找到Xilinx提供的模板),与DDR、3态控制相关的端口,输入全设置为0,输出不关心,编写Verilog如下:

//------------------------------------------------------------------------ //--OSERDESE2测试模块 //------------------------------------------------------------------------

//-------------------------------------------------------- module serializer( input clk_ser , //串行输出时钟,50M*5=250M input clk_per , //并行输入时钟,50M input rst_n , //复位信号,低电平有效 input [9:0] par_data , //并行输入数据,位宽10

output ser_data //串行输出数据 ); //------------------------------------------------------------------ wire shift1; //级联线1 wire shift2; //级联线2

//------------------------------------------------------------------

//例化主模块MASTER OSERDESE2 #( .DATA_RATE_OQ ("DDR") , // DDR, SDR .DATA_RATE_TQ ("SDR") , // 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_inst1 ( .OFB () , // 1-bit output: Feedback path for data .OQ (ser_data) , // 1-bit output: Data path output .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_ser) , // 1-bit input: High speed clock .CLKDIV (clk_per) , // 1-bit input: Divided clock .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 (shift1) , .SHIFTIN2 (shift2) , .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 );

//例化从模块SLAVE OSERDESE2 #( .DATA_RATE_OQ ("DDR") , // DDR, SDR .DATA_RATE_TQ ("SDR") , // 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_inst2 ( .OFB () , // 1-bit output: Feedback path for data .OQ () , // 1-bit output: Data path output .SHIFTOUT1 (shift1) , .SHIFTOUT2 (shift2) , .TBYTEOUT () , // 1-bit output: Byte group tristate .TFB () , // 1-bit output: 3-state control .TQ () , // 1-bit output: 3-state control .CLK (clk_ser) , // 1-bit input: High speed clock .CLKDIV (clk_per) , // 1-bit input: Divided clock .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 () , .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

每隔20ns随机生成1个10位2进制数据作为并行输入,观察串行输出,Testbench如下:

//------------------------------------------------ //--OSERDESE2原语仿真 //------------------------------------------------

`timescale 1ns / 1ps //时间单位/精度

//---------------------------------------------------- module tb_serializer();

reg clk_per ; reg clk_ser ; reg rst_n ; reg [9:0] par_data ; wire ser_data ;

//---------------------------------------------------- initial begin clk_per clk_ser rst_n par_data #180 rst_n end //---------------------------------------------------------- always #10 clk_per = ~clk_per; always #2 clk_ser = ~clk_ser;

always #20 par_data

//---------------------------------------------------- serializer serializer_inst( .clk_per (clk_per) , .clk_ser (clk_ser) , .rst_n (rst_n) , .par_data (par_data) , .ser_data (ser_data) );

endmodule

仿真结果如下:

可以看出:

在第1条蓝线处,是复位后并行时钟的第1个上升沿,此时采集到的数据为11000_00001 在第2条蓝线处,也就是4个串行时钟的延迟后,串行输出开始有数据,分别为1-0-0-0-0-0-0-0-1-1,可以看出是第1个上升沿采集到的数据输出(11000_00001从低位往高位输出) 在第2条蓝线处,是复位后并行时钟的第2个上升沿,此时采集到的数据为01000_01101 在第3条蓝线处,也就是4个串行时钟的延迟后,串行输出开始有数据,分别为1-0-1-1-0-0-0-0-1-0,可以看出是第2个上升沿采集到的数据输出(01000_01101从低位往高位输出) 其他与上述相同。

这里官方手册没有给出10bitDDR输出的时序图,输出延迟给出的表如下图:

可以看到这里10:1的输出延迟应该是5个时钟周期,但是我上面仿真的却是4个时钟周期,一开始我还以为是哪里错了,搞得我重复仿真了好几遍,后面又看了一下手册,终于在延迟表的下面发现了这句话(上图标红):CLK、CLKDIV的时钟沿通常不是相位一致的。当这两个时钟的时钟沿相位一致时,延迟会存在一个周期的差异。

这样的话,仿真结果应该是没有问题。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:安装zabbix-4.0-LTS(Apache+mariadb)
下一篇:Linux应用程序基础及Yum仓库的建立
相关文章

 发表评论

暂时没有评论,来抢沙发吧~