mars4zhu 发表于 2022-11-3 08:45

记录一次竞争与冒险的实测(HDL代码中的组合电路的信号作为时钟,毛刺带来的影响)

<div class='showpostmsg'> 本帖最后由 mars4zhu 于 2022-11-3 08:50 编辑

<h1>竞争与冒险的实测<a href="http://summerdawn.top:7081/contention_race/contention_race.html#id1" title="Permalink to this heading"></a></h1>

<p>记录一次HDL代码中的组合电路的信号作为时钟,毛刺带来的影响</p>

<p>两种代码实现流水灯效果,以下代码运行正确的流水灯效果</p>

<pre style="background:#555; padding:10px; color:#ddd !important;">
module test0_pin (
      inputclk_50M,
      inputnRST,
      input KEY,

      output LED
);

      parameter COUNTER_MAX = (50_000_000-1);

      reg rCounter;
      always @ (posedge clk_50M or negedge nRST) begin
                if (!nRST) begin
                        rCounter &lt;= 32&#39;d0;
                end
                else begin
                        rCounter &lt;= (rCounter &gt;= COUNTER_MAX) ? 32&#39;d0 : (rCounter + 32&#39;d1);
                end
      end
// ============================

      reg rLED;
      always @ (posedge clk_50M or negedge nRST) begin
                if (!nRST)
                        rLED &lt;= 8&#39;b0000_0001;
                else
                        rLED &lt;= (rCounter == COUNTER_MAX) ?
                              {rLED, rLED} : rLED;
      end

// ============================
      assign LED = (nRST) ? ~rLED : ~KEY;

endmodule
</pre>

<p></p>

<p>以下代码运行的流水灯效果存在异常</p>

<pre style="background:#555; padding:10px; color:#ddd !important;">
module test0_pin (
      inputclk_50M,
      inputnRST,
      input KEY,

      output LED
);

      parameter COUNTER_MAX = (50_000_000-1);

      reg rCounter;
      always @ (posedge clk_50M or negedge nRST) begin
                if (!nRST) begin
                        rCounter &lt;= 32&#39;d0;
                end
                else begin
                        rCounter &lt;= (rCounter &gt;= COUNTER_MAX) ? 32&#39;d0 : (rCounter + 32&#39;d1);
                end
      end
// ============================

      wire clk_div;
      assign clk_div = (!nRST) ? 1&#39;b0 :
                ( (rCounter &lt; (COUNTER_MAX/2)) ? 1&#39;b0 : 1&#39;b1 );

      reg rLED;
      always @ (posedge clk_div or negedge nRST) begin
                if (!nRST)
                        rLED &lt;= 8&#39;b0000_0001;
                else
                        rLED &lt;= {rLED, rLED};
      end

// ============================
      assign LED = (nRST) ? ~rLED : ~KEY;

endmodule
</pre>

<p>&nbsp;</p>

<p></p>

<p>这两段verilog代码,都是执行流水灯,第二个就跑起来有问题。有时候有一两个LED就一闪而过,似乎clk_div上有毛刺之类的现象。。。 运行效果如视频, 总会跳过几个LED(一闪而过,能看到被跳过的LED有轻微的闪一下),</p>

<p>这段代码,assign语句:</p>

<pre style="background:#555; padding:10px; color:#ddd !important;">
assign clk_div = (!nRST) ? 1&#39;b0 :
      ( (rCounter &lt; (COUNTER_MAX/2)) ? 1&#39;b0 : 1&#39;b1 );
</pre>

<p>主要期望的功能是产生分频时钟, clk_div = clk_50M / COUNTER_MAX,这种计数器分频,还可以调节占空比、相移,</p>

<p>但是在运行的时候, 在rCounter变化的那一瞬间,譬如从50M变为0, 由于rCounter是32bit位宽的,各个bit到达比较器的时间会有细微差别,造成比较器看到的信号并不是此时此刻的真正的rCounter的值,所以才会产生毛刺。</p>

<p></p>

<p>而运行行为仿真是很难发现此类问题,行为仿真是按照一种理想器件的无延时特性运行,而实际运行的物理器件具有延时。以下的行为仿真(iverilog + gtkwave)波形图。</p>

<p></p>

<p>以下的网络文章按照有延时的物理特性仿真,就发现了竞争冒险现象的毛刺。</p>

<p><a href="https://zhuanlan.zhihu.com/p/451396150">https://zhuanlan.zhihu.com/p/451396150</a>&nbsp;组合逻辑毛刺消除(竞争冒险)</p>

<p>信号在 IC/FPGA 器件中通过逻辑单元连线时,是存在延时的。延时的大小不仅和连线的长短和逻辑单元的数目有关,而且也和器件的制造工艺、工作环境等有关。因此,信号在器件中传输的时候,所需要的时间是不能精确估计的,当多路信号同时发生跳变的瞬间,就产生了&ldquo;竞争冒险&rdquo;。</p>

<p>信号由于经由不同路径传输达到某一汇合点的时间有先有后的现象,就称之为竞争,英文名Race;由于竞争现象所引起的电路输出发生瞬间错误的现象,就称之为冒险,英文名Hazard或者Risk。有竞争不一定有冒险,但出现了冒险就一定存在竞争。发生冒险时往往会出现一些不正确的尖峰信号,这些尖峰信号就是&ldquo;毛刺&rdquo;。</p>

<p>当然,打一拍也是有一定原则的,不是想打就打的</p>

<p>1.全局时钟的跳变沿最可靠。 2.来自异步时钟域的输入需要寄存一次以同步化,再寄存一次以减少亚稳态带来的影响。 3.不需要用到跳变沿的来自同一时钟域的输入,没有必要对信号进行寄存。 4.需要用到跳变沿的来自同一时钟域的输入,寄存一次即可。 5.需要用到跳变沿的来自不同时钟域的输入,需要用到3个触发器,前两个用以同步,第3个触发器的输出和第2个的输出经过逻辑门来判断跳变沿。</p>

<p><a href="https://baike.baidu.com/item/%E6%AF%9B%E5%88%BA/24249328">https://baike.baidu.com/item/%E6%AF%9B%E5%88%BA/24249328</a></p>

<p>信号在FPGA器件内部通过连线和逻辑单元时,都有一定的延时。延时的大小与连线的长短和逻辑单元的数目有关,同时还受器件的制造工艺、工作电压、温度等条件的影响。信号的高低电平转换也需要一定的过渡时间。由于存在这两方面因素,多路信号的电平值发生变化时,在信号变化的瞬间,组合逻辑的输出有先后顺序,并不是同时变化,往往会出现一些不正确的尖峰信号,这些尖峰信号称为&rdquo;毛刺&rdquo;。如果一个组合逻辑电路中有&rdquo;毛刺&rdquo;出现,就说明该电路存在&rdquo;冒险&rdquo;。(与分立元件不同,由于PLD内部不存在寄生电容电感,这些毛刺将被完整的保留并向下一级传递,因此毛刺现象在LD、FPGA设计中尤为突出) 图6.21给出了一个逻辑冒险的例子,从图6.22的仿真波形可以看出,&rdquo;A、B、C、D&rdquo;四个输入信号经过布线延时以后,高低电平变换不是同时发生的,这导致输出信号&rdquo;OUT&rdquo;出现了毛刺。(我们无法保证所有连线的长度一致,所以即使四个输入信号在输入端同时变化,但经过PLD内部的走线,到达或门的时间也是不一样的,毛刺必然产生)。可以概括的讲,只要输入信号同时变化,(经过内部走线)组合逻辑必将产生毛刺。 将它们的输出直接连接到时钟输入端、清零或置位端口的设计方法是错误的,这可能会导致严重的后果。 所以我们必须检查设计中所有时钟、清零和置位等对毛刺敏感的输入端口,确保输入不会含有任何毛刺</p>

<p><a href="https://zhuanlan.zhihu.com/p/372453668">https://zhuanlan.zhihu.com/p/372453668</a>&nbsp;时序电路&mdash;&mdash;DFF再理解</p>
</div><script>                                var loginstr = '<div class="locked">查看精华帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                               
                                if(parseInt(discuz_uid)==0){
                                                                                        (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                }
</script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

为天问地问自己 发表于 2022-11-3 11:27

<p>手边没有板子,只能学习学习代码了</p>

lugl4313820 发表于 2022-11-4 08:14

LED可以玩出这水平,学习了。

baiweihua 发表于 2022-11-7 19:41

<p>很好的例子!</p>

baiweihua 发表于 2022-11-7 19:43

<p>把竞争冒险讲清楚了!:loveliness:</p>

reallmy 发表于 2022-11-8 14:38

<p>大概看了下你的代码,很多地方不规范,或者说Verilog不建议这样写,找一个Verilog设计规范,会避免很多问题,也会对设计有一定的提升</p>

leilei0000 发表于 2024-1-26 15:14

<p>把竞争冒险讲清楚了,学习了</p>

白猫警督 发表于 2024-3-26 16:59

<p>把竞争冒险讲清楚了,学习了</p>
页: [1]
查看完整版本: 记录一次竞争与冒险的实测(HDL代码中的组合电路的信号作为时钟,毛刺带来的影响)