IDDR的输入输出引脚包括时钟输入C、时钟取反输入CB、数据输入D(在时钟信号C的上升沿与下降沿都发生变化)、异步复位R(高电平有效)与数据输出Q1和数据输出Q2。
IDDR的原语如下:
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(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
.D(D), // 1-bit input: Serial Data Input
.R(R) // 1-bit input: Active-High Async Reset
);
对于Kintex ultrascale的IDDRE1,有三种模式:OPPOSITE_EDGE、SAME_EDGE、 SAME_EDGE_PIPELINED,这三种模式下,输出信号Q1与Q2采样的数据分别是在时钟信号C的上升沿处的数据和下降沿处的数据,这是一致的。但是Q1与Q2发生变化的时间对于三种模式是有区别的。
在OPPOSITE_EDGE模式下,输出信号Q1在上升沿处对输入信号D进行采样,同时在该上升沿处Q1输出变为采样值;而输出信号Q2在下降沿处对输入信号D进行采样,同时在该下降沿处Q2输出变为采样值,如下图所示。
在SAME_EDGE模式下,输出信号Q1与Q2发生变化的时间都是在上升沿处,但是不在同一个上升沿,两个变化的时间相差一个时钟周期。输出信号Q1在上升沿处对输入信号D进行采样,同时在该上升沿处Q1输出变为采样值;而输出信号Q2在下降沿处对输入信号D进行采样,同时在下一个上升沿沿处Q2输出变为采样值,如下图所示。
在SAME_EDGE_PIPELINED模式下,输出信号Q1与Q2发生变化的时间都是在上升沿处,而且在同一个上升沿。输出信号Q1在上升沿处对输入信号D进行采样,同时在下一个上升沿处Q1输出变为采样值;而输出信号Q2在下降沿处对输入信号D进行采样,同时在下一个上升沿沿处Q2输出变为采样值,如下图所示。
相同点 | 不同点 | |
---|---|---|
OPPOSITE_EDGE | Q1采样的是上升沿处D的值,Q2采样的是下降沿处D的值 | Q1与Q2数据发生变化是在不同的边沿,Q1数据发生变化是在采样的上升沿处,Q2数据发生变化是在采样的下降沿处 |
SAME_EDGE | Q1采样的是上升沿处D的值,Q2采样的是下降沿处D的值 | 与OPPOSITE_EDGE 模式不同的是:Q1与Q2数据发生变化是在相同的边沿,但是相差一个时钟周期,Q1数据发生变化是在采样的上升沿处,Q2数据发生变化是在采样的下降沿的下一个上升沿 |
SAME_EDGE_PIPELINED | Q1采样的是上升沿处D的值,Q2采样的是下降沿处D的值 | Q1与Q2数据发生变化是在相同的边沿,与SAME_EDGE 模式不同的是:Q1与Q2变化发生在同一个上升沿,都是在下一个上升沿处 |
ODDR的输入输出引脚包括数据输入D1、数据输入D2、时钟信号C、异步复位信号SR(高电平有效)和数据输出Q(在时钟信号C的上升沿和下降沿均会发生变化)。
ODDR的原语如下:
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
);
与IDDR不同的是,ODDR只有一种模式——OPPOSITE_EDGE,在该模式下:数据输出Q在上升沿处的数据变为在上升沿处对输入数据D1的采样值,在下降沿处变为在上升沿处对输入数据D2的采样值,如下图所示。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/06/05 20:10:15
// Design Name:
// Module Name: iddr_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module iddr_top
(
input clk ,
input rst ,
input din ,
output dout_1,
output dout_2
);
wire clk_opposite;
// <-----Cut code below this line---->
// IDDRE1: Dedicated Double Data Rate (DDR) Input Register
// Kintex UltraScale
// Xilinx HDL Language Template, version 2021.1
IDDRE1 #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // 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(dout_1), // 1-bit output: Registered parallel output 1
.Q2(dout_2), // 1-bit output: Registered parallel output 2
.C(clk), // 1-bit input: High-speed clock
.CB(clk_opposite), // 1-bit input: Inversion of High-speed clock C
.D(din), // 1-bit input: Serial Data Input
.R(rst ) // 1-bit input: Active-High Async Reset
);
// End of IDDRE1_inst instantiation
assign clk_opposite = ~clk;
endmodule
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/06/05 20:17:59
// Design Name:
// Module Name: tb_iddr_oddr
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_iddr_oddr();
reg clk,rst;
reg din;
wire dout_1,dout_2;
initial begin
clk = 1'b1;
rst <= 1'b1;
#200
rst <= 1'b0;
#10
repeat(100) begin
#5
din = {$random}%2;
#5
din = {$random}%2;
end
end
always #5 clk = ~clk;
iddr_top iddr_top_inst
(
.clk (clk ),
.rst (rst ),
.din (din ),
.dout_1(dout_1),
.dout_2(dout_2)
);
endmodule
分别对三种模式进行仿真,可以看到仿真结果与前面的理论结果一致。
(1)OPPOSITE_EDGE模式
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/06/05 20:10:29
// Design Name:
// Module Name: oddr_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module oddr_top(
input clk ,
input rst ,
input din_1 ,
input din_2 ,
output dout
);
// ODDRE1 : In order to incorporate this function into the design,
// Verilog : the following instance declaration needs to be placed
// instance : in the body of the design code. The instance name
// declaration : (ODDRE1_inst) and/or the port declarations within the
// code : parenthesis may be changed to properly reference and
// : connect this function to the design. All inputs
// : and outputs must be connected.
// <-----Cut code below this line---->
// ODDRE1: Dedicated Double Data Rate (DDR) Output Register
// Kintex UltraScale
// Xilinx HDL Language Template, version 2021.1
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(dout), // 1-bit output: Data output to IOB
.C(clk), // 1-bit input: High-speed clock input
.D1(din_1), // 1-bit input: Parallel data input 1
.D2(din_2), // 1-bit input: Parallel data input 2
.SR(rst ) // 1-bit input: Active-High Async Reset
);
// End of ODDRE1_inst instantiation
endmodule
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/06/05 20:17:59
// Design Name:
// Module Name: tb_iddr_oddr
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_iddr_oddr();
reg clk,rst;
reg din_1,din_2;
wire dout;
initial begin
clk = 1'b1;
rst <= 1'b1;
#200
rst <= 1'b0;
#12
repeat(100) begin
#10
din_1 = {$random}%2;
din_2 = {$random}%2;
end
end
always #5 clk = ~clk;
oddr_top oddr_top_inst
(
.clk (clk ),
.rst (rst ),
.din_1(din_1),
.din_2(din_2),
.dout (dout )
);
endmodule
对ODDR进行仿真,可以看到仿真结果与前面的理论结果一致。在上升沿处,输出dout与上上升沿处输入din_1的值一致;在下降沿处,输出dout与上升沿处输入din_2的值一致。