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 输出延时一拍

相关推荐
Hello-FPGA7 小时前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安9 小时前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha60169 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld9 小时前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家21 小时前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家1 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
FPGA小迷弟2 天前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha1282 天前
CPU 内部结构是什么?---deepseek
fpga开发
abc light2 天前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072193 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理