10. case,casez,casex語(yǔ)句
Verilog定義了case,casez和casex語(yǔ)句,用于做多種情況下的選擇語(yǔ)句。
reg [1:0] sel;
reg [2:0] result;
always @(*)
case(sel)
2’b00: result = 3’d0;
2’b01: result = 3’d1;
2’b10: result = 3’d2;
endcase
使用case語(yǔ)句代替嵌套的if-else將會(huì)產(chǎn)生更易讀的代碼,更好的邏輯利用率和更高的性能。
casez和casex語(yǔ)句在比較中允許“don't care”條件。 casez將“z“”值視為"don't care",casex將“z”和“x”值都視為“don't care”。如果casez或casex表達(dá)式中的任何位都是"don't care value",那么該位將被忽略。以下是casez和casex的例子。
reg [1:0] sel;
reg [2:0] result;
// using casez
always @(*)
casez(sel)
2’b0?: result = 3’d0;
2’b10: result = 3’d1;
2’b11: result = 3’d2;
endcase
// using casex
always @(*)
casex(sel)
2’b0x: result = 3’d0;
2’b10: result = 3’d1;
2’b11: result = 3’d2;
Endcase
case的表達(dá)式可以是一個(gè)常量,如下例所示。
reg [1:0] sel;
reg [2:0] result;
always @(*)
case(1
~sel[1]: result = 3’d0;
sel[1] & ~sel[0]: result = 3’d1;
sel[1] & sel[0]: result = 3’d2;
Endcase
在案例中使用don't care條件很容易導(dǎo)致case 條件重疊或重復(fù)。而且,使用這些語(yǔ)句會(huì)導(dǎo)致綜合和仿真不匹配。以下是案例case條件重疊的一個(gè)例子。
// casez statement contains overlapped case items
reg [1:0] sel;
reg [2:0] result;
always @(*)
casez(sel)
2’b0z: result = 3’d0;
2’b10: result = 3’d2;
2’b11: result = 3’d3;
2’b01: result = 3’d1; // overlap with 2’b0z
Endcase
允許重疊或重復(fù)的case條件,在大多數(shù)情況下不會(huì)觸發(fā)任何仿真或綜合警告。這是一種危險(xiǎn)且難以調(diào)試的情況.。建議開發(fā)人員完全避免使用casex和casez語(yǔ)句。
在case語(yǔ)句中添加一個(gè)默認(rèn)的條件是避免一系列問題的簡(jiǎn)單方法。 有兩種方法可以達(dá)到相同的效果,如以下示例所示。
reg [1:0] sel;
reg [2:0] result;
// using default clause
always @(*)
case(sel)
2’b00: result = 3’d0;
2’b01: result = 3’d1;
2’b10: result = 3’d2;
default: result = 3’d3;
endcase
// 在case語(yǔ)句之前進(jìn)行默認(rèn)賦值
always @(*)
result = 3’d3;
case(sel)
2’b00: result = 3’d0;
2’b01: result = 3’d1;
2’b10: result = 3’d2;
Endcase
11. 在always塊中混合阻塞和非阻塞賦值
Verilog指定了總是可以出現(xiàn)在塊中的兩種賦值類型:阻塞和非阻塞。阻塞和非阻塞賦值分別用于描述組合邏輯和時(shí)序邏輯。永遠(yuǎn)不要在同一個(gè)塊中混合使用阻塞和非阻塞賦值。這樣做可能會(huì)導(dǎo)致不可預(yù)知的綜合和仿真結(jié)果。在許多情況下,綜合工具不會(huì)產(chǎn)生任何警告,但綜合結(jié)果將是不正確的。以下兩個(gè)代碼示例說明了阻塞和非阻塞賦值的混合使用。
reg blocking, non_blocking;
always @(posedge clk) begin
if(reset) begin
blocking = 0;
non_blocking
end
else begin
blocking = ^data;
non_blocking
end
end
always @(*) begin
blocking = ^data;
non_blocking
end
正確的方法是:
reg blocking, non_blocking;
always @(posedge clk) begin
if(reset) begin
non_blocking
end
else begin
non_blocking
end
end
always @(*) begin
blocking = ^data;
End
12. 多個(gè)阻塞賦值
always塊中的阻塞賦值按其順序執(zhí)行。 盡管這樣做通常很方便,但是建議開發(fā)者限制使用多個(gè)阻塞賦值來賦值always塊中的相同變量。下面的兩個(gè)代碼示例顯示了使用多個(gè)阻塞分配的潛在問題。
reg signal_a, signal_b, signal_c, signal_d;
always (*) begin
signal_a = signal_b & signal_c;
// …
signal_d = signal_a & signal_e;
end
無意中改變signal_a和signal_d分配的順序?qū)?huì)破壞signal_d的功能。
reg [15:0] signal_a, signal_b;
always (*) begin
signal_a[15:12] = 4’b0;
// …
// additional code
signal_a = signal_b;
End
signal_a的最后一個(gè)賦值優(yōu)先,signal_a的位[15:12]永遠(yuǎn)不會(huì)被復(fù)位。
13. 使用命名的always塊
以下是always塊的例子。
reg reg_unnamed;
always @(posedge clk) begin : myname
// only visible in the “myname” block
reg reg_named;
// post-synthesis name : myname.reg_named
reg_named
// post-synthesis name : reg_unnamed
reg_unnamed
end // always
命名塊可以在幾種情況下有用。 因?yàn)閍lways塊是唯一標(biāo)識(shí)的,所以在仿真中更容易找到它。 而且,限制變量的范圍允許重復(fù)使用相同的變量名稱。
編輯:hfy
-
FPGA
+關(guān)注
關(guān)注
1626文章
21678瀏覽量
602043
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論