[英]Multiple Clock Assertion in Systemverilog
這是設計代碼:
module mul_clock (input clkA, clkB, in, output out);
bit temp;
reg x[2:0];
always @ (posedge clkA)
temp <= temp ^ in;
always @ (posedge clkB)
x <= {x[1:0], temp};
assign out = x[2] ^ x[1];
endmodule
如何為“Out”寫Assertion,因為它是一個多時鍾設計。
我試過一個,但仍然有一些錯誤。 請幫我修改這個斷言或寫另一個斷言:
property p1;
bit t;
bit x[2:0];
@(posedge clkA)
(1'b1, t ^= in) |=> @(posedge clkB) (1'b1, x[0] = t) |=> @(posedge clkB) (out == x[2] ^ x[1], x[1] = x[0]) |=> @(posedge clkB) (out == x[2] ^ x[1], x[2] = x[1]);
endproperty
注意 :使用always block和單個時鍾斷言,我們可以驗證輸出端口。 但是如果可能的話,我希望通過多鎖斷言來實現它,而不需要任何總阻塞。
免責聲明:我沒有測試過這個。
你有沒有嘗試過:
#1 @(posedge clkA) (1'b1, t ^= in) |->
#2 @(posedge clkB) (1'b1, x[0] = t) |=>
#3 @(posedge clkB) (out == x[2] ^ x[1], x[1] = x[0]) |=>
#4 @(posedge clkB) (out == x[2] ^ x[1], x[2] = x[1]);
也就是說,時鍾切換中存在重疊的含義。 根據我的經驗,非重疊的含義將導致斷言不在下一個clkB上進行采樣,而是跳過一個clkB然后在clkB上進行采樣。
此外,我不太明白為什么你在斷言中一直使用含義。 第2行不是第3行的先決條件,對於第3行和第4行也是如此。 我讀這個的方式斷言應該從每個clkA開始,然后一個序列將始終跟隨。 在這種情況下,以下更正確,盡管前面的代碼可能仍然有效。
@(posedge clkA)
(1'b1, t ^= in) |->
@(posedge clkB)
(1'b1, x[0] = t) ##1
(1'b1, x[1] = x[0]) ##1
(out == x[2] ^ x[1], x[2] = x[1]);
最后,如果clkA比clkB快得多,會發生什么? 幾個斷言將並行開始,並且不同意在clkB的第一個構造上t的實際值。 我必須承認,我對一個屬性的本地值的范圍很朦朧,但檢查這是否會導致你的麻煩。 可能的修復方法可能是在屬性范圍外聲明變量t。 因此t將在clkA的每個posedge上更新為新值,並且您將有n個斷言檢查相同的事情(這不是問題)。
編輯:我從第3行刪除了out == x[2] ^ x[1]
,因為x
是屬性的本地。 因此,您無法檢查此斷言的某個其他實例所做的值。
另外:如果上述方法不起作用,或者如果開始並行斷言檢查相同內容似乎是浪費,則以下代碼可能有效。
Edit2:將x放在屬性中並更改屬性中的兩個最后一行以更新x以更正值。
bit t;
always_ff@(posedge clkA)
t ^= in;
property p1;
bit[2:0] x;
@(posedge clkB)
(1'b1, x[0] = t) |=>
(1'b1, x[1] = x[0]) ##0 (1'b1, x[0] = t) ##1
(1'b1, x[2] = x[1]) ##0 (1'b1, x[1] = x[0]) ##0 out == x[2] ^ x[1];
endproperty
最后的獎金提示:創建的觸發器應該重置。 也就是說,x和temp都應該在各自的時鍾域本地重置。 您可以選擇同步或異步重置。 這也必須添加到您的財產。 另外:始終使用always_ff或always_comb,永遠不要使用always。
異步重置:
always_ff @ (posedge clkA or posedge arstClkA)
if(arstClkA)
temp <= 0;
else
temp <= temp ^ in;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.