自学内容网 自学内容网

Xilinx IDDR和 ODDR原语使用和仿真

// IODDR 回环 ,使用 SAME_EDGE 模式,注意的是 从 ODDR输出 时钟需要偏移90度,不然数据 上下沿采样错误
// 数据从 IDDR 输出时,最好将 数据和 frame 有效信号 同步在偏移90度的时钟下
// 本测试内容 是 50MHZ 的 8bit (1~126) 数据进入 IDDR – ODDR 输出。 IDDR 和 ODDR 时钟 200MHZ
后续研究 OPPOSITE_EDGE 模式。

代码没有进行优化
大家自行参考

`timescale 1ns / 1ps

// IODDR 回环 ,使用 SAME_EDGE 模式,注意的是 从 ODDR输出 时钟需要偏移90度,不然数据 上下沿采样错误
// 数据从 IDDR 输出时,最好将 数据和 frame 有效信号 同步在偏移90度的时钟下
// 本测试内容 是 50MHZ 的 8bit (1~126) 数据进入 IDDR -- ODDR 输出。 IDDR 和 ODDR 时钟 200MHZ

module IODDR(

    input i_clk_50m ,
    input i_clk_200m,
    input i_rst 
);


wire       w_data_o       ;
wire       w_data_valid_o ;
wire       locked;
wire       frame_h        ;
wire       frame_l        ;
wire       data_pin       ;
wire       data_nin       ;

reg  [7:0] r_cnt          ;
reg        r_valid        ;
reg  [7:0] r_data_i       ;                        
reg        datain_n       ;
reg        datain_p       ;
reg        r_data_pin     ;
reg        r_data_nin     ;
reg [3:0]  r_read_cnt     ;
reg [7:0]  r_dataout      ;
reg [1:0]  r_shift_data   ;
reg        r_data_valid_1d;
reg        r_data_valid_2d;
reg [3:0]  r_read_cnt_1d  ;
reg [3:0]  r_read_cnt_2d  ;
reg [7:0]  r_final_data   ;
reg        r_final_valid  ;
reg        r_data_valid   ;
reg [1:0]  r_frame_cnt    ;

   clk_wiz_0 clk_wiz_u0
   (
    // Clock out ports
    .clk_out1(clk_out1),     // output clk_out1
    // Status and control signals
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(i_clk_200m));   

always @ (posedge i_clk_50m )
begin
    if (i_rst || ~locked)
        r_valid <= 0;
    else if (r_cnt == 128 - 1)
        r_valid <= 0;    
    else if (r_cnt == 1)
        r_valid <= 1; 
    else
        r_valid <= r_valid;
end

always @ (posedge clk_out1 )
begin
     r_data_valid   <= frame_h;
    r_data_valid_1d <= r_data_valid;
end

always @ (posedge i_clk_50m )
begin
    if (i_rst || ~locked)
        r_cnt <= 0;
    else if (r_cnt == 256 -1)
        r_cnt <= 0; 
    else
        r_cnt <= r_cnt + 1;
end

always @ (posedge i_clk_50m)
begin
   r_data_i <= r_cnt ;
/*  if (i_rst || ~locked)
     r_data_i <= 0;
 else if (r_cnt == 1)
    r_data_i <= 8'b10101010;
 else if (r_cnt == 2)
     r_data_i <= 8'b01010101;
 else if (r_cnt == 3)
     r_data_i <= 8'b00110011; */
end

always @ (posedge i_clk_200m )
begin
    if (i_rst || ~locked)
        r_frame_cnt <= 0;
    else if (r_frame_cnt == 3)
        r_frame_cnt <= 0; 
    else if (r_valid)
        r_frame_cnt <= r_frame_cnt + 1;
    else
        r_frame_cnt <= r_frame_cnt;
end

always @ (posedge i_clk_200m )
begin
    if (i_rst || ~locked) begin
        datain_p <= 0;
        datain_n <= 0;
    end else begin
         case (r_frame_cnt) 
            0: begin
                datain_p <= r_data_i[7];
                datain_n <= r_data_i[6];
            end
            1: begin
                datain_p <= r_data_i[5];
                datain_n <= r_data_i[4];                  
            end        
            2: begin
                datain_p <= r_data_i[3];
                datain_n <= r_data_i[2];            
            end  
            3: begin
                datain_p <= r_data_i[1];
                datain_n <= r_data_i[0];      
            end   
            default :begin  
                datain_p <= 0;
                datain_n <= 0;                   
            end
         endcase
     end   
end

   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_dataout (
      .Q(w_data_o),   // 1-bit DDR output
      .C(i_clk_200m),   // 1-bit clock input
      .CE(1'b1), // 1-bit clock enable input
      .D1(datain_p), // 1-bit data input (positive edge)
      .D2(datain_n), // 1-bit data input (negative edge)
      .R(i_rst),   // 1-bit reset
      .S(1'b0)    // 1-bit set
   );

   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_valid (
      .Q(w_data_valid_o),   // 1-bit DDR output
      .C(i_clk_200m),   // 1-bit clock input
      .CE(1'b1), // 1-bit clock enable input
      .D1(r_valid), // 1-bit data input (positive edge)
      .D2(r_valid), // 1-bit data input (negative edge)
      .R(i_rst),   // 1-bit reset
      .S(1'b0)    // 1-bit set
   );

   IDDR #(
      .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE" 
                                      //    or "SAME_EDGE_PIPELINED" 
      .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
      .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) IDDR_datain (
      .Q1(data_pin), // 1-bit output for positive edge of clock
      .Q2(data_nin), // 1-bit output for negative edge of clock
      .C(clk_out1),   // 1-bit clock input
      .CE(1), // 1-bit clock enable input
      .D(w_data_o),   // 1-bit DDR data input
      .R(i_rst),   // 1-bit reset
      .S(0)    // 1-bit set
   );

   IDDR #(
      .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE" 
                                      //    or "SAME_EDGE_PIPELINED" 
      .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
      .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) IDDR_validin (
      .Q1(frame_h), // 1-bit output for positive edge of clock
      .Q2(frame_l), // 1-bit output for negative edge of clock
      .C(clk_out1),   // 1-bit clock input
      .CE(1), // 1-bit clock enable input
      .D(w_data_valid_o),   // 1-bit DDR data input
      .R(i_rst),   // 1-bit reset
      .S(0)    // 1-bit set
   );
 
always @ (posedge clk_out1)
begin
    r_data_pin      <= data_pin;
    r_data_nin      <= data_nin;
    r_data_valid_2d <= r_data_valid_1d;
    r_read_cnt_1d   <= r_read_cnt;
    r_read_cnt_2d   <= r_read_cnt_1d;

end
 
 always @ (posedge clk_out1 )
begin
    if (i_rst || ~locked)
        r_read_cnt <= 0;
    else if (r_read_cnt == 3)
        r_read_cnt <= 0; 
    else if (r_data_valid_1d)
        r_read_cnt <= r_read_cnt + 1;
    else
        r_read_cnt <= r_read_cnt;
end

always @ (posedge clk_out1 )
begin
    if (i_rst || ~locked) begin
        r_shift_data <= 0;
    end else if (r_data_valid_1d) begin
        r_shift_data <= {r_data_pin,r_data_nin};
    end   
end

always @ (posedge clk_out1 )
begin
    if (i_rst || ~locked) begin
        r_dataout <= 0;
    end else if (r_data_valid_2d) begin
        r_dataout <= {r_dataout[5:0],r_shift_data};
    end   
end

always @ (posedge clk_out1 )
begin
    if (i_rst || ~locked) begin
        r_final_data <= 0;
    end else if (r_read_cnt_2d == 3) begin
        r_final_data <= r_dataout;   
    end else begin
        r_final_data <= 0;   
    end
end

always @ (posedge clk_out1 )
begin
    if (i_rst || ~locked) begin
        r_final_valid <= 0;
    end else if (r_read_cnt_2d == 3) begin
        r_final_valid <= 1;
    end else begin
        r_final_valid <= 0;   
    end
end

endmodule

`timescale 1ns / 1ps
module tb_IODDR();

reg i_clk_50m   ;
reg i_clk_200m  ;
reg i_rst       ;

initial begin 
    i_clk_50m   = 1'b1;
    i_clk_200m  = 1'b1;
    i_rst       = 1'b1;
    
    #100
    i_rst       = 1'b0; 

end

always #10   i_clk_50m = ~ i_clk_50m;
always #2.5 i_clk_200m = ~ i_clk_200m;

IODDR IODDR_u0(

    .i_clk_50m  (i_clk_50m  ),
    .i_clk_200m (i_clk_200m ),
    .i_rst      (i_rst      )
);


endmodule

在这里插入图片描述
IDDR 数据输出延时一拍
数据输出延时一拍
数据输入 的时候,ODDR 输出延时一拍
数据输入 的时候,ODDR 输出延时一拍


原文地址:https://blog.csdn.net/gw123456780/article/details/144353905

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!