SystemVerilog竞赛条件挑战响应

如上所述,这是我对导师的回应SystemVerilog竞赛条件挑战


种族#1阻止和非阻塞分配

byte slam;扣篮;初始开始永远开始@(提出CLK);扣篮=〜扣篮;Slam + =扣篮;结束始终@(提出CLK)篮子<=猛击+扣篮;

比赛#1必须是Verilog / SystemVerilog中最常见的竞争状态。硬件设计师可能更熟悉这场比赛,但验证工程师也必须处理这一点。当您有多个线程或进程并行运行并且它们都同步到同一事件(时钟边沿)时,读取旧值或从阻塞分配的更新值之间存在竞争。这就是为什么当一个进程写入时必须始终使用非阻塞分配,另一个进程读取与同一时钟同步的相同变量。然后,您保证始终读取以前的值。这里的大多数代码示例都有这个问题


初始化时的种族#2未知数

逻辑乒乓球;初始开始fork forever @(posedge clk);如果(pong)ping = 0;否则ping = 1;永远永远开始@(提出CLK);如果(ping)pong = 0;别的乒乓球= 1;结束加入_none结束

这基本相同比赛#1。此外,编码的方式,未知值得到了与0,就像它们一样。如果您尝试实现此操作并非总是如此ping =!pong;然后一切都将保持未知。


种族#3程序和连续分配

字节颜色,​​条纹,弹性;始终@(提出Clk)条纹+ = 1;始终开始@(提出CLK);颜色+ = 1;Beach_ball = Bouncy;结束分配Bouncy = Colors &&条纹;

连续分配表现为独立的进程,并且在任何过程之间没有执行的确定顺序。每当连续转让变化的右侧操作数时,左侧都有一个分配。但是,如果另一个进程正在对这些操作数进行更改,则在程序分配到Beach_ball之前或之后,左侧更新时无法保证。请注意,所有累积的分配运算符都喜欢+ =要么++只是阻止分配的快捷方式。没有非阻塞的等效快捷方式,因此您必须将其扩展出:

总是@(提出Clk)条纹<=条纹+ 1;

种族#4不完全敏感性列表

比特分数;字节FieldGoal,触地得分;byte down;始终@(提出CLK)开始(向下<4)开始得分<= 1;FieldGoal <= FieldGoal + 3;touchdown <= touchdown + 7;下降<=下+ 1;结束否则开始得分<= 0;下降<= 0;结束结束总是@(得分)足球= FieldGoal +触达;

我不会打这场比赛,只是糟糕的编码。在最早版本的Verilog中,您可以弄清楚表达式列表以始终以模拟连续分配的行为。尽管此代码进行了分配来分配每个时钟周期,但其值仅为时钟周期的一半。因此,它将失踪更改为FieldGoal和触地得分。在Verilog-2001中改变了总是@ *并进一步改善永远_comb.在SystemVerilog.


种族#5 fork /加入*不消耗时间

bit shot_put;位标枪;初始开始@(提出CLK);fork shot_put = $ wandul();标枪= $ wandu();join_none @(shot_put或标枪)掷=(shot_put ||标枪);结束

这不是一场比赛。在父流程暂停或终止之前,不应该启动Fork / Join_none内的进程。此代码将根据shot_put和标志in的初始值计算抛出,它们为0,而不是$ wandul()的值。最后,停止使用弃用的$ Aquary(),其分发/稳定性差,然后切换到$ urandom_range(1)


比赛#6在超过1个线程中的分配

位单身,双重,三重,homerun,循环;初始开始永远开始@(提出CLK);single = $ urandom_range(0,10)> 1;double = $ urandom_range(0,10)> 2;triple = $ urandom_range(0,10)> 4;homerun = $ urandom_range(0,10)> 8;结束结束初始开始永远开始#1 Cycle =&{单,双,三重,homerun};@(提出了CLK);结束结束总是@(提出CLK)开始#1棒球=棒球+ Homerun;如果(周期)开始#0周期= 0; end end

我看到的时候我会畏缩#0要么#1洒在代码中。通常意味着编码器不太了解SystemVerilog调度语义,足够好,并抛出这些。在这种情况下,比赛已被移动一个时期(#1)远离时钟边缘。循环的分配同时发生到它的读数总是块。


种族#7边缘敏感事件

位[3:0]目标;总是@(提出CLK)目标+ = 2;初始开始@(提出CLK);@(目标== 2)曲棍球= 1;结束

这是另一种形式的比赛#1。一个进程是写入的,另一个进程正在读取相同的变量。但是,阅读是等待表达式的事件控制(目标== 2)改变。所以,取决于初始总是块,它要么在第一个时钟周期上从错误(1'b0)到真(1'b1)的升高),或者在下一个周期中的跌倒从true到false。始终在同步进程之间使用非阻塞分配,如我所解释的比赛#1。并且很少有用在边缘敏感事件中的表达式。您应该使用以下内容:

@(Posedge Clk Iff(目标== 2));

种族#8命名事件

事件检票口,击球手;初始开始@(提出CLK);Fork永远开始@batsman;重复(cricket + 1)@(提出Clk);- >检票口;最终开始 - >击球手;@便门;板球+ = 1;结束加入_none结束

命名事件是同步对象,可以遭受与之前的相同类型的问题比赛#7。在触发之前,您必须等待事件。如果第二个永远阻止在第一个永远块开始执行之前的击球手击球手,则进入一个僵局,其中第一个永远块是死锁的等待已经触发的事件。您可以使用非阻塞触发来解决此特定种族- >>击球手和检票口。我会确保你有一个挺好在使用命名事件之前了解SystemVerilog的事件调度算法。


种族#9 NBA函数

bit [3:0]凹凸,尖峰,side_out;功能位[3:0]设置(位[3:0] _bump);set <= _bump ^(_bump << 1);EndFunction初始开始永远开始@(Posedge Clk);凹凸+ = 1;spike = set(bump);side_out = bump 
         

这是一个你总是输的比赛。如果使用非阻塞分配返回函数,或者到任何函数或任务的输出参数,则在NBA有机会更新值之前将复制当前值。您必须在此处使用阻塞作业。


种族#10程序力/释放

字节俯卧撑,situps,reps;分配situps = 3 +俯卧撑;总是@(Posedge Clk)Reps <= reps + 1;始终开始@(提出CLK);俯卧撑+ =代表;强制Situps = 0;@(提出了CLK);释放仰卧起坐;肌肉=俯卧撑+ situps;结束初始#300 $ finish(); endmodule

这与种族#3。所有连续分配都是独立的并发进程。您不能依赖于它们在同一时区内执行顺序。


这就是我们的小竞争条件挑战的结论。我希望你能够得到它的东西。顺便说一下,这些代码片段都来自我们在去年或者上看的真实客户设计。

-dave_rich.

评论

0思想“SystemVerilog竞赛条件挑战响应

    发表评论