always 語句
always 語句是重復執行的。always 語句塊從 0 時刻開始執行其中的行為語句;當執行完最后一條語句后,便再次執行語句塊中的第一條語句,如此循環反復。多用于仿真時鐘的產生,信號行為的檢測等。
always語句的格式:
always @(posedge clk) begin
temp = a ;
a = b ;
b = temp ;
end
()中可以是*,表示:每當任何輸入發生變化時執行begin和end之間的語句。也可以是posedge clk,表示:時鐘上升沿時執行begin和end之間的語句。assign語句和always @(*)創建相同的組合邏輯,比如下面代碼中的兩個輸出波形是一致的。
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign=a&b;
always @(*) begin
out_alwaysblock=a&b;
end
endmodule
連續性賦值,過程性賦值 :連續性賦值總是處于激活狀態,任何操作數的改變都會影響表達式的結果;過程賦值只有在語句執行的時候,才會起作用。
阻塞賦值與非阻塞賦值 :是過程賦值的兩種類型。
阻塞賦值 :阻塞賦值屬于順序執行,下一條語句執行前,當前語句一定會執行完畢。使用等號 = 作為賦值符。initial語句用阻塞賦值。
非阻塞賦值 :并行執行,即下一條語句的執行和當前語句的執行是同時進行的,它不會阻塞位于同一個語句塊中后面語句的執行。使用 <= 作為賦值符。
使用非阻塞賦值是為了避免競爭冒險,那么實際使用中只需要記住:always時序邏輯塊中多用非阻塞賦值<=(后面的時序邏輯電路會另外介紹),always組合邏輯塊中多用阻塞賦值=; 在仿真電路時,initial 塊中一般多用阻塞賦值=。 例如下面代碼中,用assign語句,always組合語句,always時鐘語句實現異或:
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
assign out_assign=a^b;
always @(*) begin
out_always_comb=a^b;
end
always @(posedge clk) begin
out_always_ff<=a^b;
end
endmodule
if 語句格式
if (condition1) true_statement1 ;
else if (condition2) true_statement2 ;
else if (condition3) true_statement3 ;
else default_statement ;
如果只有兩種情況,就只有if和else。下面用上一節中MUX2_1做練習,上一節中采用了assign的三元運算符語句,這里使用always if語句實現2選1的功能:
module mux2_1
(
input wire in1,
input wire in2,
input wire sel,
output reg out
);
always@(*) begin
if(sel == 1'b1)//當“if...else...”中只有一個變量時不需要加“begin...end".但是為了不遺漏,還是加上
out = in1; //always塊中的組合邏輯關系時使用阻塞賦值“=”進行賦值
else
out = in2;
end
endmodule
3-8譯碼器的實現
從真值表看譯碼器功能:A2A1A0=000-111共8種輸入,對應輸出Y的下標,對應下標的輸出為1(高電平),其他輸出為0(低電平)。3-8譯碼器的作用:按照之前點亮LED燈的思路,如果一個I/O端口控制一個LED燈,那么I/O端口很有可能不夠用,這時候聰明人就想出用3-8譯碼器的方式,3個I/O口就可以控制8個LED。
設計規劃
這個示例中,繪制波形圖如圖所示。
編寫代碼
module decoder3_8
(
input wire in1 ,
input wire in2 ,
input wire in3 ,
output reg [7:0] out
);
always@(*) begin
//使用"{}"位拼接符將3個1bit數據按照順序拼成一個3bit數據
if({in1, in2, in3} == 3'b000)
out = 8'b0000_0001;
else if({in1, in2, in3} == 3'b001)
out = 8'b0000_0010;
else if({in1, in2, in3} == 3'b010)
out = 8'b0000_0100;
else if({in1, in2, in3} == 3'b011)
out = 8'b0000_1000;
else if({in1, in2, in3} == 3'b100)
out = 8'b0001_0000;
else if({in1, in2, in3} == 3'b101)
out = 8'b0010_0000;
else if({in1, in2, in3} == 3'b110)
out = 8'b0100_0000;
else if({in1, in2, in3} == 3'b111)
out = 8'b1000_0000;
else
out = 8'b0000_0001;
end
endmodule
代碼中使用always組合邏輯塊。由于if對應的執行語句只有一句,可以不使用begin,end但是由于怕以后復雜代碼會遺漏,還是選擇加上。always組合邏輯使用阻塞語句,用=進行賦值。
上面RTL代碼綜合出的RTL視圖:
編寫testbench
`timescale 1ns/1ns
module tb_decoder3_8();
//reg define
reg in1;
reg in2;
reg in3;
wire [7:0] out;
//初始化輸入信號
initial begin
in1 <= 1'b0;
in2 <= 1'b0;
in3 <= 1'b0;
end
always #10 in1 <= {$random} % 2;
always #10 in2 <= {$random} % 2;
always #10 in3 <= {$random} % 2;
//-------------decoder3_8_inst----------------
decoder3_8 decoder3_8_ins
(
.in1(in1),
.in2(in2),
.in3(in3),
.out(out)
);
endmodule
經過兩個實例后,testbench已經超級熟悉了吧。
對比波形
看看波型:
驗證了波形的正確性
-
FPGA
+關注
關注
1626文章
21677瀏覽量
601990 -
FPGA設計
+關注
關注
9文章
428瀏覽量
26489 -
仿真
+關注
關注
50文章
4047瀏覽量
133430 -
時鐘
+關注
關注
10文章
1721瀏覽量
131376 -
譯碼器
+關注
關注
4文章
310瀏覽量
50285
發布評論請先 登錄
相關推薦
評論