10. case,casez,casex語句
Verilog定義了case,casez和casex語句,用于做多種情況下的選擇語句。
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語句代替嵌套的if-else將會產生更易讀的代碼,更好的邏輯利用率和更高的性能。
casez和casex語句在比較中允許“don't care”條件。 casez將“z“”值視為"don't care",casex將“z”和“x”值都視為“don't care”。如果casez或casex表達式中的任何位都是"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的表達式可以是一個常量,如下例所示。
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條件很容易導致case 條件重疊或重復。而且,使用這些語句會導致綜合和仿真不匹配。以下是案例case條件重疊的一個例子。
// 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
允許重疊或重復的case條件,在大多數情況下不會觸發任何仿真或綜合警告。這是一種危險且難以調試的情況.。建議開發人員完全避免使用casex和casez語句。
在case語句中添加一個默認的條件是避免一系列問題的簡單方法。 有兩種方法可以達到相同的效果,如以下示例所示。
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語句之前進行默認賦值
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指定了總是可以出現在塊中的兩種賦值類型:阻塞和非阻塞。阻塞和非阻塞賦值分別用于描述組合邏輯和時序邏輯。永遠不要在同一個塊中混合使用阻塞和非阻塞賦值。這樣做可能會導致不可預知的綜合和仿真結果。在許多情況下,綜合工具不會產生任何警告,但綜合結果將是不正確的。以下兩個代碼示例說明了阻塞和非阻塞賦值的混合使用。
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. 多個阻塞賦值
always塊中的阻塞賦值按其順序執行。 盡管這樣做通常很方便,但是建議開發者限制使用多個阻塞賦值來賦值always塊中的相同變量。下面的兩個代碼示例顯示了使用多個阻塞分配的潛在問題。
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分配的順序將會破壞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的最后一個賦值優先,signal_a的位[15:12]永遠不會被復位。
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
命名塊可以在幾種情況下有用。 因為always塊是唯一標識的,所以在仿真中更容易找到它。 而且,限制變量的范圍允許重復使用相同的變量名稱。
編輯:hfy
-
FPGA
+關注
關注
1630文章
21798瀏覽量
606067
發布評論請先 登錄
相關推薦
評論