一、是否可以
1.就我个人而言,虽然知道内部怎么实现的,但是目前我不知道怎么用verilog来实现
2.就目前了解,ODDR底层不是纯verilog来实现的,而是通过硬核来实现的
3.其本质是一个专用的选择器(Multiplexer) 和触发器(Flip-Flop) 的组合。
二、为啥不能用普通verilog来直接实现等效
1.时序性能
IOB这些电路是物理上最靠近IOB引脚的位置,其路径是经过精细该设计和优化的,
从而保证在极低的时钟到输出的延迟,非常潇的skew。通过普通的verilog代码在
FPGA fabric可编程逻辑区中实现的逻辑,其延迟和skew不确定性都会很大,不能
完全满足DDR时序要求。
2.时钟处理
普通逻辑无法直接使用一个时钟的正负边沿区驱动两个触发器,然后完美的去控制
MUX的切换时间,这个通过模拟电路或者数字集成电路就很好实现。
3.可靠性
专用硬件电路的行为是确定和可靠的。而用通用逻辑实现DDR功能,在高速率下很容易出现毛刺和时序违例。
三、功能模型
module oddr_model #(
parameter DDR_CLK_EDGE = "OPPOSITE_EDGE", // 模拟模式参数
parameter INIT = 1'b0, // 初始值
parameter SRTYPE = "SYNC" // 复位类型,本例只做简单同步
)(
output reg Q,
input C,
input CE,
input D1,
input D2,
input R,
input S
);
reg d1_reg, d2_reg;
// 上升沿触发的触发器,捕获D1
always @(posedge C) begin
if (R) begin
d1_reg <= 1'b0;
end else if (S) begin
d1_reg <= 1'b1;
end else if (CE) begin
d1_reg <= D1;
end
end
// 下降沿触发的触发器,捕获D2
always @(negedge C) begin
if (R) begin
d2_reg <= 1'b0;
end else if (S) begin
d2_reg <= 1'b1;
end else if (CE) begin
d2_reg <= D2;
end
end
// 用时钟选择要输出的数据
// 注意:实际硬件中这个MUX的切换速度极快,这里只是行为模拟
always @(*) begin
if (C) begin
Q = d1_reg; // 时钟高电平时,输出上升沿采样的D1
end else begin
Q = d2_reg; // 时钟低电平时,输出下降沿采样的D2
end
end
endmodule
四、接口
// 首先需要包含Xilinx的原语库,但通常Vivado会自动识别,无需手动include
// 直接实例化即可
ODDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q
.SRTYPE("SYNC") // 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 (for positive edge)
.D2(D2), // 1-bit data input (for negative edge)
.R(R), // 1-bit reset
.S(S) // 1-bit set
);