在Verilog中case語句經常用於多分支表決的結構,case後的表示式會與各分支表示式“全等”那麼對應的分支會被執行.其基本結構如下:

case(expression)

expr1 : statement_or_null;

exprn : statement_or_null;

default : statement_or_null;

endcase

雖然一般case經常被使用,但是在構建模擬驗證平臺時,經常會遇到case後的敏感表示式出現高阻態z和不定態x的情況,而對於部分位出現高阻態z和不定態x的情況有時需要忽略掉,如下例.

【示例】

`timescale 1 ns / 1 ps

module top_tb;

reg [1:0] d1,d2,d3,d4,d5,d6;

reg [1:0] sel;

reg [1:0] dout;

initial begin

d1 = 2'b00;d2 = 2'b10;d3 = 2'b0x;

d4 = 2'bz0;d5 = 2'bxx;d6 = 2'bzz;

sel = 2'b00;

#1 sel = 2'b10;

#1 sel = 2'b00;

#1 sel = 2'b0x;

#1 sel = 2'bz0;

#1 sel = 2'bxx;

#1 sel = 2'bzz;

#1 sel = 2'b11;

#1 $stop;

end

always @(sel)

begin

case(sel)

2'b00 : begin

dout = d1;

$display("Branch 2'b00!");

end

2'b10 : begin

dout = d2;

$display("Branch 2'b10!");

end

2'b0x : begin

dout = d3;

$display("Branch 2'b0x!");

end

2'bz0 : begin

dout = d4;

$display("Branch 2'bz0!");

end

2'b1x : begin

dout = d5;

$display("Branch 2'b1x!");

end

2'b1z : begin

dout = d6;

$display("Branch 2'b1z!");

end

default : begin

dout = 2'b00;

$display("Branch default!");

end

endcase

end

endmodule     // top_tb

【模擬結果】

Sel   |   Result

2’b00  # Branch 2'b00!

2’b10  # Branch 2'b10!

2’b00  # Branch 2'b00!

2’b0x  # Branch 2'b0x!

2’bz0  # Branch 2'bz0!

2’bxx  # Branch default!

2’bzz  # Branch default!

2’b11  # Branch default!

示例中確實可以將case後的敏感表示式與分支表示式進行全匹配,匹配包括表示式結果的每一位.但是如果期望2’b00和2’b0x或者2’b0z選擇執行相同的分支,或者2’b10和2’b1x或者2’b1z選擇執行相同的分支,使用原有的case語句是無法實現的,為此,為了滿足這種特殊的要求,case語句演變出了兩種變體casez和casex.

casez和casex的用法與傳統的case一樣,只是在敏感表示式和分支表示式匹配時稍有不同,casez語句中,如果分支表示式的結果中某些位的值位高阻z,那麼在對這些位進行比較時會忽略不進行比較,僅考慮其他對應位的比較.同理,casex也是會對某些位為z比進行比較,但是其進一步擴充套件為對包含x的位也不進行比較.

【示例】

`timescale 1 ns / 1 ps

module top_tb;

reg [1:0] d1,d2,d3,d4,d5,d6;

reg [1:0] sel;

reg [1:0] dout;

initial begin

d1 = 2'b00;d2 = 2'b10;d3 = 2'b0x;

d4 = 2'bz0;d5 = 2'bxx;d6 = 2'bzz;

sel = 2'b00;

#1 sel = 2'b10;

#1 sel = 2'b00;

#1 sel = 2'b0x;

#1 sel = 2'bz0;

#1 sel = 2'bxx;

#1 sel = 2'bzz;

#1 sel = 2'b11;

#1 $stop;

end

always @(sel)

begin

casez(sel)

2'b00 : begin

dout = d1;

$display("Branch 2'b00!");

end

2'b10 : begin

dout = d2;

$display("Branch 2'b10!");

end

2'b0x : begin

dout = d3;

$display("Branch 2'b0x!");

end

2'bz0 : begin

dout = d4;

$display("Branch 2'bz0!");

end

2'b1x : begin

dout = d5;

$display("Branch 2'b1x!");

end

2'b1z : begin

dout = d6;

$display("Branch 2'b1z!");

end

default : begin

dout = 2'b00;

$display("Branch default!");

end

endcase

end

endmodule     // top_tb

【模擬結果】

Sel   |   Result

2’b00  # Branch 2'b00!

2’b10  # Branch 2'b10!

2’b00  # Branch 2'b00!

2’b0x  # Branch 2'b0x!

2’bz0  # Branch 2'b00!

2’bxx  # Branch default!

2’bzz  # Branch 2'b00!

2’b11  # Branch 2'b1z!

此處將case替換為casez後,從模擬結果可以看出,2’bz0、2’bzz與2’b00結果一致,即不對敏感表示式與分支表示式中對應位存在z的位進行比較.這裡需要注意當sel位2’bzz時,因為不對任何位進行全等檢查,所以敏感表示式會與第一個分支匹配.可見casez語句中會忽略表示式中的高阻態位.

【示例】

`timescale 1 ns / 1 ps

module top_tb;

reg [1:0] d1,d2,d3,d4,d5,d6;

reg [1:0] sel;

reg [1:0] dout;

initial begin

d1 = 2'b00;d2 = 2'b10;d3 = 2'b0x;

d4 = 2'bz0;d5 = 2'bxx;d6 = 2'bzz;

sel = 2'b00;

#1 sel = 2'b10;

#1 sel = 2'b00;

#1 sel = 2'b0x;

#1 sel = 2'bz0;

#1 sel = 2'bxx;

#1 sel = 2'bzz;

#1 sel = 2'b11;

#1 $stop;

end

always @(sel)

begin

casex(sel)

2'b00 : begin

dout = d1;

$display("Branch 2'b00!");

end

2'b10 : begin

dout = d2;

$display("Branch 2'b10!");

end

2'b0x : begin

dout = d3;

$display("Branch 2'b0x!");

end

2'bz0 : begin

dout = d4;

$display("Branch 2'bz0!");

end

2'b1x : begin

dout = d5;

$display("Branch 2'b1x!");

end

2'b1z : begin

dout = d6;

$display("Branch 2'b1z!");

end

default : begin

dout = 2'b00;

$display("Branch default!");

end

endcase

end

endmodule     // top_tb

【模擬結果】

Sel   |   Result

2’b00  # Branch 2'b00!

2’b10  # Branch 2'b10!

2’b00  # Branch 2'b00!

2’b0x  # Branch 2'b00!

2’bz0  # Branch 2'b00!

2’bxx  # Branch 2'b00!

2’bzz  # Branch 2'b00!

2’b11  # Branch 2'b1x!

此處將case替換為casex後,從模擬結果可以看出,2’b0x、2’bxx與2’b00結果一致,2’bz0和2’bzz也與結果一致,即不對敏感表示式與分支表示式中對應位存在x和z的位進行比較.可見casex語句中會忽略表示式中的高阻態位和不定態.

【示例】

`timescale 1 ns / 1 ps

module top_tb;

reg [7:0] in;

reg [7:0] out;

initial begin

in = 8'b0000_0000;

#1 in = 8'b0000_0001;

#1 in = 8'b0000_0010;

#1 in = 8'b0000_0100;

#1 in = 8'b0000_1000;

#1 in = 8'b0001_0000;

#1 in = 8'b0010_0000;

#1 in = 8'b0100_0000;

#1 in = 8'b1000_0000;

#1 in = 8'b0010_0100;

#1 in = 8'b1111_0010;

#1 in = 8'b0000_1111;

#1 $stop;

end

always @*

begin

casez(in)

8'bzzzz_zzz1 : out = 0;

8'bzzzz_zz1z : out = 1;

8'bzzzz_z1zz : out = 2;

8'bzzzz_1zzz : out = 3;

8'bzzz1_zzzz : out = 4;

8'bzz1z_zzzz : out = 5;

8'bz1zz_zzzz : out = 6;

8'b1zzz_zzzz : out = 7;

default      : out = 0;

endcase

end

endmodule

【模擬結果】

從模擬結果可以看出,在進行匹配時,當有多位匹配成功,從右側開始第一次匹配成功的分支會被執行.示例中in為’h24和’h02的結果是一致的,’h0f和’h01的結果是一致的.

從上述幾例可以看出case、casez和casex在對0/1/z/x進行比較時的對應關係如下表:

case

0

1

X

Z

 

casez

0

1

X

Z

 

casex

0

1

X

Z

0

1

0

0

0

0

1

0

0

1

0

1

0

1

1

1

0

1

0

0

1

0

1

0

1

1

0

1

1

1

X

0

0

1

0

X

0

0

1

1

X

1

1

1

1

Z

0

0

0

1

Z

1

1

1

1

Z

1

1

1

1

其中casez語句用來處理不考慮高阻值z的比較過程,casex語句則將高阻態z和不定態都視為忽略,即在表示式進行比較時,不將該位進行比較,這樣根據具體需要靈活使用casex和casez了.

綜上所述,case進行精確比較,會對每一位不管該位是0/1/z/x的任何值;casez進行忽略z的比較,如果敏感表示式和分支表示式中有一位為z,那麼在比較時該位的比較忽略;casex進行忽略x和z的比較,如果敏感表示式和分支表示式中有一位為x或者z,那麼在比較時該位的比較忽略,當有多位都可匹配時,僅從右側開始第一次匹配成功的分支會被執行.