编写D触发器(DFF)时出现锁存器(Latch)问题的排查求助
排查Verilog代码中的锁存器问题
你贴出的这段代码本身不会生成锁存器——两个always块都是边沿触发,且每个时钟沿都会给目标变量赋值,完全符合D触发器的综合规则:
- 第一个
always块:a1是由clk_a上升沿触发的D触发器,输入为in; - 第二个
always块:b1是由clk_b上升沿触发的D触发器,输入为a1;out同样是clk_b上升沿触发的D触发器,输入为b1的上一拍值(非阻塞赋值<=是并行执行的,out<=b1取的是时钟沿到来前b1的旧值)。
团队检测到锁存器,大概率是以下原因导致:
变量声明错误:如果
a1/b1/out被错误声明为wire类型,却在always块里赋值——wire只能通过assign进行连续赋值,这种错误会让综合工具误生成锁存器(部分工具可能直接报语法错误)。正确做法是将这些变量声明为reg:reg a1, b1, out;综合工具误判或配置问题:部分旧版综合工具会把无复位的触发器误识别为锁存器,或者工具分析规则设置过于严格。建议查看工具的综合报告,定位被标记为锁存器的具体变量,针对性排查。
未展示代码的影响:你只贴了部分代码,可能未展示的逻辑中存在组合逻辑未完全赋值的情况(比如
if/case语句缺省分支),导致锁存器生成,团队误以为是这段代码的问题。概念混淆:
a1由clk_a驱动,b1由clk_b采样a1属于跨时钟域场景,这只会带来亚稳态风险,不会生成锁存器,团队可能混淆了锁存器与跨时钟域问题的概念。
如果确认变量声明正确,且工具报告显示锁存器确实来自这段代码,可以尝试添加异步复位明确触发器行为,避免工具误判:
always@(posedge clk_a or negedge rst_n) begin if(!rst_n) a1 <= 1'b0; else a1 <= in; end always@(posedge clk_b or negedge rst_n) begin if(!rst_n) begin b1 <= 1'b0; out <= 1'b0; end else begin b1 <= a1; out <= b1; end end
内容的提问来源于stack exchange,提问作者余昌翰
相关产品推荐
相关产品推荐

