Xilinx IDDR和 ODDR原语使用和仿真

// IODDR 回环 ,使用 SAME_EDGE 模式,注意的是 从 ODDR输出 时钟需要偏移90度,不然数据 上下沿采样错误

// 数据从 IDDR 输出时,最好将 数据和 frame 有效信号 同步在偏移90度的时钟下

// 本测试内容 是 50MHZ 的 8bit (1~126) 数据进入 IDDR -- ODDR 输出。 IDDR 和 ODDR 时钟 200MHZ

后续研究 OPPOSITE_EDGE 模式。

代码没有进行优化

大家自行参考

c 复制代码
`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
c 复制代码
`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 输出延时一拍

相关推荐
技术小白爱FPGA4 小时前
Xilinx LVDS 接口中的时钟对齐模块的RTL编写
fpga开发
Anin蓝天(北京太速科技-陈)4 小时前
204-基于Xilinx Virtex-6 XC6VLX240T 和TI DSP TMS320C6678的信号处理板
嵌入式硬件·fpga开发·信号处理
ThreeYear_s17 小时前
基于FPGA的智能电子密码指纹锁(开源全免)
fpga开发·开源
我爱C编程1 天前
【硬件测试】基于FPGA的4FSK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
fpga开发·信道模块·snr·4fsk调制解调
正在努力的小河1 天前
FPGA实战篇(按键控制LDE实验)
fpga开发
whik11941 天前
Microsemi Libero SoC免费许可证申请指南(Microchip官网2024最新方法)
fpga开发
Leventure_轩先生1 天前
[Verilog]第一个流水灯项目的一些疑问和思考
fpga开发
∑狸猫不是猫2 天前
数字图像处理(17):RGB与HSL互转
图像处理·计算机视觉·fpga开发
@晓凡2 天前
移植NIOS10.1工程,NIOS10.1路径修改
fpga开发·eclipse·nios ii