設計背景:
阻塞(=)和非阻塞(<=)一直是在我們FPGA中討論的問題,資深的學者都是討論的是賦值應該發生在上升下降沿還是在哪里,我們在仿真中看的可能是上升下降是準確的,但是在時間電路中這就是不得而知了,今天我們將學習阻塞和非阻塞的區別,我們不研究他們發生在哪里,之討論發生的時間和發生的地方。
設計原理:
阻塞:在本語句中“右式計算”和“左式更新”完全完成之后,才開始執行下一條語句;
非阻塞:當前語句的執行不會阻塞下一語句的執行。
我們來看一下下面的阻塞的代碼
0modulestudy_4 (clk,rst_n,d,q);
1 //輸入輸出端口
2 inputclk;
3 inputrst_n;
4 input[1:0]d;
5 outputreg[1:0]q;
6
7 reg[1:0]q1;//定義一個寄存器
8
9 always@(posedgeclk)
10 begin
11 if(!rst_n) //復位時用阻塞給寄存器輸出賦初值
12 begin
13 q1 =0;
14 q =0;
15 end
16 else //阻塞語句進行賦值
17 begin
18 q1 =d;
19 q =q1;
20 end
21 end
22
23endmodule
always語句塊對Clk的上升沿敏感,當發生Clk 0~1的跳變時,執行該always語句。
在begin...end語句塊中所有語句是順序執行的,而且最關鍵的是,阻塞賦值是在本語句中“右式計算”和“左式更新”完全完成之后,才開始執行下一條語句的。
在上面的代碼中在18行當上升沿來到先執行把d的值給q1,然后下一個上升沿把q1賦值給q。
我們的測試文件如下:
0`timescale1ns/1ps
1
2moduletb;
3
4 regclk;
5 regrst_n;
6 reg[1:0]d;
7 wire[1:0]q;
8
9 initialbegin
10 clk =1;
11 rst_n =0;
12 d =0;
13
14 #200.1rst_n =1;
15
16 #100d =2;
17 #100d =0;
18
19 end
20
21 always#10clk =~clk;
22
23 study_4 dut(
24 .clk(clk),
25 .rst_n(rst_n),
26 .d(d),
27 .q(q)
28 );
29
30endmodule
放真圖如下:
我們可以清楚的看到第一個上升沿的時候寄存器q為0,第二個上升沿的時候q為2,接下來,再看看非阻塞賦值的情況。
所謂非阻塞賦值,顧名思義,就是指當前語句的執行不會阻塞下一語句的執行。
非阻塞代碼如下:
0modulestudy_4 (clk,rst_n,d,q);
1
2 inputclk;
3 inputrst_n;
4 input[1:0]d;
5 outputreg[1:0]q;
6
7 reg[1:0]q1;
8
9 always@(posedgeclk)
10 begin
11 if(!rst_n) //復位時用非阻塞給寄存器輸出賦初值
12 begin
13 q1 <=0;
14 q <=0;
15 end
16 else //非阻塞語句進行賦值
17 begin
18 q1 <=d;
19 q <=q1;
20 end
21 end
22
23endmodule
非阻塞在18行以后是這樣執行的,18行的時候d的值給q1,但是不是立馬給過去,而是等到上升的時候才給,在上升沿同樣執行19行,把q1得值給q,大家要明白的這個時候給值是q1的舊值,然后同樣在19行也是在上升沿到來后值才給過去的。
我們兩個模塊用的是一樣的仿真文件,我在這里就不給大家展示了,大家可以直接看仿真圖,如下:
大家可以清楚的看到,在第一個上升沿的時候d的值為2,執行18行然后不直接賦值,在等到上升沿來的時候值過去,同樣的后面的也是這么執行的,那么我們可以看到圖中和我們分析的一樣。
-
FPGA
+關注
關注
1629文章
21729瀏覽量
603009 -
非阻塞賦值
+關注
關注
0文章
10瀏覽量
9999
發布評論請先 登錄
相關推薦
評論