reg型變數怎麼賦值_使用阻塞賦值和非阻塞賦值建模的分頻時鐘
阿新 • • 發佈:2021-01-01
技術標籤:reg型變數怎麼賦值
我們常常能看到一個Verilog RTL Coding guideline :在建模時序邏輯的時候,使用非阻塞賦值。
但事實上,當我們遵循使用非阻塞賦值來建模分頻時鐘(時鐘路徑)時,可能會存在競爭冒險的問題。
module Non_blocking( input clk , input rst_n, input data_in, output data_out) reg clk_div , [email protected](posedgeclk or negedge rst_n) begin if(!rst_n) begin clk_div<= 0 ; end else begin clk_div <= ~clk_div ; //update value after delta end end reg data_reg ;
[email protected](posedgeclk or negedge rst_n) begin if(!rst_n) begin data_reg<= 0 ; end else begin data_reg <= data_in ; //update value after delta end end [email protected](posedgeclk_div or negedge rst_n) begin if(!rst_n) begin data_out<= 0 ; end else begin data_out <= data_reg ; end end endmodule
Testbench:
module Non_blocking_tb; reg clk; reg rst_n; reg data_in; wire data_out; initial begin clk= 0 ; rst_n = 1 ; #10 rst_n = 0 ; #10 rst_n = 1 ; end always #2 clk =~clk ; initial begin data_in = 0 ; repeat(20) begin @(posedge clk) data_in =$random%2 ; end end Non_blocking Non_blocking( .clk(clk) , .rst_n(rst_n), .data_in(data_in), .data_out(data_out) ); endmodule
上述程式碼可以理解為master clock生成的generated clock和master clock生成的data之間存在競爭冒險,也可以理解為非阻塞賦值去除了master clock和generated clock之間的同步關係,這種同步關係在綜合的時候是需要有STA工具來保證的。
上述程式碼data_out取樣到的是data_reg更新後錯誤的值。
也就是說上述的程式碼風格(在時鐘路徑上使用非阻塞賦值),導致了綜合前後模擬的不匹配。
非阻塞賦值“<=”主要用來建模硬體上觸發器賦值行為,它分為兩步:
1、計算“<=”表示式右邊的值
2、在delta延時之後,將表示式右邊的值賦給左邊的變數。
避免這種綜合前後模擬的不匹配,最簡單的方式就是使用阻塞賦值來建模分頻時鐘(時鐘路徑)。
[email protected](posedgeclk or negedge rst_n) begin
if(!rst_n) begin
clk_div = 0 ;
end
else begin
clk_div = ~clk_div ; //update value immediately
end
end
使用同樣的Testbench,模擬結果:
上述程式碼data_out取樣到的是data_reg更新前正確的值。
這種使用阻塞賦值的方式來建模時鐘路徑時序邏輯也不會存在任何綜合上的問題。
所以之前大家熟知的guideline,應該精確為:
在建模資料路徑上時序邏輯的時候,使用非阻塞賦值;在建模時鐘路徑上時序邏輯的時候,使用阻塞賦值。