赞
踩
ISERDESE2是一种专用的串行到并行转换器,具有特定的时钟和逻辑功能,旨在促进高速源同步应用的实现。ISERDESE2避免了在FPGA结构中设计反序列化器时遇到的额外时序复杂性。
iserdes2支持SDR与DDR两种模式,在SDR模式下可以完成1bit到2-8bit的数据转换,在DDR模式下可以完成1bit到4bit、6bit、8bit以及通过两个iserdes2原语可以完成1ibt到10bit、14bit的串并转换(如图二)。
图1:iserdes2位宽
图2:iserdes2的10位与14位级联
注意:Slave模块中的Q1与Q2不可以作为级联的输出,在1bit转10bit的过程中使用Q3与Q4进行扩展、在1bit转10bit的过程中使用Q3-Q8这6位进行扩展。
在串并转换过程中很难避免的会出现传输错位导致采集到的数据出现错误,这是就需要用到slipbit模块进行数据校准。
slipbit是iserdes2原语中的一个输入,通过判断输出Q中的数据与校验和是否相同来判断数据是否相同,如果不同通过拉高一个时钟的slipbit进行移位操作,直到检测到数据校验和正确表明采集到的正确。
图3:slip_bit信号的变化情况
备注:图3中的q[7:0]数值移位不正确,是随机添加上去的数据,具体可以看vivado仿真情况。
SRD模式下8:1 输出每次有一个时钟的slipbit会对校验不正确的数据Q[7:0]进行循环左移,例如:1001_0011——>0010_0111。DDR模式下8:1输出每次有一个时钟的slipbit会对校验不正确的数据Q[7:0]进行循环右移1bit,然后左移3bit依次循环,例如0010_0111把最高移的1移到最低位变成了0010_0111——>1001_0011(右移1bit)——>1001_1110(左移3bit)
图4:SDR与DDR 8:1模式移位方式
iserdes2原语包含引脚
图5:iserdes2引脚框图
具体引脚说明 :
通过拉高BITSLIP重新排序输出信号,BITSLIP只需要拉高一个时钟(CLK_DIV),完成移位操作后,如果校验和与输入还是不通,再次拉高,直到校验和正确,来保证采集到的数据正确。
图6:DDR Bitslip 时序图
DDR 模式Bitslip信号变高后有三个CLK_DIV的延时,SDR 模式Bitslip号变高后有两个CLK_DIV的延时。
图7: 时钟使能引脚
CE1和CE2引脚用来作为时钟使能的时钟源,通过属性 NUM_CE来选择。当 NUM_CE=1时使用CE1作为时钟使能信号;当 NUM_CE=2时,在CLKDIV=0时使用CE2R,在CLKDIV=1时使用CE1R作为时钟使能信号。
clk串行数据输入时钟,clkdiv并行输出数据时钟,保证clk与clkdiv没有相位差,即可以通过PLL生成它们。
SDR模式8:1传输clk=400M,clkdiv=50M , DDR模式8:1传输clk=400M,clkdiv=100M
图8: 时钟使能引脚
在MEMORY_QDR以外的任何模式下,将CLKB连接到CLK的反转,在MEMORY_QDR模式下,CLKB应该连接到一个唯一的相移时钟。
在iserdes模式MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE中只用MEMORY使用,其他模式接地就可以。
在MEMORY_DDR3模式使用,其他模式接地。
在MEMORY、MEMORY_DDR3模式使用。
图9:输入模式设置
D与DDLYA都是iserdes2的输入引脚,通过配置IOBDELAY Value的模式来选择输入的引脚。
在oserdes2的信号输入到iserdes2下使用,使用是需要将ISERDES2中的OFB_USED设置为TURE
图10:OFB使用连接方式
复位引脚,高电平复位,最好与CLKDIV同步,来保证ISERDES2同步复位成功。
iserdes2的输出引脚。
传输位宽为10bit或者14bit时、将iserdes2(Slave)的SHIFTIN1、SHIFTIN2连接iserdes2(master)中的SHIFTOUT1、SHIFTOUT2(如图2)
在使用ISERDES2是需要配置其中的一些属性,下边对其做一些简单的描述
配置数据流传输模式:SDR或者DDR,默认配置为DDR
配置数据位宽:1)、DATA_RATE为DDR可以配置为4、6、8、10、14。2)、DATA_RATE为SDR可以配置2、3、4、5、6、7、8。默认值为4
配置CLKDIV时钟翻转使能,在MEMORY、MEMORY_DDR3模式使用,默认值为FALSE。
配置CLK与CLKB时钟翻转使能,在MEMORY、MEMORY_DDR3模式使用,默认值为FALSE。
模式配置,可配置模式为MEMORY, MEMORY_DDR3,MEMORY_QDR,NETWORKING,默认值为FALSE。一般使用NETWORKING。
CE1、CE2使能配置,默认值为2。
OSERDES2与ISERDES2级联配置,配置为TURE后可以将OSERDES2的输出引脚OFB与ISERDES2的输入引脚OFB进行数据传输。默认值为FALSE
ISERDES2主从模式配置,默认为Master,只有DDR模式的10:1或者14:1是用到Slave,默认配置Master。
初始化第一个到第四个寄存器的值,默认为0,默认即可。
复位以后第一个到第四个寄存器的值,默认为0,默认即可。
配置D与DDLYA的模式、可配置为NONE、IBUF, IFD、BOTH,具体如图9,默认为NONE,默认即可,其他情况目前还没用到。
在数据为方便测试文件编写,将OSERDES2与ISERDES2级联,如图10所示。本文采用数据8’h32与8'h8c作为一组校验和,一共使用了32组校验和与随机数组成一组包文,将该包文发送到OSERDES2原语进行并串转换,然后将数据发送到ISERDES2模块。
图11 :VIVADO Schematic
- module top(
-
- input sys_clk ,
- input rst_n ,
- output o_iserdese2_vld ,
- output [7:0] o_iserdese2
-
- );
-
-
-
- wire rst_wire ;
- wire clk_wiz_0 ;
- wire clk ;
- wire clk_div ;
- wire oserdese_ofb;
- wire locked ;
- wire flag_wire ;
-
- clk_wiz_0 u_clk_wiz_0(
- .clk_out1 ( clk_div ),//output clk_out1
- .clk_out2 ( clk ),//output clk_out2
- .reset ( ~rst_n ),//input reset
- .locked ( locked ),
- .clk_in1 ( sys_clk ) //input clk_in1
- );
-
-
-
- assign rst_wire = rst_n==0;
-
- //例化并串转换原语;
- oserdese2_ctrl u_oserdese2_ctrl(
- .clk ( clk ), //系统时钟信号;
- .clk_div ( clk_div ),
- .rst ( rst_wire ), //系统复位信号,高电平有效;
- .ofb ( oserdese_ofb ),
- .o_cheeksum_flag ( flag_wire ),
- .cheek_sum_first ( 8'h32 ), //校验和
- .cheek_sum_secord( 8'h8c )
- );
-
- iserdese2_ctrl u_iserdese2_ctrl(
- .clk ( clk ),//系统时钟信号;
- .clk_div ( clk_div ),
- .rst ( rst_wire ),//系统复位信号,高电平有效;
- .ofb ( oserdese_ofb ),
- .dout ( o_iserdese2 ),//输出数据
- .dout_vld ( o_iserdese2_vld ), //输出数据有效指示信号;
- .i_cheeksum_flag (flag_wire ),
- .cheek_sum_first ( 8'h32 ), //校验和
- .cheek_sum_secord( 8'h8c )
- );
-
- endmodule

本文采用DDR模式8:1输出传输,系统时钟为50M,通过PLL模块生成CLK=200M,CLKDIV=50M。
图12:CLK(200M)与CLKDIV(50M)
-
- module oserdese2_ctrl(
- input clk ,
- input clk_div ,
- input rst ,
- input [7:0] cheek_sum_first , //校验和
- input [7:0] cheek_sum_secord, //校验和
-
- output ofb ,
-
- output o_cheeksum_flag
- );
-
- parameter PACKAGE_NUM = 32 ; //校验和长度
-
-
-
- reg o_cheeksum_flag ;
- reg [7:0] cnt ;
- reg [7:0] din ;
-
- wire add_cnt ;
- wire end_cnt ;
- reg [5:0] cnt ;
- reg [7:0] cnt_package ;
-
-
- //校验和发送完成标志位;
- always@(posedge clk_div)begin
- if(rst)begin
- o_cheeksum_flag <= 1'b0;
- end
- else if(cnt_package==PACKAGE_NUM-1)begin
- o_cheeksum_flag <= 1'b1;
- end
- end
-
- always@(posedge clk_div)begin
- if(rst)begin
- cnt <= 0;
- end
- else if(add_cnt)begin
- if(end_cnt)begin
- cnt <= 0;
- end
- else begin
- cnt <= cnt + 1;
- end
- end
- end
- assign add_cnt = !o_cheeksum_flag ;
- assign end_cnt = add_cnt && cnt == 2-1 ;
-
- //校验头计数器计算头部长度
- always @(posedge clk_div or posedge rst)begin
- if(rst)begin
- cnt_package <= 0;
- end
- else if(cnt_package==PACKAGE_NUM-1)begin
- cnt_package <= cnt_package;
- end
- else if(end_cnt)begin
- cnt_package <= cnt_package + 1;
-
- end
- end
-
- //校验头部{7C,82}与数据拼接;
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin
- din <= cheek_sum_first;
- end
- else if(cnt_package==PACKAGE_NUM-1)begin//如果校准序列发送完毕,则发送随机信号用于测试。
- din <= {(din[0] ^ din[4] ^ din[5] ^ din[6]),din[7:1]};//M序列公式为x^8+x^4+x^3+x^2+1。
- end
- else if(cnt==1-1)begin//发送校准序列8'h5c;
- din <= cheek_sum_first;
- end
- else if(cnt==2-1)begin//发送校准序列8'h82.
- din <= cheek_sum_secord;
- end
- end
-
- //例化OSERDESE2原语
- OSERDESE2 #(
- .DATA_RATE_OQ ( "DDR" ),// 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)
- )
- OSERDESE2_inst (
- .OFB ( 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 ( ),
- .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 ( ),
- .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

OSERDES2仿真
图13:OSERDES2仿真
如上图中din在clk_div上升沿采集到的数是8’h8c(8'b1000_1100),经过四个clk的延时(DDR模式8:1采样延时,如图14OSERDES2采集延时)后采集串行数据线ofb上的数为8‘b0011_0001,这个数是8’h8c的从高到低0011_0001,因此采用到的ofb数据正确。
- module iserdese2_ctrl(
- clk ,
- clk_div ,
- rst ,
- ofb ,
- cheek_sum_first , //校验和
- cheek_sum_secord , //校验和
- i_cheeksum_flag ,
-
- dout ,
- dout_vld
-
- );
-
- parameter CNT_NUM = 5'd16 ;
- input clk ;
- input clk_div ;
- input rst ;
- input ofb ;
- input i_cheeksum_flag ;
- input [7:0] cheek_sum_first ;
- input [7:0] cheek_sum_secord;
- output [7:0] dout ;
- output dout_vld ;
- reg bitslip ;
- reg slip_flag ;
- wire add_cnt ;
- reg [4:0] cnt ;
- wire [7:0] dout ;
- reg dout_vld ;
-
- wire [7:0] q ;
-
- reg flag_cheek ;
- reg [2:0] slip_cnt ;
- wire add_cnt_slip ;
- wire end_cnt_slip ;
- reg [2:0] cnt_shift ;
- wire add_cnt_shift ;
- wire end_cnt_shift ;
-
- //例化ISERDESE2原语
- ISERDESE2 #(
- .DATA_RATE ( "DDR" ),// DDR, SDR
- .DATA_WIDTH ( 8 ),// Parallel data width (2-8,10,14)
- .DYN_CLKDIV_INV_EN ( "FALSE" ),// Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
- .DYN_CLK_INV_EN ( "FALSE" ),// Enable DYNCLKINVSEL inversion (FALSE, TRUE)
- .INIT_Q1 ( 1'b0 ),// INIT_Q1 : Initial value on the Q outputs (0/1)
- .INIT_Q2 ( 1'b0 ),// INIT_Q2 : Initial value on the Q outputs (0/1)
- .INIT_Q3 ( 1'b0 ),// INIT_Q3 : Initial value on the Q outputs (0/1)
- .INIT_Q4 ( 1'b0 ),// INIT_Q4 : Initial value on the Q outputs (0/1)
- .INTERFACE_TYPE ( "NETWORKING" ),// MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
- .IOBDELAY ( "NONE" ),// NONE, BOTH, IBUF, IFD
- .NUM_CE ( 2 ),// Number of clock enables (1,2)
- .OFB_USED ( "TRUE" ),// Select OFB path (FALSE, TRUE)
- .SERDES_MODE ( "MASTER" ),// MASTER, SLAVE
- .SRVAL_Q1 ( 1'b0 ),// SRVAL_Q1 : Q output values when SR is used (0/1)
- .SRVAL_Q2 ( 1'b0 ),// SRVAL_Q2 : Q output values when SR is used (0/1)
- .SRVAL_Q3 ( 1'b0 ),// SRVAL_Q3 : Q output values when SR is used (0/1)
- .SRVAL_Q4 ( 1'b0 ) // SRVAL_Q4 : Q output values when SR is used (0/1)
- )
- ISERDESE2_inst (
- .O ( ),// 1-bit output: Combinatorial output
- .Q1 ( q[7] ),// Q1 - Q8: 1-bit (each) output: Registered data outputs
- .Q2 ( q[6] ),
- .Q3 ( q[5] ),
- .Q4 ( q[4] ),
- .Q5 ( q[3] ),
- .Q6 ( q[2] ),
- .Q7 ( q[1] ),
- .Q8 ( q[0] ),
- .SHIFTOUT1 ( ),// SHIFTOUT1 : 1-bit (each) output: Data width expansion output ports
- .SHIFTOUT2 ( ),// SHIFTOUT2 : 1-bit (each) output: Data width expansion output ports
- .BITSLIP ( bitslip ),// 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
- // CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
- // to Q8 output ports will shift, as in a barrel-shifter operation, one
- // position every time Bitslip is invoked (DDR operation is different from SDR).
- .CE1 ( 1'b1 ),// CE1: 1-bit (each) input: Data register clock enable inputs
- .CE2 ( 1'b1 ),// CE2: 1-bit (each) input: Data register clock enable inputs
- .CLKDIVP ( 1'b0 ),// 1-bit input: TBD
- // Clocks: 1-bit (each) input: ISERDESE2 clock input ports
- .CLK ( clk ),// 1-bit input: High-speed clock
- .CLKB ( ~clk ),// 1-bit input: High-speed secondary clock
- .CLKDIV ( clk_div ),// 1-bit input: Divided clock
- .OCLK ( 1'b0 ),// 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
- // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
- .DYNCLKDIVSEL(1'b0 ),// 1-bit input: Dynamic CLKDIV inversion
- .DYNCLKSEL ( 1'b0 ),// 1-bit input: Dynamic CLK/CLKB inversion
- // Input Data: 1-bit (each) input: ISERDESE2 data input ports
- .D ( 1'b0 ),// 1-bit input: Data input
- .DDLY ( 1'b0 ),// 1-bit input: Serial data from IDELAYE2
- .OFB ( ofb ),// 1-bit input: Data feedback from OSERDESE2
- .OCLKB ( 1'b0 ),// 1-bit input: High speed negative edge output clock
- .RST ( rst ),// 1-bit input: Active high asynchronous reset
- // SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
- .SHIFTIN1 ( ),
- .SHIFTIN2 ( )
- );
-
- //当没有完成校准时,如果检测到转换结果与要求不一致,则把该信号拉高。
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin
- bitslip <= 1'b0;
- end//当没有校准,且没有处于校准阶段时检测到串并转换结果不为8'h32或者8'h8c时拉高;
- else if(((q != cheek_sum_first) && (q != cheek_sum_secord)) && (~slip_flag) && (~bitslip) && (~dout_vld))begin
- bitslip <= 1'b1;
- end
- else begin
- bitslip <= 1'b0;
- end
- end
-
- //滑块计数器,因为bitslip拉高后,输出需要经过一段时间才会有效,因此这段时间不能对输出数据进行读取判断。
-
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin
- slip_cnt <= 1'b0;
- end
- else if(add_cnt_slip)begin
- if(end_cnt_slip)begin
- slip_cnt <= 1'b0;
- end
- else begin
- slip_cnt <= slip_cnt + 1'd1;
- end
- end
- end
-
- assign add_cnt_slip = slip_flag ;
- assign end_cnt_slip = add_cnt_slip && slip_cnt == 4-1;
-
- //bitslip拉高后的标志信号,初始值为0,当bitslip拉高时拉高,当slip_cnt计数器计数到最大值时清零。
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin
- slip_flag <= 1'b0;
- end
- else if(bitslip)begin
- slip_flag <= 1'b1;
- end
- else if(end_cnt_slip)begin
- slip_flag <= 1'b0;
- end
- end
-
-
- //转换成功计数器,用于记录校准阶段,当校准阶段检测到固定个连续有效数据时,认为校准成功。
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin//
- cnt <= 0;
- end//当在校准阶段时,当bitslip有效时拉高;
- else if((slip_flag || bitslip) && (~dout_vld))begin
- cnt <= 0;
- end
- else if(cnt == CNT_NUM - 1)begin//当检测到固定校准数据时,计数器保持该数值。
- cnt <= CNT_NUM - 1;
- end
- else if(add_cnt)begin
- cnt <= cnt + 1;
- end
- end
-
- //当不处于移动滑块状态且检测到输出数据为规定数据时加1.
- assign add_cnt = ((q == cheek_sum_first) || (q == cheek_sum_secord)) && (~slip_flag) && (~bitslip) && (cnt != (CNT_NUM - 1));
-
- //将转换后的数据输出,只有当校准完成后,输出有效指示信号磁能拉高,表示输出的数据有效。
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin
- dout_vld <= 0;
- end
- else begin
- dout_vld <= end_cnt_shift;
- end
- end
-
- assign dout = q;
- always@(posedge clk_div or posedge rst)begin //oserdese2采用的DDR(8:1)模式,它有4个CLK_DIV的延时
- if(rst)begin
- cnt_shift <= 0;
- end
- else if(add_cnt_shift)begin
- if(end_cnt_shift)begin
- cnt_shift <= cnt_shift ;
- end
- else begin
- cnt_shift <= cnt_shift + 1;
- end
-
- end
- end
- assign add_cnt_shift = i_cheeksum_flag && flag_cheek ;
- assign end_cnt_shift = add_cnt_shift && cnt_shift == 4-1 ;//CLK_DIV的延时计数
- always@(posedge clk_div or posedge rst)begin
- if(rst)begin
- flag_cheek <= 1'd0;
- end
- else if(cnt == CNT_NUM - 1)begin//对bitslip拉高后的时钟计数。
- flag_cheek <= 1'd1;
- end
- end
- endmodule

ISERDES2仿真
图14 :ISERDES2仿真
在OSERDES2中输入32个{8'h32,8'h8c}后的数据是8'h46、8'ha3、8'ha3、8'h51、8'ha8、8'hd4,在ISERDES2中采集到的数据在dout_vld为高电平是也是8'h46、8'ha3、8'ha3、8'h51、8'ha8、8'hd4,因此,ISERDES2模块设计正确。
说明:本文是ISERDES2使用过程中的一些总结,可能不是完全正确,仅供参考。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。