在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3900|回复: 13

[讨论] 非阻塞赋值(Non-blocking Assignment)是个伪需求

[复制链接]
发表于 2018-9-13 11:02:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
verilog的赋值很是复杂,包括:
1. Continuous assignment;
2. Procedural assignment:
  a. Blocking Assignment;
  b. Non-bocking Assignment(NBA);

但其实没有必要,理解起来也可以很简单;
比如Continuous assignment是针对wire而言,wire需要的是driven,而不是assign,驱动(driven)是物里
的概念,而赋值是编程的概念;

这个连续指的不是值的变化,而是assign这个动作。比如assign wireA = wireB,不是这一次把wireB的值赋值给wireA,而是以后wireA的值都跟随wireB的值的变化而变化。所以可以理解为driven和连接。也因此continous assignment只能针对wire使用。

Procedural Assignment针对寄存器使用,值的就是赋值,因为reg可以存值。因此称为过程性(Procedural),赋值之后就结束了。

那为什么还需要blocking和Non-blocking呢?

可能是要处理多个寄存器之间的赋值问题。
CASE 1(https://blog.csdn.net/chief_cf/article/details/52373831):




  1. always@(posedge clk)
  2.     begin
  3.         b <= a;
  4.         c <= b;
  5.     end


复制代码



&#8203;

                               
登录/注册后可看大图
&#8203;

这个的写法可以改成:




  1. always@(posedge clk)
  2.     begin
  3.         c = b;
  4.         b = a;
  5.     end


复制代码


具体综合成什么电路,就交给综合器。

CASE 2(值交换):




  1. always@(posedge clk)
  2.     begin
  3.         b <= a;
  4.         a <= b;
  5.     end


复制代码


我不清楚具体综合出的电路是什么样的,但是写法可以改成:




  1. always@(posedge clk)
  2.     begin
  3.         tmp = b;
  4.         b = a;
  5.         a = tmp;
  6.     end


复制代码


也不需要非阻塞赋值;

什么意思呢?就是要化简建模的方法论(Methodology):
只需要处理wire和reg的assignment即可。
不需要为多个wire之间怎么assign,多个reg之间怎么assign再提供新的机制了。
这样的Methodology最简单。

事实上,可以看到新出的建模方法,无论是SystemC还是Chisel,都没有Non-blocking Assignment的概念。

简单的建模方法论(Methodology)重要的,可以降低学习难度,减少很多实践中的问题。
 楼主| 发表于 2018-9-13 13:48:43 | 显示全部楼层
本帖最后由 wjcdx 于 2018-9-13 13:57 编辑

CASE 3:




  1. always @(posedge clk)
  2.     begin
  3.         a <= u&v&w;
  4.         b <= x|y|z;
  5.     end


复制代码


这种写法提倡拆分成两个always语句块,每个处理一个独立的逻辑:




  1. always @(posedge clk)
  2. begin
  3.     a = u&v&w;
  4. end

  5. always @(posedge clk)
  6. begin
  7.     b = x|y|z;
  8. end


复制代码
发表于 2018-9-14 14:13:20 | 显示全部楼层
汗,不清楚具体对应什么电路,就认为自己是对的?电路本身是实际存在的,并不是你代码产生的,我觉得你这么理解不是完全合理。
 楼主| 发表于 2018-9-14 14:19:39 | 显示全部楼层
回复 3# gaurson

确实比较激进,综合器可以对用户屏蔽易产生错误的细节。请问下你知道吗?能否帮忙提供下综合后的电路结构,谢谢!
 楼主| 发表于 2018-9-14 14:21:29 | 显示全部楼层
回复 3# gaurson

或者有必须NBA的场景吗?
发表于 2018-9-14 16:52:35 | 显示全部楼层
我的看法:非阻塞赋值,跟电路的结构息息相关。两个触发器之间传送值时使用,假设有两个触发器,a,b。a被赋予了新的值,但是a输出的旧的值经过一段线网,已经到达b的D端。所以沿到来的时刻,a存新的值,b存a旧的值。b不能存a新的值,因为a新的值还没有达到b的D端。这样的原理正好符合非阻塞赋值的方式。
 楼主| 发表于 2018-9-14 21:14:52 | 显示全部楼层
本帖最后由 wjcdx 于 2018-9-14 21:24 编辑

回复 6# 轩辕紫冀

你说的这个应该是CASE 2:值交换。

Verilog可以在Gate and Switch层进行建模,也可以在RTL层进行建模。
这个NBA应该属于RTL层的概念,因为他使用的是reg这个数据类型,而不是DFF这个结构。

RTL层是一个抽象层次,所以我觉得使用RTL进行建模时,应当尽量使用这个抽象层次的语法结构。
至于如何综合成最终的电路,则交给综合器去做。我认为综合器是可以把CASE 2中的reg tmp给优化掉的。

打一个比方:如果坐在汽车里面,就只需要踩油门就行了。没必要再从底盘上开两个洞,把脚伸下去用脚划拉,还要拖着车,反受其累。
当然,如果Verilog的RTL不是汽车,而是自行车,屁股坐在上面,还是要用脚踩,那就是另一回事了。这个意思是说,Verilog的RTL确实有必须要NBA来表达的模型。

如果没有NBA,那么Assignment只有两种:用于wire的continous assignment和用于reg的procedural assignment,相当好理解。增加了Non-Blocking Assignment之后就大大的复杂化了。

如果需要把DFF拆开看值的传递,则层次处在Gate and Switch层,这个时候考虑a和b值交换不需要临时变量是何时的。
如果在RTL层,DFF已经被抽象出来了,是一个简单的reg变量。就像物理题里面一个物体被抽象成了一个点,那他的长宽高就不需要再考虑了。
 楼主| 发表于 2018-9-21 18:22:14 | 显示全部楼层
找到一个NBA的用途:简化Simulation和Synthesis的难度。

如果没有NBA的概念,若两条赋值语句连续出现,则无法判断这两条语句是否有先后顺序,即这两条赋值语句对应的电路是串联还是并联。

如果存在NBA,则可以通过赋值的类型来区分:
如果是BA,则串联;
如果是NBA,则并联;

当然在不存在NBA概念的情况下,也是可以判断两条语句是否有先后顺序关系:
在所在代码块范围(begin-end)内,检查判断所用到的变量是否存在依赖关系。

这个需要解析语法树,或者对代码做数据流分析。当时做起来可能没那么容易。
也可能只是权衡的问题,不得而知了。
发表于 2018-9-21 19:02:01 | 显示全部楼层
个人理解,Verilog本身只是“建模”语言。具体到阻塞/非阻塞,只规定了两种赋值语句的行为。所以无论怎么写,仿真器和综合器都不会报错。但是存在两个问题,所描述的行为是否有物理电路与之对应;电路行为在仿真阶段和综合后是否一致。
像是电平敏感always快内使用多个多个非阻塞赋值就没有意义,仿真结果不可信
 楼主| 发表于 2018-9-21 22:25:53 | 显示全部楼层
回复 9# 13hope

> 个人理解,Verilog本身只是“建模”语言。


Verilog是个大杂烩(中性,非贬义),包含了支持验证、综合、测试的语法结构,比如:initial, repeat, forever, task等。


> 具体到阻塞/非阻塞,只规定了两种赋值语句的行为。所以无论怎么写,仿真器和综合器都不会报错。但是存在两个问题,所描述的行为是否有物理电路与之对应;电路行为在仿真阶段和综合后是否一致。


感谢提醒,可能就是与综合后电路一致的原因。Verilog发展历经了好多个版本,有可能是历史原因。


不过,最终要求的不是你建模的电路和综合后的电路一模一样,否则不是要写RTL代码,而是要画版图了。最终的要求是综合后的电路符合RTL描述的模型,行为一致。


RTL是一个抽象的建模层次,而不是物理的建模层次,无法与综合后的电路完全对应:比如+-x÷这些operators都不是使用电路描述的,但综合后却有电路,怎么对应呢?


还有综合器要对RTL的代码做优化,有一些电路不必要的会被优化掉,效率不高的会被优化成更高效的方式。


再有,很多时候使用的是工具提供的库里面的模块,这个是黑盒的,也不清楚里面的电路。


今天发现一个2001版本的新特性,可以佐证我的观点:
&#8203;

                               
登录/注册后可看大图
&#8203;

引自:https://www.cnblogs.com/tshell/p/3236476.html


从这个里面可以看到,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;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-25 21:42 , Processed in 0.029025 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表