前言
提前給出一些觀點:
- 仿真是為了仿真,所以不要設置極限情況,例如在時鐘上升沿通過阻塞賦值給數據,應該避免這種情況;
- 各種不同的仿真軟件對時鐘上升沿通過阻塞賦值給數據的理解不一致,例如modelsim和isim;
- 可以使用非阻塞賦值設置數據值,避免在時鐘上升沿時刻使用阻塞賦值給數據。
本文最后會給出推薦的仿真觀點。
實踐分析
事實上,上面三點說的是針對一種情況,我們舉一個簡單的例子說明。我們的設計文件,很簡單,就是一個檢測上升沿的程序:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Reborn Lee
// website : https://blog.csdn.net/Reborn_Lee
//////////////////////////////////////////////////////////////////////////////////
module delay(
input wire in,
input wire clk,
input wire rst,
output reg out_r3
);
reg in_reg;
always@(posedge clk) begin
if(rst) begin
in_reg <= 0;
end
else begin
in_reg <= in;
end
end
wire mid_pos;
assign mid_pos = ~in_reg & in;
reg reg_pos;
reg reg1_pos;
reg reg2_pos;
always@(posedge clk) begin
if(rst) begin
reg_pos <= 0;
reg1_pos <= 0;
reg2_pos <= 0;
out_r3 <= 0;
end
else begin
reg_pos <= mid_pos;
reg1_pos <= reg_pos;
reg2_pos <= reg1_pos;
out_r3 <= reg2_pos;
end
end
endmodule
如下,我們的testbench為:
`timescale 1ns / 1ps
// Engineer: Reborn Lee
// website : https://blog.csdn.net/Reborn_Lee
module sim_delay;
reg clk;
reg rst;
reg in;
wire out_r3;
initial begin
clk = 0;
forever begin
#5 clk = ~clk;
end
end
initial begin
rst = 1;
in = 0;
#20
rst = 0;
#100
@(posedge clk) begin
in = 1;
end
#300
in = 0;
end
delay delay_inst(
.in(in),
.clk(clk),
.rst(rst),
.out_r3(out_r3)
);
endmodule
我們對輸入進行賦值:
@(posedge clk) begin
in = 1;
end
可見,使用的是阻塞賦值,且在時鐘上升沿賦值;
在這種情況下,我們使用vivado自帶的仿真工具仿真,得到結果如下:
isim仿真工具
可見,得不到上升沿,這我們其實也能理解;由于是行為仿真,所以,一切都是理想的,不考慮延遲;我們使用阻塞賦值在時鐘上升沿時刻給輸入賦值,立即生效;固然,我們的時鐘在上升沿采樣的時候,得到in_reg和in是同邊沿的,這樣自然就得不到邊沿了,后面延遲多拍也自然無用。
這是vivado的仿真工具isim對這種情況的理解。
現在問題來了,當我們使用modelsim進行仿真的時候,情況是這樣的:
modelsim仿真工具
它會對in延遲一整拍,也就是要給時鐘,最終也就能得到上升沿了。同樣的設計,同樣的仿真文件,為何會出現這樣的差異呢?這里給出的解釋是仿真工具對這種情況的理解問題:在實際情況中(考慮真實環境,存在延遲),這種輸入的邊沿出現在時鐘的有效沿,本身就是不合法的,因為這會導致時序通過不了,例如建立時間。對于這種情況,modelsim或者questasim的處理就比較直接,我不準出現這種情況,如果你出現了,我們認為此刻無效。其效果類似于非阻塞賦值:
@(posedge clk) begin
in <= 1;
end
這里使用了非阻塞賦值,那么在時鐘上升沿時刻,in的值就沒那么快生效,如此,無論在那個平臺仿真,仿真情況都一致了。
下面是這種情況下在任意平臺的仿真圖:
任意平臺
推薦的仿真設計
開門見山,在時鐘有效沿時刻給數據是不符合實際的,是極端的做法,這在實際情況中不會出現,即使出現,綜合布線工具也會重新布線避免這種情況,否則就是時許違規。因此為了有意義的仿真且統一仿真平臺,我們應該在距離有效沿一定延遲給數據,例如:
#100
@(posedge clk) begin
#1 in = 1;
end
或者:
#100
@(negedge clk) begin
in = 1;
end
總之,別在有效沿給數據,以這種情況為例,給出仿真圖:
#100
@(posedge clk) begin
#1 in = 1;
end
推薦的仿真方式
總結
從上面的分析可以看出,為了適應不同的仿真平臺(并不是說哪個仿真平臺錯了) ,且本著仿真意義的實際情況,我們不應該在極端的情況下進行仿真,不僅沒有意義,而且讓人疑惑。推薦的做法是在下降沿或者距離時鐘的上升沿有一定的延遲給數據,這才能避開不同平臺的差異且有實際意義。
-
FPGA設計
+關注
關注
9文章
428瀏覽量
26489 -
仿真器
+關注
關注
14文章
1016瀏覽量
83646 -
Vivado
+關注
關注
19文章
808瀏覽量
66343
發布評論請先 登錄
相關推薦
評論