ISERDES2 DDR模式10:1采样

前言        

        在上篇文章ISERDES2介绍中介绍了该原语的使用以及DDR模式8:1采样的代码与仿真波形,本文对ISERDES2不做过多介绍,直接给出DDR模式的10:1采集,方法与8:1采用一样,引入OSERDES将数据传入ISERDES2模块中进行采样。

代码介绍

        代码包括PLL模块,oserdes2_ctrl,iserdes2_ctrl

1. 顶层模块

module top(

     sys_clk          ,
     rst_n            ,
     o_iserdese2_vld  ,
     o_iserdese2

);
    parameter               DATA_WIDTH = 4'd10  ;
    parameter               CHEEK_SUM1 = 10'h323;
    parameter               CHEEK_SUM2 = 10'h28c;
 

    input                   sys_clk             ;
    input                   rst_n               ;
    output                  o_iserdese2_vld     ;
    output [DATA_WIDTH-1:0] o_iserdese2         ;
  
    wire                    rst_wire            ;
    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 ( CHEEK_SUM1    ),    //校验和
        .cheek_sum_secord( CHEEK_SUM2    )  
    );

      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 (CHEEK_SUM1        ),    //校验和
        .cheek_sum_secord(CHEEK_SUM2        )  
    );

endmodule  

2. PLL模块

        DDR模式10:1数据串并转换CLK:CLKDIV=5:1,本文通过系统时钟50MHz生成一个CLK=250MHz,一个CLKDIV=50MHz用与iserder2原语使用。PLL模块通过软件生成,这里不再介绍。

3.  oserdese2_ctrl


module oserdese2_ctrl(
        clk             ,
        clk_div         ,
        rst             ,
        cheek_sum_first ,    //校验和
        cheek_sum_secord,    //校验和
    
        ofb             ,   

        o_cheeksum_flag     
); 
    


    
    parameter         PACKAGE_NUM = 32 ;  //校验和长度
    parameter         DATA_WIDTH  = 10 ;


    input                      clk             ;
    input                      clk_div         ;
    input                      rst             ;
    input  [DATA_WIDTH-1:0]    cheek_sum_first ;    //校验和
    input  [DATA_WIDTH-1:0]    cheek_sum_secord;    //校验和
    
    output                     ofb             ;   

    output                     o_cheeksum_flag ;  

 
    reg                        o_cheeksum_flag ;
    reg   [7:0]                cnt             ;
    reg   [DATA_WIDTH-1:0]     din             ;
     
    wire                       add_cnt         ;
    wire                       end_cnt         ;
    reg   [5:0]                cnt             ;
    reg   [7:0]                cnt_package     ;
    wire                       shiftout1       ;
    wire                       shiftout2       ;

    //校验和发送完成标志位;
    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[9: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     ( 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_Master (
        .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   (  shiftout1    ),
        .SHIFTIN2   (  shiftout2    ),
        // 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 #(
        .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_Slave (
        .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  (    shiftout1  ),
        .SHIFTOUT2  (    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         ( 1'b0          ),
        .D2         ( 1'b0          ),
        .D3         ( din[8]        ),
        .D4         ( din[9]        ),
        .D5         ( 1'b0          ),
        .D6         ( 1'b0          ),
        .D7         ( 1'b0          ),
        .D8         (1'b0           ),
        .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

        在DDR数据OSERDES2原语使用中,位宽大于8的时候,需要用到两个OSERDES2原语进行转换。连接方式如下图,将Slave的SHIFTOUT与Master的SHIFTIN向连,连接方式与ISEDES2的连接相反。

        

4. iserdese2_ctrl

 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;
    parameter                    DATA_WIDTH  = 4'd10;
    input                        clk                ;
    input                        clk_div            ;
    input                        rst                ;
    input                        ofb                ;
    input                        i_cheeksum_flag    ;
    input   [DATA_WIDTH-1:0]     cheek_sum_first    ;
    input   [DATA_WIDTH-1:0]     cheek_sum_secord   ;
    output  [DATA_WIDTH-1:0]     dout               ;
    output                       dout_vld           ;

    reg                          bitslip            ;

    reg                          slip_flag          ;
    wire                         add_cnt            ;
    reg     [4:0]                cnt                ;
    wire    [DATA_WIDTH-1:0]     dout               ;
    reg                          dout_vld           ;
    
    wire    [DATA_WIDTH-1: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      ;
    wire                         shiftout1          ;
    wire                         shiftout2          ; 

    //例化ISERDESE2原语
    ISERDESE2 #(
        .DATA_RATE          ( "DDR"         ),// DDR, SDR
        .DATA_WIDTH         ( 10            ),// 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_Master (
        .O          (               ),// 1-bit output: Combinatorial output
        .Q1         ( q[9]          ),// Q1 - Q8: 1-bit (each) output: Registered data outputs
        .Q2         ( q[8]          ),
        .Q3         ( q[7]          ),
        .Q4         ( q[6]          ),
        .Q5         ( q[5]          ),
        .Q6         ( q[4]          ),
        .Q7         ( q[3]          ),
        .Q8         ( q[2]          ),
        .SHIFTOUT1  ( shiftout1     ),// SHIFTOUT1 : 1-bit (each) output: Data width expansion output ports
        .SHIFTOUT2  ( 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   (               )
    );
     ISERDESE2 #(
        .DATA_RATE          ( "DDR"         ),// DDR, SDR
        .DATA_WIDTH         ( 10             ),// 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           ( "FALSE"       ),// Select OFB path (FALSE, TRUE)
        .SERDES_MODE        ( "SLAVE"       ),// 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_Slave (
        .O          (               ),// 1-bit output: Combinatorial output
        .Q1         (               ),// Q1 - Q8: 1-bit (each) output: Registered data outputs
        .Q2         (               ),
        .Q3         ( q[1]          ),
        .Q4         ( q[0]          ),
        .Q5         (               ),
        .Q6         (               ),
        .Q7         (               ),
        .Q8         (               ),
        .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        (               ),// 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   (  shiftout1    ),
        .SHIFTIN2   (  shiftout2    )
    );

    //当没有完成校准时,如果检测到转换结果与要求不一致,则把该信号拉高。
    always@(posedge clk_div or posedge rst)begin
        if(rst)begin
            bitslip <= 1'b0;
        end//当没有校准,且没有处于校准阶段时检测到串并转换结果不为8'h5c或者8'h82时拉高;
        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  

        在DDR数据OSERDES2原语使用中,位宽大于8的时候,需要用到两个OSERDES2原语进行转换。连接方式如下图。

5  测试代码

`timescale 1ns / 1ns
module test ();
    localparam	CYCLE		= 	20			    ;    //系统时钟50M
    localparam	RST_TIME	= 	10			    ;    

    reg							clk			    ;   
    reg							rst_n		    ;

    wire    [9 : 0]             o_iserdese2     ;
    wire                        o_iserdese2_vld ;

    top u_top(
        .sys_clk            ( clk		        ),
        .rst_n              ( rst_n             ),
        .o_iserdese2        ( o_iserdese2       ),
        .o_iserdese2_vld    ( o_iserdese2_vld   )
    );

   
    initial begin
        clk = 0;
        forever #(CYCLE/2) clk = ~clk;
    end

   
    initial begin
        rst_n = 1;
        #2;
        rst_n = 0;
        #(RST_TIME*CYCLE);
        rst_n = 1;
  
    end

endmodule

        仿真亲测没有问题,具体方法查看可以上篇文章ISERDESR原语介绍中的DDR模式8:1串并转换,代码只是修改了PLL的采样时钟,ISERDES2与OSERDES2各添加了一个Slave原语模块,其他没有变化。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA一只小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值