文章目录
-
- 一、前言
- 二、基本原理
- 三、补充内容
- 四、个人声明
一、前言
本文是FPGA IDDR基本原理的姊妹篇,建议先阅读IDDR原理部分内容。
二、基本原理
IDDR通过两个寄存器分别采集时钟上升沿和下降沿的数据信号实现双边沿数据转化为单边沿数据(详见文章《IDDR基本原理》)。而ODDR可视为IDDR的逆操作,同样采用双寄存器结构:一个寄存器在时钟上升沿输出数据,另一个在下降沿输出数据,然后通过数据选择器实现交替输出,基本电路结构如下图所示:
ODDR相比于IDDR原理更加简单,以下是具体实现和测试代码:
module oddr # (
/* d初始值 */
parameter D_INIT = 1'b0
)(
input wire clk,
input wire rstn,
input wire d0,
input wire d1,
output wire q
);
reg dff0, dff1;
/* dff0 */
always @ (posedge clk, negedge rstn) begin
if (~rstn)
dff0 <= D_INIT;
else
dff0 <= d0;
end
/* dff1 */
always @ (negedge clk, negedge rstn) begin
if (~rstn)
dff1 <= D_INIT;
else
dff1 <= d1;
end
/* q output */
assign q = clk? dff0: dff1;
endmodule
`timescale 1ns / 1ps
`timescale 1ns / 1ps
module tb_oddr();
parameter D_INIT = 1'b0;
reg clk, rstn;
reg d0, d1;
wire q;
initial begin
clk = 1'b0;
rstn = 1'b0;
d0 = 1'b0;
d1 = 1'b0;
#5
rstn = 1'b1;
d0 = 1'b0;
d1 = 1'b0;
#20
d0 = 1'b1;
d1 = 1'b0;
#20
d0 = 1'b1;
d1 = 1'b1;
#20
d0 = 1'b0;
d1 = 1'b0;
#20
d0 = 1'b0;
d1 = 1'b1;
#20
d0 = 1'b1;
d1 = 1'b1;
#20
d0 = 1'b1;
d1 = 1'b1;
#20
d0 = 1'b0;
d1 = 1'b1;
$stop();
end
always #10 clk = ~clk;
oddr # (
.D_INIT(D_INIT)
) u_oddr (
.clk(clk),
.rstn(rstn),
.d0(d0),
.d1(d1),
.q(q)
);
endmodule
仿真波形如图所示。在25至45ns的数据周期内,d0保持高电平,d1维持低电平。输出信号q在30-40ns期间呈现高电平,随后在40-50ns区间转为低电平。 
三、补充内容
各FPGA厂商的ODDR电路设计存在差异。下图为高云FPGA ODDR电路结构(参考Gowin UG289 图4-16),该设计在本文第二节所述电路的基础上额外集成了两级寄存器。
下图为安路FPGA ODDR电路结构(参考Anlogic TN805 图5-4),该设计在DFF1前端额外增加了一级寄存器(其具体作用个人目前尚不了解)。 
四、个人声明
本文由个人整理、创作,旨在进行个人学习、研究或记录,不用于任何商业性行为,文中部分内容参考以下资料:
- Xilinx Inc. 7 Series FPGA SelectIO Resources User Guide(UG471).
- Anlogic Inc. SF1 FPGA IO用户指南(TN805).
- Gowin Inc. 可编程通用管脚用户指南(UG289).
本文引用的任何第三方资料,其知识产权(包括但不限于著作权、商标权等)均归原作者或原始权利人所有。本文对这些内容不主张任何权利。
网硕互联帮助中心



评论前必须登录!
注册