fpga锁存器设计
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if (g == 1'b1) q <= 0; else if (a == 1'bl) q <= b;
end 推荐的编码风格: always @(g1 or g2 or a or b) begin:
q <= 1'b0 ; if (gl == 1'b1) q <= a; else if (g2 == 1'bl) q <= b;
Page 3 of 8
让锁存器不再让人头痛
www.edacn.net/bbs
设计者就不可能完成PCI规范中对Reset功能的定义。为了设计是可测试的,可以采用如图1所 示的方法。它们使用多选的方法,提供一般功能或者I/O接口的数据。多选器的选择控制位来自 于扫描控制全能的测试模式管脚。
图1 让锁存器变得可测试 避免产生组合电路反馈 组合电路反馈是指组合逻辑电路形式的反馈环路.组合反馈环路会引发一系列问题,包括会使精 确静态时序分析难以实现。如图2、3所示。 不好:出现组合环路
process (state, bus_request) begin -- 对输入进行初始化被避免产生锁存器 bus_hold <= ‘0’;
Page 2 of 8
让锁存器不再让人头痛
www.edacn.net/bbs
bus_interrupt <= ‘0’; case (state) ... ... end process; 例 5 通过对所有输入条件赋输入值,避免产生锁存器 差的编码风格: always @(g or a or b) begin :
Page 1 of 8
让锁存器不再让人头痛
www.edacn.net/bbs
须提供文档记录。包括对每个锁存器的列表、描述和相关的时序特殊需求。寄存器堆、存储 器、FIFO 和其它一些设计中使用的 D 锁存器是允许的。 注意:用设计检查工具对设计中的锁存器进行检查。 例 1 所示的 Verilog 程序,综合会产生锁存器。因为在 if 语句的使用中缺少 else 语句。 例 2 所示的 VHDL 程序,综合后会产生锁存器。因为,when others 条件成立时,z 变量没 有被赋值。 例 1 因为缺少 else 语句,而产生锁存器
always @ ( a or b)
begin if (a == 1'b1) q <= b; end 例 2 因为代码中未对 z 变量赋值,而产生锁存器 process (c) begin case c is when '0' => q <= '1'; z <= ' 0'; when others => q <= '0'; end case; end process; 例 3 因为代码中缺少赋值和条件语句,而产生锁存器
Page 5 of 8
让锁存器不再让人头痛
www.edacn.net/bbs
图5带full case的例子 由于在例 8 中使用了 full case 语句,综合工具在综合时不会产生锁存器。另外,综合指令 “synthesis full_case”以注释的方式出现在代码中,只影响综合工具的综合结果,对设 计模型的语义没有其它影响。警告:使用full_case指令可能会导致设计模型和综合出的网表 功能不一致。 四、再谈锁存器 前面已经讲了当条件语句没有覆盖到所有分支时将产生锁存器, 很多资料也提到在设计中要 避免锁存器,其中的原因是什么呢? 例9 一个锁存器 module test_latch(y, a, b); output y; input a; input b; reg y; always @(a or b) begin if(a==1’b1) y=b; end endmodule
Page 4 of 8
让锁存器不再让人头痛
www.edacn.net/bbs
3'b001: y1=a[1]; 3'b010: y1=a[2]; 3'b011: y1=a[3]; endcase end endmodule 其综合出来的RTL图如图4。
图4 例七是一个不完整的条件分支的例子,sel信号位宽为3,可出现8种输入情况,但是在前级保证 输入只可能出现3’000、3’001、3’010、3’011四种情况下,在使用综合指令“synthesis full_case”后,综合工具将其综合成不带锁存器的电路如下图5所示。 例8 带full case的例子 module latch_test(y1,a,sel); output y1; input [3:0] a; input [2:0] sel; reg y1; always @(sel or a) begin case(sel) /*synthesis full_case*/ 3'b000: y1=a[0]; 3'b001: y1=a[1]; 3'b010: y1=a[2]; 3'b011: y1=a[3]; endcase end endmodule
⎧
⎪ ⎪ ⎩Q = 0
G2 输出 Q = 0 ⋅1 +1⋅1⋅ D = 1 ,所以 D 不影响 Q 和 Q
锁存器原理图
⎧ ⎪Q = 0 ⎪ ⎪ ⎩Q = 1
G2 输出 Q = 1⋅1 + 0 ⋅1⋅ D = 0 ,所以 D 也不影响 Q 和 Q
∴结论:原来状态不被改变,D 不影响 Q 和 Q 。 由上述分析看出:
⎧ ⎪ ⎪C = 0时,Q = D,电路不锁存数据,相当于缓冲器 ⎨ ⎪ ⎪ ⎩C = 1时,D不起作用,电路状态保持C由0 → 1时刻前D决定的状态
也就是说, C 由 0 → 1 时刻将数据 D 锁定并保持,直到 C 由 1 → 0。 二、下面谈在你的设计中,如何避免使用任何锁存器 但也有例外,你可以使用工艺无关的 GTECH D 锁存器。然而,对于所有的锁存器都必
Page 6 of 8
让锁存器不再让人头痛
来自百度文库
www.edacn.net/bbs
从图6可知,例9对应的电路是锁存器。在信号a为高电平的时候,信号b可以传递给y,即使b是 带毛刺的信号。 例10 一个D触发器 module test_d(y,clk,a,b); output y; input clk; input a; input b; reg y; always @(posedge clk) begin if(a==1'b1) y=b; end endmodule
推荐的编码风格: MUX3_PROC: process (decode, A, B) begin if (decode = ‘1’) then
C <= A;
else
C <= B; end if; end process MUX3_PROC;
三、如果必须使用锁存器 在有些设计中,不可避免地需要用到锁存器。例如,在PCI接口设计中,如果不用锁存器,
如例 4 的 VHDL 代码所示,将默认值赋值语句写在进程的开始。 如例 5 的 Verilog 代码所示,对所有可能的输入条件,都有明确的输出。 如例 6 的 VHDL 代码所示,对于条件语句的最后一个分支,使用 else 语句(而不使用 elsif 语句) 。 例 4 通过默认值,避免产生锁存器
always @(d)
begin case (d) 2’b00: z <= 1’b1; //缺少对s的赋值 2’b01: z <= 1’b0; //缺少对s的赋值 2’b10: z <= 1’b1;s <= 1’b 1; endcase end //缺少在条件2’b11下对变量z和s的赋值
通过使用以下编码技术,可以避免产生锁存器。
参考文献: [1] Verilog HDL的数字系统应用设计。王钿,国防工业出版社 [2] Reuse Methodology Manual for System-on-a-chip Designs. Michael Keating [3] Verilog HDL Synthesis A Practical Primer. J.Bhasker [4] http://www.edacn.net/bbs/
end 例6 VHDL代码中,通过对条件语句的最后分支使用else语句,避免产生锁存器 差的编码风格: MUX3_PROC: process (decode, A, B) begin if (decode = ‘0’) then
C <= A;
elsif (decode = ‘1’) then
C <= B; end if; end process MUX3_PROC;
从图8可知,例10对应的电路是D触发器。信号a被综合成D触发器的使能端,只有在时钟上 沿到来且a为高时,b信号的值才能传递给a;只要在时钟上升沿期间信号b是稳定,即使在其他
Page 7 of 8
让锁存器不再让人头痛
www.edacn.net/bbs
时候b还有毛刺,经过D触发器后数据是稳定的,毛刺被滤除。 实际上,锁存器与D触发器实现的逻辑功能基本相同,都有暂存数据的功能。但如果两者由 与非门来搭建的话。锁存器所耗用的逻辑资源要比D触发器少,换句话说使用锁存器时集成度更 高。所以在早期的ASIC设计中,为了提高芯片集成度,有不少设计都采用了锁存器。但锁存器 对毛刺敏感,无异步复位端,不能让芯片在上电时处在一个确定的状态;加外,采用锁存器也会 使静态时序分析变得复杂,不利于设计的可重用,所以在当今ASIC的设计中,除了CPU这种甚 高速电路,一般不提倡使用锁存器。而FPGA的基本逻辑单元由多输入查找表、D触发器构成,并 不存在锁存器这种现成的结构,因此如果在FPGA设计中使用锁存器的话,反而会更耗资源。 基于以上原因,在FPGA设计中,应该避免使用锁存器。在时序逻辑电路中,可以将锁存器 改为带使能端的D触发器;而在组合电路中,可以通过更改代码以覆盖所有条件分支,或者在组 合进程中以赋默认值的方式避免锁存器的产生。 下面的一个例子就是通过在组合进程中以赋默认 值避免产生锁存器的例子。 例11 通过赋默认值的方式避免产生锁存器。 always @(sel or a) begin y2=3’b000; //通过赋默认值,可以避免产生锁存器 casex(sel) /*synthesis parallel_case*/ 3’bxx1: y2=a[0]; 3’bx1x: y2=a[1]; 3’b1xx: y2=a[2]; endcase end 五、触发器和锁存器的推断 明白综合工具(如大多数计算机软件一样)是“愚蠢”的,这很重要。在VDHL中没有保留 字指定模型是组合的还是时序的,时序逻辑是同步的还是异步的。 如果一个信号或者变量维持它的值超过一段时间, 便综合成一个触发器或者锁存器。 在VHDL 中,一个信号保持它的值直至赋予一个新值。如果一个进程包含一条wait语句,任何在进程中 赋值的信号(或者变量)必须保持它们的值直到wait语句完成。所以在一个有wait语句的进程 中赋值的所有信号和变量必须保存在寄存器中。 类似地, 如果一些贯穿进程的通路对一个信号或 者变量赋值,而其他通路没有,则隐式地创建一个触发器或者锁存器。这典型地发生在:如果一 条case语句或者if语句不完整。
图2 好:不出现组合环路
图3 对于CASE语句生成锁存器的问题: 例7 case条件分支不完整导致了锁存器的产生 module latch_test(y1,a,sel); output y1; input [3:0] a; input [2:0] sel; reg y1; always @(sel or a) begin case(sel) 3'b000: y1=a[0];
让锁存器不再让人头痛
www.edacn.net/bbs
让锁存器不再让人头痛
(喜欢把学的东西整理一下,欢迎大家指正 chenhongyi123@163.com 2007.04.13) 触发器是指由时钟边沿触发的存储器单元。 锁存器指一个由信号而不是时钟控制的电平 敏感的设备。 一、锁存器的工作原理 锁存器不同于触发器,它不在锁存数据时,输出端的信号随输入信号变化,就像信号通 过一个缓冲器一样;一旦锁存信号起锁存作用,则数据被锁住,输入信号不起作用。锁存器 也称为透明锁存器,指的是不锁存时输出对于输入是透明的。 如下图所示为锁存器的原理图
C 是锁存控制信号输入端,D 数据输入端, Q 和 Q 是数据互补输出端。
Ⅰ: C =0, G2 左与门被封锁, G3 被封锁
⎧ ⎪Q = D G2 输出, Q = 0 ⋅ Q + 1⋅ D = D ,∴ ⎪ ⎨ ⎪ ⎪ ⎩Q = D
Ⅱ: C 时,分两种情况
⎪Q = 1 (a) ⎪ ⎨
(b) ⎪ ⎨