当前位置:   article > 正文

赛灵思7系列 ODDR、IDDR原语 与 ultrascale系列ODDRE1 、IDDRE1 原语_赛灵思源语

赛灵思源语

一、赛灵思7系列FPGA


1.1 ODDR:实现数据的双边沿发送


        支持两种模式:OPPOSITE_EDGE模式、SAME_EDGE模式

   ODDR #(
      .DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1,Q初始值
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_inst (
      .Q(Q),   // 1-bit DDR output
      .C(C),   // 1-bit clock input
      .CE(CE), // 1-bit clock enable input,高电平使能发送数据
      .D1(D1), // 1-bit data input (positive edge)
      .D2(D2), // 1-bit data input (negative edge)
      .R(R),   // 1-bit reset,高电平复位
      .S(S)    // 1-bit set,高电平置位
   );

1.1.1、OPPOSITE_EDGE模式

        时钟上升沿提取D1数据赋值给Q,时钟下降沿提取D2数据赋值给Q。Q输出相比较于时钟边沿,有一定的延迟。 

 1.1.2、SAME_EDGE模式

        时钟上升沿提取D1和D2,然后依次在一个时钟内赋值给Q,发送出去。 

 1.2 IDDR:实现输入信号的时钟双边沿接收

        支持3种模式:OPPOSITE_EDGE模式、SAME_EDGE模式、SAME_EDGE_PIPELINED模式。

   IDDR #(
      .DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE" 
                                      //    or "SAME_EDGE_PIPELINED" 
      .INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1,Q1的初始值
      .INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1  Q2的初始值
      .SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC" 
   ) IDDR_inst (
      .Q1(Q1), // 1-bit output for positive edge of clock
      .Q2(Q2), // 1-bit output for negative edge of clock
      .C(C),   // 1-bit clock input
      .CE(CE), // 1-bit clock enable input,高电平时接收新数据
      .D(D),   // 1-bit DDR data input,IOB输入
      .R(R),   // 1-bit reset,高电平复位
      .S(S)    // 1-bit set,高电平置位
   );

1.2.1、OPPOSITE_EDGE模式

        时钟上升沿的DDR数据赋值给Q1,时钟下降沿时的数据赋值给Q2,Q1与Q2的输出相比较时钟上升沿与下降沿延迟了一段时间。

1.2.2、SAME_EDGE模式

        在时钟上升沿同时将DDR数据赋值给Q1和Q2。时序图如下。CE有效后第一个时钟内,Q2为无效值。

 1.2.3、SAME_EDGE_PIPELINED模式

        在时钟上升沿将DDR数据赋值给Q1与Q2,Q1与Q2进行了流水线处理。

二、ultrascale架构FPGA

2.1、ODDRE1 实现数据的双边沿发送

        仅支持SAME_EDGE模式。时钟上升沿提取数据,在一个时钟周期内发送出去。

ODDRE1 #(
      .IS_C_INVERTED(1'b0),      // Optional inversion for C,信号取反
      .IS_D1_INVERTED(1'b0),     // Unsupported, do not use
      .IS_D2_INVERTED(1'b0),     // Unsupported, do not use
      .SIM_DEVICE("ULTRASCALE"), // Set the device version for simulation functionality (ULTRASCALE)
      .SRVAL(1'b0)               // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1),复位后初始值
   )
   ODDRE1_inst (
      .Q(Q),   // 1-bit output: Data output to IOB
      .C(C),   // 1-bit input: High-speed clock input
      .D1(D1), // 1-bit input: Parallel data input 1
      .D2(D2), // 1-bit input: Parallel data input 2
      .SR(SR)  // 1-bit input: Active-High Async Reset
   );

2.2、IDDRE1 实现数据的双边沿发送

        支持3种模式:OPPOSITE_EDGE模式、SAME_EDGE模式、SAME_EDGE_PIPELINED模式。

      IDDRE1 #(
      .DDR_CLK_EDGE("OPPOSITE_EDGE"), // IDDRE1  mode (OPPOSITE_EDGE,                                                                         SAME_EDGE, SAME_EDGE_PIPELINED)
      .IS_CB_INVERTED(1'b0),   // Optional inversion for CB,0时不对CB取反,1时对CB取反
      .IS_C_INVERTED(1'b0)      // Optional inversion for C,0时不对C取反,1时对C取反
   )
   IDDRE1_inst (
      .Q1(Q1), // 1-bit output: Registered parallel output 1
      .Q2(Q2), // 1-bit output: Registered parallel output 2
      .C(C),   // 1-bit input: High-speed clock
      .CB(CB), // 1-bit input: Inversion of High-speed clock C,C时钟的取反输入
      .D(D),   // 1-bit input: Serial Data Input
      .R(R)    // 1-bit input: Active-High Async Reset,高电平有效
   );

2.2.1、OPPOSITE_EDGE模式

        时钟上升沿的DDR数据赋值给Q1,时钟下降沿时的数据赋值给Q2

 2.2.2、SAME_EDGE模式

        在时钟上升沿。Q1与Q2同时有效。

2.2.3、SAME_EDGE_PIPELINED模式

        相似与SAME_EDGE模式,数据Q1与Q2在时钟上升沿同时有效,不过数据对没有被拆分到不同时钟。

三、通过实例解析原语

        假设有一需求,将SPARTAN7 8bits位宽的数据,采用双边沿DDR的方式发送Ultrascale系列的任意FPGA上。为实现该需求进行设计(仿真模型设计)。
        首先确认spartan7需要使用的原语为ODDR,ultrascale FPGA使用原语为IDDRE1。

Spartan7示例程序:


 

`timescale 1ns/1ps

module S7_model
    (output ddr_clk,//DDR数据同步时钟
    output data_valid,//数据有效标志
    output [3:0] ddr_data
);

//-------------------模拟生成时钟---------
reg clk=0;//模拟生成100M时钟
always
begin
    #5 clk <= ~clk;
end

//----------------------基于clk实现逻辑----------------
wire clk_bufg;
wire not_clk_bufg;
reg [7:0] clk_cnt =0;//时钟计数
reg data_valid;
reg [7:0]data=0;
wire [3:0] data_pos;
wire [3:0] data_neg;

assign ddr_clk = clk_bufg;
   BUFG BUFG_inst (
      .O(clk_bufg), // 1-bit output: Clock output.
      .I(clk)  // 1-bit input: Clock input.
   );


always@(posedge clk_bufg)
begin
    clk_cnt <= #1 clk_cnt + 1'b1;
end

always@(posedge clk_bufg)
begin
    if(clk_cnt >= 8'h80) begin//clk_cnt从0x80到0x00有效
        #1 data_valid <= 1'b1;
         data <= clk_cnt;
     end
     else begin
        #1 data_valid <= 1'b0;
     end
end

assign data_pos = data[3:0];
assign data_neg =data [7:4];

//上升沿发送data_pos,下降沿发送data_neg.因为数据经过ODDR输出时存在延时,
//因此接收数据时,应该是上升沿接收data_neg,下降沿接收data_pos
    generate
        genvar i;
        for(i=0;i<=3;i=i+1) begin
             ODDR #(
              .DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE" 
              .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1
              .SRTYPE("ASYNC") // Set/Reset type: "SYNC" or "ASYNC" 
           ) ODDR_inst (
              .Q(ddr_data[i]),   // 1-bit DDR output
              .C(clk_bufg),   // 1-bit clock input
              .CE(1'b1), // 1-bit clock enable input
              .D1(data_pos[i]), // 1-bit data input (positive edge)
              .D2(data_neg[i]), // 1-bit data input (negative edge)
              .R(1'b0),   // 1-bit reset
              .S(1'b0)    // 1-bit set
           );
        end
    endgenerate

endmodule

Ultra FPGA示例程序


`timescale 1ns / 1ps
module ultra_model(
    input ddr_clk,//DDR数据同步时钟
    input data_valid,//数据有效标志
    input [3:0] ddr_data
    );
wire [3:0] ddr_data_pos;//
wire [3:0] ddr_data_neg;//
wire [7:0] rx_data;//还原的8bits数据
reg rx_valid;//还原的数据有效标志

wire ddr_clk_bufg;

   BUFG BUFG_inst (
      .O(ddr_clk_bufg), // 1-bit output: Clock output.
      .I(ddr_clk)  // 1-bit input: Clock input.
   );
   
  always@(posedge ddr_clk_bufg)
  begin
    #1 rx_valid <=data_valid;
  end
  
  assign rx_data = {ddr_data_pos,ddr_data_neg};
  
        generate
        genvar i;
        for(i=0;i<=3;i=i+1) begin
           IDDRE1 #(
              .DDR_CLK_EDGE("OPPOSITE_EDGE"), // IDDRE1 mode (OPPOSITE_EDGE, SAME_EDGE, SAME_EDGE_PIPELINED)
              .IS_CB_INVERTED(1'b0),          // Optional inversion for CB
              .IS_C_INVERTED(1'b0)            // Optional inversion for C
           )
           IDDRE1_inst (
              .Q1(ddr_data_pos[i]), // 1-bit output: Registered parallel output 1
              .Q2(ddr_data_neg[i]), // 1-bit output: Registered parallel output 2
              .C(ddr_clk_bufg),   // 1-bit input: High-speed clock
              .CB(~ddr_clk_bufg), // 1-bit input: Inversion of High-speed clock C
              .D(ddr_data[i]),   // 1-bit input: Serial Data Input
              .R(1'b0)    // 1-bit input: Active-High Async Reset
           );
        end
    endgenerate
    
endmodule

仿真顶层文件


`timescale 1ns/1ps

module testbench_ddr();


wire  ddr_clk;//DDR数据同步时钟
wire  data_valid;//数据有效标志
wire  [3:0] ddr_data;

S7_model S7_model
(   .ddr_clk(ddr_clk),//DDR数据同步时钟
    .data_valid(data_valid),//数据有效标志
    .ddr_data(ddr_data)
);


ultra_model ultra_model
(   .ddr_clk(ddr_clk),//DDR数据同步时钟
    .data_valid(data_valid),//数据有效标志
    .ddr_data(ddr_data)
);

endmodule

 仿真结果截图:

        可以看到,Spartan7有效数据0x80、0x81、0x82·····,在ultra_model模块成功接收到0x80、0x81、0x82···

        需要注意的是,S7上升沿发送数据A,则ultra接收该数据时,只能在下降沿提取到该数据A。因为A滞后于时钟上升沿。如果还是想在ultra FPGA的上升沿提取到该数据,则需要采取措施调整一下时钟数据的时序。比如:考虑在ultraFPGA使用IDELAYE3延迟一下时钟输入引脚,或者在spartan7上使用ODELAYE2,延迟以下数据输出引脚。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/779115
推荐阅读
相关标签
  

闽ICP备14008679号