VHDL带超时上升沿等待语句的SystemVerilog等效实现问询
问题背景
用户需要将以下VHDL代码转换为等效的SystemVerilog代码:
process begin wait until rising_edge(mysig) for 1 us; if rising_edge(mysig) do_something() else do_something_else(); end if; end process
用户已参考论坛用户@dave_59的思路实现了timed_re_wait任务,该任务用于模拟上述带超时的上升沿等待逻辑,目前仿真可正常运行,但不确定是否存在未考虑的边界情况,因此提出两个疑问:
- 该
timed_re_wait任务的实现是否正确? - 调用该任务后,如何检测当前
mysig是否出现了上升沿?如果无法直接检测,是否只能通过让任务输出expired标志位来进行后续判断?
解答
一、timed_re_wait任务的正确性与边界检查
要确认任务实现是否正确,核心是看它是否完全复现VHDL原逻辑的行为:在1微秒窗口内等待mysig的上升沿,超时则终止等待。需要重点验证以下边界场景:
- 调用任务时
mysig已处于上升沿触发状态:比如调用前mysig刚完成从0到1的跳变,此时VHDL会直接识别上升沿,任务需要立即返回,不能进入超时等待。 - 超时瞬间恰好出现上升沿:当1微秒超时的同一仿真时刻,
mysig发生上升沿,此时应判定为捕获到上升沿,而非超时,对应原逻辑执行do_something()。 - 任务重复调用的状态独立性:多次调用任务时,内部的时序事件(如超时定时器)不能残留上一次调用的状态,避免干扰后续逻辑。
如果你的任务实现覆盖了以上场景,且仿真验证通过,那么基本可以认为是正确的。
二、调用任务后检测上升沿的方案
在SystemVerilog中,调用任务后无法直接用rising_edge(mysig)判断任务等待窗口内是否出现过上升沿——因为任务执行期间的时序事件已经结束,当前时刻的rising_edge检测只能反映当下的信号状态,无法对应之前的等待周期。
因此,最可靠的方式是让timed_re_wait任务输出一个expired标志位:
- 若
expired为0,说明超时前捕获到了mysig的上升沿,后续执行do_something(); - 若
expired为1,说明等待超时,执行do_something_else()。
典型的任务实现示例:
task timed_re_wait(input logic mysig, input time timeout, output bit expired); fork begin @(posedge mysig); // 等待上升沿触发 expired = 1'b0; end begin #timeout; // 等待超时时间 expired = 1'b1; end join_any disable fork; // 终止未完成的分支 endtask
调用时直接根据expired值分支处理:
bit expired_flag; timed_re_wait(mysig, 1us, expired_flag); if (!expired_flag) begin do_something(); end else begin do_something_else(); end
这种方式完全匹配VHDL原逻辑的行为,也是SystemVerilog中实现带超时事件等待的标准做法,不存在歧义。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

