casez和casex谁是谁
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进行比较时的对应关系如下表:
其中casez语句用来处理不考虑高阻值z的比较过程,casex语句则将高阻态z和不定态都视为忽略,即在表达式进行比较时,不将该位进行比较,这样根据具体需要灵活使用casex和casez了.
综上所述,case进行精确比较,会对每一位不管该位是0/1/z/x的任何值;casez进行忽略z的比较,如果敏感表达式和分支表达式中有一位为z,那么在比较时该位的比较忽略;casex进行忽略x和z的比较,如果敏感表达式和分支表达式中有一位为x或者z,那么在比较时该位的比较忽略,当有多位都可匹配时,仅从右侧开始第一次匹配成功的分支会被执行.