SystemVerilog单语句多自增运算符执行顺序及LRM规定问询
SystemVerilog聚合赋值中自增操作的执行顺序问题
嘿,这个问题戳中了SystemVerilog里一个很容易踩的坑,我来给你掰扯清楚:
首先明确结论:你写的这种聚合赋值里,i++的执行顺序是完全未定义的——既不保证从左到右,也不保证从右到左。也就是说,初始i=0时,你给出的两种结果都有可能出现,甚至还可能出现其他混乱的结果,完全取决于仿真器的实现逻辑。
关于SystemVerilog LRM的规定
IEEE 1800-2017(当前常用的SystemVerilog标准)里,第11.3.2节(表达式求值顺序)明确说明:
除非标准有明确规定,否则表达式中操作数的求值顺序是未定义的。
而在聚合赋值(就是你用大括号{}的这种赋值方式)的第11.4.14节里,也补充了:右侧各个元素表达式的求值顺序没有被指定。简单说就是,标准故意没给这个顺序定死,工具厂商可以自由实现,所以你绝对不能依赖这种写法的执行顺序。
针对你的需求的安全替代方案
既然你的目的是避免硬编码索引、减少错误,给你推荐几种安全且易维护的写法:
用循环赋值(最稳妥通用):
for (int idx = 0; idx < 8; idx++) begin desc.src_addr[idx] = rdata[i++]; end循环的执行顺序是明确的,每次迭代都会按顺序给
desc.src_addr的每个元素赋值,同时i稳步自增,完全不会有顺序歧义。用数组切片(更简洁,适用于连续数组):
如果rdata是连续的定宽/动态数组,直接用切片语法一步到位:desc.src_addr = rdata[i : i+7]; i += 8; // 最后手动更新i的位置这种写法既简洁,又彻底避开了自增顺序的问题,可读性拉满。
最后提醒
永远不要依赖未定义行为写代码!哪怕你当前用的仿真器每次都输出你想要的结果,换个工具版本或者厂商,结果可能就完全不一样了,后期维护会埋巨大的坑。
内容的提问来源于stack exchange,提问作者Sharanbr
相关产品推荐
相关产品推荐

