SystemVerilog竞赛条件挑战Responses

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


Race #1 Blocking and non-blocking assignments

byte slam; bit dunk; initial begin forever begin @(posedge clk); dunk = ~dunk; slam += dunk; end end always @(posedge clk) basket <= slam + dunk;

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


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

logic pong; initial begin fork forever begin @(posedge clk); if (pong) ping = 0; else ping = 1; end forever begin @(posedge clk); if (ping) pong = 0; else pong = 1; end join_none end

This is basically the same asRace #1。此外,编码的方式,未知值得到了与0,就像它们一样。如果您尝试实现此操作并非总是如此ping = !pong;然后一切都将保持未知。


种族#3程序和连续分配

byte colours, stripes, bouncy; always @(posedge clk) stripes += 1; always begin @(posedge clk); colours += 1; beach_ball = bouncy; end assign bouncy = colours && stripes;

连续分配表现为独立的进程,并且在任何过程之间没有执行的确定顺序。每当连续转让变化的右侧操作数时,左侧都有一个分配。但是,如果另一个进程正在对这些操作数进行更改,则在程序分配到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中改变了总是 @*和further improved with总是_combin SystemVerilog


Race #5 fork/join* that don’t consume time

位铅球;位标枪;初始开始@(posedge clk);叉铅球=$random();标枪=$random();连接无@(铅球或标枪)投掷=(铅球| |标枪);结束

This is not a race. The processes inside a fork/join_none are not supposed to start until its parent process suspends or terminates. This code will calculate throw based on the initial values for shot_put and javelin, which are 0, not the values from $random(). Finally, stop using the deprecated $random() with its poor distribution/stability, and switch to$urandom_range(1)


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

bit single, double, triple, homerun, cycle; initial begin forever begin @(posedge 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; end end initial begin forever begin #1 cycle = & { single, double, triple, homerun }; @(posedge clk); end end always @(posedge clk) begin #1 baseball = baseball + homerun; if (cycle) begin #0 cycle = 0; end end

I cringe whenever I see#0或者#1sprinkled in code. It usually means the coder did not understand SystemVerilog scheduling semantics well enough and throws these in. In this case the race has been moved one timeunit (#1) away from the clock edge. The assignment to cycle occurs simultaneously to its reading in the总是block.


Race #7 Edge sensitive events

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

这是另一种形式的Race #1。One process is writing, and another process is reading the same variable. But here the read is an event control waiting the expression(goal==2)改变。所以,取决于最初的总是blocks, it either catches the rise from false(1’b0) to true(1’b1) on the first clock cycle, or the fall from true to false in the next cycle. Always use non-blocking assignments between synchronous processes as I explained inRace #1。And it is rare to use an expression in an edge sensitive event. You should use the following:

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

Race #8 Named events

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

Named events are synchronization objects that can suffer from the same kinds of problems as in the previousRace #7。在触发之前,您必须等待事件。如果第二个永远阻止在第一个永远块开始执行之前的击球手击球手,则进入一个僵局,其中第一个永远块是死锁的等待已经触发的事件。您可以使用非阻塞触发来解决此特定种族->>击球手和wicket。I would make sure you have avery goodunderstanding of SystemVerilog’s event scheduling algorithm before using named events.


种族#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程序力/释放

byte pushups, situps, reps; assign situps = 3 + pushups; always @(posedge clk) reps <= reps + 1; always begin @(posedge clk); pushups += reps; force situps = 0; @(posedge clk); release situps; muscles = pushups + situps; end initial #300 $finish(); endmodule

This is the same asRace #3。All continuous assignments are independent concurrent processes. You cannot depend on their order of execution within the same time region.


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

-dave_rich

评论

0思想“SystemVerilog竞赛条件挑战Responses

    发表评论