zoukankan      html  css  js  c++  java
  • 非阻塞赋值(Non-blocking Assignment)是个伪需求(2)

     
    13hope:
    个人理解,Verilog本身只是“建模”语言。具体到阻塞/非阻塞,只规定了两种赋值语句的行为。所以无论怎么写,仿真器和综合器都不会报错。但是存在两个问题,所描述的行为是否有物理电路与之对应;电路行为在仿真阶段和综合后是否一致。 像是电平敏感always快内使用多个多个非阻塞赋值就没有意义,仿真结果不可信
     
    wjcdx:
    > 个人理解,Verilog本身只是“建模”语言。
     
    Verilog是个大杂烩(中性,非贬义),包含了支持验证、综合、测试的语法结构,比如:initial, repeat, forever, task等。
     
    > 具体到阻塞/非阻塞,只规定了两种赋值语句的行为。所以无论怎么写,仿真器和综合器都不会报错。但是存在两个问题,所描述的行为是否有物理电路与之对应;电路行为在仿真阶段和综合后是否一致。
     
    感谢提醒,可能就是与综合后电路一致的原因。Verilog发展历经了好多个版本,有可能是历史原因。
     
    不过,最终要求的不是你建模的电路和综合后的电路一模一样,否则不是要写RTL代码,而是要画版图了。最终的要求是综合后的电路符合RTL描述的模型,行为一致。
     
    RTL是一个抽象的建模层次,而不是物理的建模层次,无法与综合后的电路完全对应:比如+-x÷这些operators都不是使用电路描述的,但综合后却有电路,怎么对应呢?
     
    还有综合器要对RTL的代码做优化,有一些电路不必要的会被优化掉,效率不高的会被优化成更高效的方式。
     
    再有,很多时候使用的是工具提供的库里面的模块,这个是黑盒的,也不清楚里面的电路。
     
    今天发现一个2001版本的新特性,可以佐证我的观点:
     
    从这个里面可以看到,register不是物理的寄存器(DFF)。而是一个变量数据类型(variable data type).
    但是又遗留了明显针对物理寄存器的非阻塞赋值,做的不彻底。NBA增加了学习的难度,进而在使用中也会产生问题。
     
    建模方法(Modeling Methodology)应该尽量简单,把这部分工作放在综合器里面去做更合适。能写综合器的人,都是对电路特性更了解的人,出错的概率更小。
     
    RTL层建模需要的只是对变量赋值(variable assignment),甚至连 连续赋值 和 过程赋值 都不需要区分。这样的区分有助于理解,却不是必须。
     
    > 像是电平敏感always快内使用多个多个非阻塞赋值就没有意义,仿真结果不可信
     
    这个链接里有很多NBA在一个always块内:
    https://github.com/alexforencich/verilog-ethernet/blob/master/rtl/arp_64.v
    cache_query_request_ip_reg <= cache_query_request_ip_next;
    outgoing_eth_dest_mac_reg <= outgoing_eth_dest_mac_next;
    outgoing_arp_oper_reg <= outgoing_arp_oper_next;
    outgoing_arp_tha_reg <= outgoing_arp_tha_next;
    outgoing_arp_tpa_reg <= outgoing_arp_tpa_next; 
    wjcdx:
    > 像是电平敏感always快内使用多个多个非阻塞赋值就没有意义,仿真结果不可信
    昨天没看清楚,给的例子是边沿敏感。你说的是电平敏感。
     
    其实,“电平敏感”这个词不准确,准确的说法是“电平变化敏感”:
    always @(a, b, c)
    begin
      if (a) begin
      end
    end
     
    这个并不是只在a为1时执行,在a为0时也执行。所以不是对a的高电平敏感,而是对a的电平变化敏感。
     
    always在Verilog里面没有区分,在SystemVerilog里面区分的就比较细。上面的always在SystemVerilog里面应该是always_comb, 而不是always_seq,综合出来是组合电路,里面使用的是wire,而不是reg.
     
    对wire使用非阻塞赋值是不正确的。这也是我为什么说在RTL建模时把NBA这个概念拿掉的原因:理解时容易混淆,使用时容易出错。
     
    13hope:
    很细致的回复,基本都赞同。只是最后一点,GitHub上的代码是always @(posedge clk)内部,用了多个<=赋值当然没问题,综合后就是一堆DFF。
     
    至于我说的“没意义”,比如下面代码,a “电平变化敏感” (双沿),首先,想描述的一定是组合逻辑。其次,语义上非阻塞赋值是在当前仿真step之后同时给temp和b赋值,也就是说a值改变触发该always,其第二条在对temp采样时,temp还未更新,所以b始终等于a上一次“变化前”的值。这个“行为”没有任何组合电路与之对应(组合电路没有记忆功能)。
    always @(a) begin
      temp <= a;
      b <= temp;
    end 
     
    至于综合后,b确实是一根wire直接连到a,temp可能被优化掉,但仿真结果与综合不一致。
    Verilog非常容易写出仿真与综合行为不一致的电路,所以有很多guideline帮助构建可综合电路。
     
     
    wjcdx:
    如果不存在NBA,可能就不会存在这样的问题了。
    如果不存在NBA,则continuous和procedural assignment都只是简单的使用等号“=”来表示。
     
    1.
    always @(a) begin
      temp = a;
      b = temp;
    end
     
    这样的写法意思是,如果a变化,则把a的值赋值给temp, 然后在把temp的值赋值给b。
    这是简单的组合逻辑,可以化简为:
    assign b = a;
     
     
    2. 如果想让b每次都取a上一次的值,则可以写成:
    always @(a) begin
      b = temp;
      temp = a;
    end
     
    仿真和综合针对这个写法,不清楚是否一致?
     
    仿真器想必不会出错,综合器如何决定这两条赋值语句能否调换顺序呢?要做数据流分析。
    如果两条赋值语句各自的left hand side与对方的right hand side存在关联,或者反过来存在关联的话,就说明存在顺序关系。如果没有,则不存在顺序关系,两条赋值语句可以分开综合。
     
    综合器把这个事情做了以后,就可以把建模人员解放出来,只关心值的传递这个核心问题即可,
    而不用考虑仿真时值如何赋值,综合后电路如何赋值,这样的问题。
     
    建模人员保证值传递的逻辑时正确的。仿真器保证仿真的正确性,综合器保证综合出的电路符合模型要求的值传递逻辑。
    各司其职,正确的人做正确的事,专业的人做各自专业领域的事,这样可以减少出错。
     
    当然,建模人员了解仿真器和综合器的工作原理是有益的。
     
    回到这个例子上来,如果建模人员考虑的是变量之间的值如何传递,
    而不是仿真时什么时候采样,什么时候赋值,出错的可能性就小多了。
  • 相关阅读:
    Step by step Dynamics CRM 2013安装
    SQL Server 2012 Managed Service Account
    Step by step SQL Server 2012的安装
    Step by step 活动目录中添加一个子域
    Step by step 如何创建一个新森林
    向活动目录中添加一个子域
    活动目录的信任关系
    RAID 概述
    DNS 正向查找与反向查找
    Microsoft Dynamics CRM 2013 and 2011 Update Rollups and Service Packs
  • 原文地址:https://www.cnblogs.com/wjcdx/p/9705266.html
Copyright © 2011-2022 走看看