講個SystemVerilog隨機約束小坑
掃描二維碼
隨時隨地手機看文章
1. 正文
節(jié)氣
2024 SUMMER
記錄個在寫SystemVerilog隨機約束時遇到的一個小坑,如果沒有認(rèn)真去查看隨機結(jié)果是否符合預(yù)期,還真不容易發(fā)現(xiàn)。
為了方便講述,寫了如下示例代碼。類cl_a里有個隨機變量aa,初始值為222。在module top里對類cl_a例化并進(jìn)行約束隨機。
class cl_a; rand int aa = 222;endclass module top; cl_a a; int b = 1; initial begin a = new(); $display("[initial]=> aa:%0d", a.aa); assert ( a.randomize() with { aa == (b == 1) ? 666 : 999;} ) else $fatal; $display("[random1]=> aa:%0d", a.aa); assert ( a.randomize() with { aa == ((b == 1) ? 666 : 999);} ) else $fatal; $display("[random2]=> aa:%0d", a.aa); assert ( a.randomize() with { aa == (b == 1);} ) else $fatal; $display("[random3]=> aa:%0d", a.aa); assert ( a.randomize() with { aa == 8 ? 666 : 999;} ) else $fatal; $display("[random4]=> aa:%0d", a.aa); endendmodule
先不看仿真結(jié)果,你們覺得行11和行14的隨機結(jié)果一致嗎?
是的,它們倆的結(jié)果完全不一樣,如果你知道為什么會不一樣,那么接下來的內(nèi)容就不用看了。其實也很簡單,對SystemVerilog運算符優(yōu)先級記得很清楚的同仁,應(yīng)該一眼就看出毛病了。==運算符的優(yōu)先級高于三目運算符(?:)。
在行11中,會先算(b==1)為X,接下來算a==X為Y,這時候這里的==不是作為隨機約束符號來使用的,它在三目運算符(?:)中判斷是否相等來使用的,因此a其實是沒有加任何約束,也就是a會被隨機之后,再判斷a==X的值Y。所以我們最終看到[random1]打印的aa為隨機數(shù)。
在行14中,會先算((b == 1) ? 666 : 999)里面的內(nèi)容,b==1結(jié)果為1,所以三目運算符結(jié)果為666,然后計算a==666,這里的==就作為隨機約束符號了,因此最終看到[random2]打印的aa為666。
在行17中,會先算(b == 1),結(jié)果為1,然后再算a==1,這里的==也作為隨機約束符號,最終看到[random3]打印的aa為1。
行20其實和行11是類似的,這里a==8的==不是作為約束符號,而是簡單的判斷是否相等符。因此最終aa的值是隨機的。
使用VSC進(jìn)行仿真,結(jié)果如下:
[]=> aa:222[]=> aa:897241389[]=> aa:666[]=> aa:1[]=> aa:-1705158938
2. 總結(jié)
節(jié)氣
2024 SUMMER
其實說白了,要么大家認(rèn)真記住SystemVerilog的符號優(yōu)先級規(guī)則,要么在不大確定的地方多用寫括號()來確定符號運算的順序,減少意外發(fā)生。行11和行14就差個括號,但結(jié)果完全不一致,而且仿真也不會報任何warning或error信息。





