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

VCS中initial块连续赋值clk未触发always块的原因咨询

VCS中同一时间步连续赋值clk为何未触发D触发器更新?

Verilog设计与测试代码

module dff (clk, reset,
  d, q, qb);
  input      clk;
  input      reset;
  input      d;
  output     q;
  output     qb;

  reg        q;

  assign qb = ~q;

  always @(posedge clk or posedge reset)
  begin
    if (reset) begin
      // 异步复位(reset高有效)
      q <= 1'b0;
    end else begin
      // 时钟上升沿时将D赋值给Q
      q <= d;
    end
  end
endmodule


// 测试平台代码
module TB;
  
  reg clk;
  reg reset;
  reg d;
  wire q, qb;
  
  dff dff_inst(clk, reset, d, q, qb);
  
  initial begin
    clk = 0;
    reset = 0;
    d = 1;
    
    #1; reset = 1;
    
    #1; reset = 0;
    
    #1;   //// 注意这里!!!
    clk = 0;
    clk = 1;
    clk = 0;
    
    #1;
    $display("q = %b", q);
  end
  
endmodule

问题描述

我是VCS新手,为测试事件驱动机制,在initial块的同一时间步内将clk信号连续赋值为0、1、0。按照事件驱动逻辑,clk存在上升沿事件,应触发always块使q被赋值为1,但$display输出q为0,请问这是为什么?


原因分析

核心问题在于Verilog仿真的时间步与边沿检测机制:

  • Verilog仿真以时间步为基本单位,信号的边沿(如posedge clk)是基于相邻时间步之间的信号值变化来判定的,而非同一时间步内的瞬时跳变。
  • 你在#1后的同一时间步内,用阻塞赋值连续执行clk=0; clk=1; clk=0;,这组操作会在当前时间步的active区域内立即完成。此时该时间步开始时clk的值为0,执行完所有赋值后clk的最终值仍为0——仿真器只会识别时间步起始与结束的信号值差异,中间的瞬时1不会被判定为有效的上升沿事件。
  • 由于未触发always @(posedge clk or posedge reset)的敏感事件,D触发器的q <= d操作从未执行,q保持了异步复位后的0值,因此$display输出0。

验证与修正方法

  1. 验证上升沿检测逻辑:若将clk赋值改为最终停留在1,该时间步结束时clk值从0变为1,仿真器会识别出上升沿,触发always块更新q:
#1;
clk = 0;
clk = 1; // 不再赋值回0

此时$display会输出q = 1。

  1. 规范时钟生成方式:若要模拟完整的时钟脉冲,需将高低电平拆分到不同时间步,比如:
#1;
clk = 1;
#1;
clk = 0;

这样能在相邻时间步产生有效的上升沿和下降沿,符合事件驱动的仿真逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:13:19