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





