xilinx原语详解及仿真——ODDR

  ODDR位于OLOGIC中,可以把单沿传输的数据转换为双沿传输的数据, 在讲解ODDR功能之前,需要先了解OLOGIC的结构及功能。

1、OLOGIC

  OLOGIC块位于IOB的内侧,FPGA内部信号想要输出到管脚,都必须经过OLOGIC。OLOGIC资源的类型为OLOGICE2(HP I/O Bank)和OLOGICE3(HR I/O Bank),两者在功能和结构上是相同的,所以本文称为OLOGIC。

  图1是OLOGIC的结构框图,分为上下两部分,下半部分用于配置输出数据路径,上半部分用于配置三态控制路径,分别实现对数据、三态信号进行单沿转双沿的功能,两部分具有共同的时钟 (CLK),但是使能信号不同(OCE和TCE)。

xilinx原语详解及仿真——ODDR_第1张图片

图1 OLOGIC结构框图

  如果输出的信号不使用OLOGIC中的ODDR功能,那么此时信号从图1中红线路径进行传输,从组合逻辑电路输出到IOB模块。如果要使用OLOGIC模块中的D触发器功能,那么信号从D1进入OLOGIC模块,沿绿色信号线进行传输。如果要使用OLOGIC的ODDR功能,把单沿传输的信号转换为双沿传输的信号,此时需要两个输入信号D1、D2沿蓝色路径进行传输。

  图2是FPGA中OLOGIC实际的框图,因为该电路还可以被配置为OSERDESE2,所以相比图1会多出一些信号端口。

xilinx原语详解及仿真——ODDR_第2张图片

图2 OLOGIC在FPGA中结构框图

2、ODDR原语

  图3是ODDR原语框图,与IDDR一样不支持同时复位和置位。ODDR端口信号如表1所示,表2描述了ODDR原语的可用参数。

xilinx原语详解及仿真——ODDR_第3张图片

图3 ODDR原语框图

表1 ODDR端口信号
端口名 含义
C 时钟输入信号。
CE 钟使能信号,高电平有效。
D1、D2 ODDR输入信号。
S/R 置位/复位引脚,高电平有效。
Q ODDR输出信号。
表2 ODDR原语的参数
参数名 含义 取值
DDR_CLK_EDGE ODDR工作模式 OPPOSITE_EDGE (默认), SAME_EDGE
INIT 设置Q端口的初始值 0(默认),1
SRTYPE 设置复位/置位相对于时钟的类型 ASYNC, SYNC(默认)

  上述的信号和参数都比较简单,与前面IDDR原语相似,不做过多解释。ODDR只有两种工作模式,相比IDDR会少一种,下文对两种模式进行讲解。

  图4是OPPOSITE_EDGE模式的时序图,在时钟CLK上升沿采集D1信号D1A,并在时钟上升沿把D1A输出到OQ。然后在时钟CLK下降沿采集D2信号D2A,并在下降沿将采集到的信号输出。这种模式使用起来会相对麻烦,FPGA内部需要在时钟上升沿给D1赋值,在时钟下降沿给D2赋值,一般不使用。

xilinx原语详解及仿真——ODDR_第4张图片

图4 OPPOSITE_EDGE模式

  图5是SAME_EDGE模式的时序图,在时钟CLK上升沿 同时采集D1、D2的数据,OQ再时钟上升沿输出采集的D1数据,再下降沿输出采集的D2数据。这种方式实现比较简单,属于常用模式。

xilinx原语详解及仿真——ODDR_第5张图片

图5 SAME_EDGE模式

3、ODDR模式仿真

​ODDR原语的模板如下所示:

   ODDR #(
      .DDR_CLK_EDGE("OPPOSITE_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_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
   );

  接下来对ODDR的两种工作模式进行仿真,对应的设计文件如下所示,din0在内部D触发器打一拍后得到dout0输出,din0经过OLOGIC内部的D触发器打一拍后得到dout1输出。两个单沿输入的信号din1、din2转化位单沿信号dout2,对应代码如下所示。

module oddr_ctrl(
    input       clk      ,//系统时钟信号;
    input       rst      ,//系统复位信号,高电平有效;

    input       clk_en   ,//时钟使能信号;
    input       din0     ,//输入数据;
    input       din1     ,//输入数据;
    input       din2     ,//输入数据;
    output      dout0    ,//输出数据
    output      dout1    ,//输出数据
    output      dout2    
); 
    reg         dout0   ;
    (* IOB = "TRUE" *)reg dout1 ;//将dout1放在ILOGICE中;

    always@(posedge clk)begin
        dout0 <= din0;
        dout1 <= din0;
    end

   //例化ODDR原语
    ODDR #(
        .DDR_CLK_EDGE ( "OPPOSITE_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_inst (
        .Q    ( dout2   ),// 1-bit DDR output
        .C    ( clk     ),// 1-bit clock input
        .CE   ( clk_en  ),// 1-bit clock enable input
        .D1   ( din1    ),// 1-bit data input (positive edge)
        .D2   ( din2    ),// 1-bit data input (negative edge)
        .R    ( rst     ),// 1-bit reset
        .S    ( 1'b0    ) // 1-bit set
    );

endmodule

对应的Test​Bench文件如下所示:

`timescale 1 ns/1 ns
module test();
    parameter	CYCLE		=   10      ;//系统时钟周期,单位ns,默认10ns;

    reg			                clk     ;//系统时钟,默认100MHz;
    reg			                rst     ;//系统复位,默认高电平有效;
    reg                         clk_en  ;
    reg                         din0    ;
    reg                         din1    ;
    reg                         din2    ;

    wire                        dout0   ;
    wire                        dout1   ;
    wire                        dout2   ;

    oddr_ctrl  u_oddr_ctrl (
        .clk        ( clk       ),
        .rst        ( rst       ),
        .clk_en     ( clk_en    ),
        .din0       ( din0      ),
        .din1       ( din1      ),
        .din2       ( din2      ),
        .dout0      ( dout0     ),
        .dout1      ( dout1     ),
        .dout2      ( dout2     )
    );

    //生成周期为CYCLE数值的系统时钟;
    initial begin
        clk = 1;
        forever #(CYCLE/2) clk = ~clk;
    end

    //生成复位信号;
    initial begin
        rst = 0;
        #2;
        rst = 1;//开始时复位10个时钟;
        #(10*CYCLE);
        rst = 0;
    end

    initial begin
        #1;
        clk_en = 1'b0;din2 = 1'b0;
        din0 = 1'b0;din1 = 1'b0;
        #(CYCLE*20);
        clk_en = 1'b1;
        #(CYCLE);
        repeat(100)begin//产生100个双沿时钟数据。
            #(CYCLE/2);
            din0 = ({$random} % 2);
            din1 = ({$random} % 2);
            #(CYCLE/2);
            din2 = ({$random} % 2);
        end
        #(CYCLE);
        clk_en = 1'b0;
        #(10*CYCLE);
        $stop;//停止仿真;
    end

endmodule

  首先对OPPOSITE_EDGE模式进行仿真,对应的TestBench代码如下所示,仿真结果如图6所示。

xilinx原语详解及仿真——ODDR_第6张图片

图6 OPPOSITE_EDGE模式

  图6仿真结果与图4的时序图一致,不做过多解释。

  然后对SAME_EDGE模式进行仿真,对应的设计文件:

module oddr_ctrl(
    input       clk      ,//系统时钟信号;
    input       rst      ,//系统复位信号,高电平有效;

    input       clk_en   ,//时钟使能信号;
    input       din0     ,//输入数据;
    input       din1     ,//输入数据;
    input       din2     ,//输入数据;
    output      dout0    ,//输出数据
    output      dout1    ,//输出数据
    output      dout2    
); 
    reg         dout0   ;
    reg         doutr   ;
    (* IOB = "TRUE" *)reg dout1 ;//将dout1放在ILOGICE中;

    always@(posedge clk)begin
        doutr <= din0;
        dout0 <= doutr;
        dout1 <= doutr;
    end

   //例化ODDR原语
    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_inst (
        .Q    ( dout2   ),// 1-bit DDR output
        .C    ( clk     ),// 1-bit clock input
        .CE   ( clk_en  ),// 1-bit clock enable input
        .D1   ( din1    ),// 1-bit data input (positive edge)
        .D2   ( din2    ),// 1-bit data input (negative edge)
        .R    ( rst     ),// 1-bit reset
        .S    ( 1'b0    ) // 1-bit set
    );

endmodule

TestBench文件如下所示:

`timescale 1 ns/1 ns
module test();
    parameter	CYCLE		=   10      ;//系统时钟周期,单位ns,默认10ns;

    reg			                clk     ;//系统时钟,默认100MHz;
    reg			                rst     ;//系统复位,默认高电平有效;
    reg                         clk_en  ;
    reg                         din0    ;
    reg                         din1    ;
    reg                         din2    ;

    wire                        dout0   ;
    wire                        dout1   ;
    wire                        dout2   ;

    oddr_ctrl  u_oddr_ctrl (
        .clk        ( clk       ),
        .rst        ( rst       ),
        .clk_en     ( clk_en    ),
        .din0       ( din0      ),
        .din1       ( din1      ),
        .din2       ( din2      ),
        .dout0      ( dout0     ),
        .dout1      ( dout1     ),
        .dout2      ( dout2     )
    );

    //生成周期为CYCLE数值的系统时钟;
    initial begin
        clk = 1;
        forever #(CYCLE/2) clk = ~clk;
    end

    //生成复位信号;
    initial begin
        rst = 0;
        #2;
        rst = 1;//开始时复位10个时钟;
        #(10*CYCLE);
        rst = 0;
    end

    initial begin
        #1;
        clk_en = 1'b0;din2 = 1'b0;
        din0 = 1'b0;din1 = 1'b0;
        #(CYCLE*20);
        clk_en = 1'b1;
        #(CYCLE);
        repeat(100)begin//产生100个双沿时钟数据。
            #(CYCLE);
            din0 = ({$random} % 2);
            din1 = ({$random} % 2);
            din2 = ({$random} % 2);
        end
        #(CYCLE);
        clk_en = 1'b0;
        #(10*CYCLE);
        $stop;//停止仿真;
    end

endmodule

仿真结果如图7所示。

xilinx原语详解及仿真——ODDR_第7张图片

图7 SAME_EDGE模式

  图7仿真结果与图5基本一致,不再过多解释。图8是该模式下时钟使能无效时仿真结果,此时输出信号将保持不变。

xilinx原语详解及仿真——ODDR_第8张图片

图8 SAME_EDGE模式下EN信号拉低

  上述仿真均与前文理论一致,下面将工程信号引脚分配,对工程进行编译,查看走线的图。

4、OLOGIC中触发器(OFD)的使用方式

  在vivado中打开走线的方式在讲解IDDR原语时已经进行了讲解,本文不再赘述。

  前文的代码中dout0与dout1的代码都相同,都是使用D触发器对din0打一拍,然后输出,通过查看dout0和dout1的寄存器位置,得到OLOGIC中组合电路和触发器功能的使用方式。图9是din0到dout0信号的走线图,红框处是寄存器所在位置,白线是信号的走线。

xilinx原语详解及仿真——ODDR_第9张图片

图9 dout0信号走向

  dout0信号是没有使用OLOGIC中的触发器和ODDR功能的,图10就是dou0信号经过OLOGIC时的路径,与前文讲解一致,直接经过组合逻辑输出。

xilinx原语详解及仿真——ODDR_第10张图片

图10 dout0经过OLOGIC

  如图11所示,是dout1信号在FPGA内部的走向,路径上又两个触发器,其中一个在OLOGIC中。

xilinx原语详解及仿真——ODDR_第11张图片

图11 dout1信号走向

  将OLOGIC放大,如图12所示,可知dout1触发器在OLOGIC中。

xilinx原语详解及仿真——ODDR_第12张图片

图12 dout1经过OLOGIC

  最后查看dout2信号的走向,如图13所示,din1和din2输入FPGA后,在OLOGIC进行单沿转双沿信号,然后通过dout2管脚输出。

xilinx原语详解及仿真——ODDR_第13张图片

图13 dout2信号走向

  将对应的OLOGIC放大,可见其实现的是ODDR功能,信号流向与前文讲解一致。

xilinx原语详解及仿真——ODDR_第14张图片

图13 dout2经过OLOGIC

  综上,OLOGIC与ILOGIC功能类似,本文主要是讲解ODDR的工作模式,并对工作模式进行仿真,同时将OLOGIC的使用方式进行讲解。掌握ODDR使用方式的同时,也知道如何使用OLOGIC中的触发器(使用IOB=TRUE原语,查看设计文件中dout1信号的定义)功能,以及OLOGIC在FPGA中的位置。

  OLOGIC中的触发器相对于FPGA内部触发器更靠近管脚,并且触发器输出与IOB之间的路径是固定的,对于多bit数据输出更有利于对齐。

  最后需要此工程文件的用户,在公众号后台回复“ODDR”(不包括引号)即可。

你可能感兴趣的:(fpga开发)