当前位置:   article > 正文

Systemverilog中同一时刻连续执行两次task的问题_system verilog一个task调用两个task,第二个没执行

system verilog一个task调用两个task,第二个没执行

在写一个driver的过程中,遇到了一个奇怪的问题。driver的drv_transfer函数如下:

 forever begin

       wait(hready);

        repeat(4) begin

               data <= data_q.pop_front;

                @if.driver_cb;

       end

 end

这样写完之后,会出现一个时钟周期,queue被pop两次的情况,因此data的第一个数据就会被覆盖掉,并且这种现象仅仅发生在第一组数据上。出现这种情况的原因在于,hready是一个和时钟同步的信号,hready和时钟的上升沿是同时到来的。当hready拉高时,循环不会被@if.driver_cb阻塞,会继续运行,直到被下一个@if.driver_cb阻塞,因此,在一个时钟周期,queue会被pop两次,当forever不阻塞在wait(hready)时,已经不是上升沿的时钟周期,因此会pop一个数据,进入下一次循环,阻塞在@if.driver_cb,然后再次pop。对第一组数据而言,wait等待的信号成立,也就是hready初始就是高电平,因此不会被wait(hready)阻塞,也不会在某个上升沿不被wait(hready)阻塞,因此,第一组数据会pop两次,而其它的数据仅仅会pop一次。解决这个问题的方法是在pop后面添加#0语句。添加#0语句会将仿真时间推向当前时间的末尾,因此第一次pop就会被@if.driver_cb阻塞。

    systemverilog中的@和wait都是阻塞,但是区别在于一个@是同步阻塞,而wait是异步阻塞。对于被@阻塞的信号,如果触发时没有执行,就会一直阻塞,对于被wait阻塞的信号,只要触发过一次,就不会被阻塞。

    对于systemverilog而言,在同一仿真时刻,不同事件出现由先后顺序的。一个被posedge clk驱动的信号,出现的顺序会晚于posedge clk,因此,如果使用wait(signal)来阻塞程序,会等信号出现之后再继续执行,如果后面还有一个@posedge clk, 程序仍然会被阻塞。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/938613
推荐阅读
相关标签
  

闽ICP备14008679号