You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

时钟门控Verilog代码功能异常问题排查求助

问题原因分析

嘿,我帮你拆解下这个问题的核心原因,其实是两个关键的理解偏差导致了你的仿真结果不符合预期:

1. 错误把组合逻辑信号当时钟用

你用always @(*) write_clk_en = write_clk & write_clk_mod;生成的write_clk_en是个组合逻辑信号,却试图用@(posedge write_clk_en)来触发赋值操作——这是问题的根源。

为什么会出问题?看你的write_clk_mod更新逻辑:它是在write_clk上升沿通过非阻塞赋值更新的。举个具体的时间点例子:当第三个write_clk上升沿(50ns左右)到来时,你把write_clk_mod设为0,这个赋值会在时钟沿的非阻塞赋值阶段生效,此时write_clk已经是高电平了,所以write_clk_en会立刻从1掉到0;而到第四个write_clk上升沿(70ns左右)时,你把write_clk_mod设回1,同样在非阻塞赋值阶段生效,此时write_clk还是高电平,write_clk_en会从0跳到1——这个跳变是在时钟高电平期间发生的,并不是你预期的“门控时钟上升沿”,但仿真器会把任何0→1的跳变都当成上升沿来触发,这就导致你误以为在write_clk_en关断的周期执行了data_in[3]的赋值。

2. 混淆了时钟使能和门控时钟的正确用法

你想要实现的是“仅当write_clk_en有效时,在时钟上升沿传输数据”,本质上是时钟使能逻辑,而非真正的门控时钟。正确的做法应该是把原始时钟write_clk作为触发源,用write_clk_mod作为使能条件,在时钟上升沿判断是否执行赋值,而不是把组合逻辑生成的write_clk_en当作时钟来用。

给你修正后的代码示例

把你最后那个触发赋值的initial块改成下面这样,就能完全符合你的预期:

initial begin
  data_in = 5'b00000;
  // 逐个bit赋值,仅在write_clk_mod有效时的时钟上升沿执行
  repeat(1) @(posedge write_clk) if(write_clk_mod) data_in[0] <= 1'b1;
  repeat(1) @(posedge write_clk) if(write_clk_mod) data_in[1] <= 1'b1;
  repeat(1) @(posedge write_clk) if(write_clk_mod) data_in[2] <= 1'b1;
  repeat(1) @(posedge write_clk) if(write_clk_mod) data_in[3] <= 1'b1;
  repeat(1) @(posedge write_clk) if(write_clk_mod) data_in[4] <= 1'b1;
end

或者更简洁的写法,避免重复代码:

initial begin
  data_in = 5'b00000;
  foreach(data_in[i]) begin
    wait(write_clk_mod);       // 先等使能信号有效
    @(posedge write_clk);      // 再等时钟上升沿
    data_in[i] <= 1'b1;
  end
end

这样修改后,只有当write_clk_mod为1时,才会在write_clk的上升沿执行赋值,完全匹配你想要的“仅在有效门控时钟上升沿传输数据”的逻辑。

内容的提问来源于stack exchange,提问作者Ansuman Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 19:37:49