casez与casex语句是case语句的两种变体, 在写testbench时用到。case 语句是一种多路条件分支的形式,可以解决 if 语句中有多个条件选项时使用不方便的问题。
一、case、casex、casez的区别
下表给出case、casex、casez的真值表:
1)在case语句中,敏感表达式中与各项值之间的比较是一种全等比较,每一位都相同才认为匹配。
2)在casez语句中,如果分支表达式某些位的值为高阻z,那么对这些位的比较就会忽略,不予考虑,而只关注其他位的比较结果。
3)在casex语句中,则把这种处理方式进一步扩展到对x的处理,即如果比较双方有一方的某些位的值是z或x,那么这些位的比较就不予考虑。
二、case/casez/casex 在simulation/synthesis的区别
有的网上说casex和casez属于不可综合语句,这是针对一般电路不会出现x状态来说的,但是综合工具并不会对x,z认识这个状态,所以综合出来的电路是一样的。
使用过程中许需要注意的问题:
1)一般经常使用到的是casez语句,最好少用casex
2)case/casez/casex其实都是可综合的
3)在电路中,可以用?来表示无关值的z
4)case的描述,匹配都是从上到下进行的
仿真的不同
1)对于case
- Example1:
- case (sel)
- 2'b00: y = a;
- 2'b01: y = b;
- 2'bx0: y = c;
- 2'b1x: y = d;
- 2'bz0: y = e;
- 2'b1?: y = f;
- default : y = g;
- endcase
对于case来说,每一种情况都会识别(1/0/z/x);当sel的状态是以下情况时,会出现以下结果
2)对于casez
- Example2:
- casez (sel)
- 2'b00: y = a;
- 2'b01: y = b;
- 2'bx0: y = c;
- 2'b1x: y = d;
- 2'bz0: y = e;
- 2'b1?: y = f;
- default: y = g;
- endcase
首先,case的描述,匹配都是从上到下进行的,如果使用了casez,看上面的casez的列表,只要输入有z/?的话,就能和任意匹配。
3)对于casex
- Example3:
- casex (sel)
- 2'b00 : y = a;
- 2'b01 : y = b;
- 2'bx0 : y = c;
- 2'b1x : y = d;
- 2'bz0 : y = e;
- 2'b1? : y = f;
- default : y = g;
- endcase
casex也是从上到下匹配,当出现x/z/?的输入的时候,都不会care
综合的时候,因为综合工具其实都不会管你什么x/z/?,对于综合工具来说是一样的,所以case/casez/casex不同写法的综合结果,例子都是同样的。
- Example4:
- case (sel)
- 2'b00 : mux_out = mux_in[0];
- 2'b01 : mux_out = mux_in[1];
- 2'b1? : mux_out = mux_in[2];
- default : mux_out = mux_in[3];
- endcase
- Example5:
- case (sel)
- 2'b00 : mux_out = mux_in[0];
- 2'b01 : mux_out = mux_in[1];
- 2'b1x : mux_out = mux_in[2];
- default : mux_out = mux_in[3];
- endcase
这俩个例子的结果是一样的。
case(不是casez/casex的时候)的列表里面的x和z,都被综合工具认为是不可达到的状态就被去掉了。casez和casex里面的x/z都被认为是don’t care。
对于综合、仿真的结果
1)在实际写代码的时候,如果使用case的时候,尽量不要用x/z/?,综合工具也会不care
2)casez和casex综合的结果是一致的。
3)casez稍好用一些,因为它可以用来代表don’t care的值
4)最重要的一点就是,casez和casex其实没有孰优孰劣
5)casez语句用来处理不考虑高阻值z的比较过程,casex语句则将高阻值z和不定值都视为不必关心的情况。所谓不必关心的情况,即在表达式进行比较时,不将该位的状态考虑在内。这样在case语句表达式进行比较时,就可以灵活地设置以对信号的某些位进行比较。
case 语句格式如下:
case(case_expr) condition1 : true_statement1 ; condition2 : true_statement2 ; …… default : default_statement ; endcase
case 语句执行时,如果 condition1 为真,则执行 true_statement1 ; 如果 condition1 为假,condition2 为真,则执行 true_statement2;依次类推。如果各个 condition 都不为真,则执行 default_statement 语句。
default 语句是可选的,且在一个 case 语句中不能有多个 default 语句。
条件选项可以有多个,不仅限于 condition1、condition2 等,而且这些条件选项不要求互斥。虽然这些条件选项是并发比较的,但执行效果是谁在前且条件为真谁被执行。
ture_statement1 等执行语句可以是一条语句,也可以是多条。如果是多条执行语句,则需要用 begin 与 end 关键字进行说明。
case 语句支持嵌套使用。
下面用 case 语句代替 if 语句实现了一个 4 路选择器的功能。仿真结果与 testbench 可参考条件语句一章,两者完全一致。
- Example1:
- module mux4to1(
- input [1:0] sel ,
- input [1:0] p0 ,
- input [1:0] p1 ,
- input [1:0] p2 ,
- input [1:0] p3 ,
- output [1:0] sout);
-
- reg [1:0] sout_t ;
- always @(*)
- case(sel)
- 2'b00: begin
- sout_t = p0 ;
- end
- 2'b01: sout_t = p1 ;
- 2'b10: sout_t = p2 ;
- default: sout_t = p3 ;
- endcase
- assign sout = sout_t ;
- endmodule
case 语句中的条件选项表单式不必都是常量,也可以是 x 值或 z 值。当多个条件选项下需要执行相同的语句时,多个条件选项可以用逗号分开,放在同一个语句块的候选项中。但是 case 语句中的 x 或 z 的比较逻辑是不可综合的,所以一般不建议在 case 语句中使用 x 或 z 作为比较值。
例如,对 4 路选择器的 case 语句进行扩展,举例如下:
- Example2:
- case(sel)
- 2'b00: sout_t = p0 ;
- 2'b01: sout_t = p1 ;
- 2'b10: sout_t = p2 ;
- 2'b11: sout_t = p3 ;
- 2'bx0, 2'bx1, 2'bxz, 2'bxx, 2'b0x, 2'b1x, 2'bzx :
- sout_t = 2'bxx ;
- 2'bz0, 2'bz1, 2'bzz, 2'b0z, 2'b1z :
- sout_t = 2'bzz ;
- default: $display("Unexpected input control!!!");
- endcase
casex、 casez 语句是 case 语句的变形,用来表示条件选项中的无关项。casex 用 "x" 来表示无关值,casez 用问号 "?" 来表示无关值。两者的实现的功能是完全一致的,语法与 case 语句也完全一致。但是 casex、casez 一般是不可综合的,多用于仿真。
例如用 casez 语句来实现一个 4bit 控制端的 4 路选择选择器。
- Example3:
- module mux4to1(
- input [3:0] sel ,
- input [1:0] p0 ,
- input [1:0] p1 ,
- input [1:0] p2 ,
- input [1:0] p3 ,
- output [1:0] sout);
- reg [1:0] sout_t ;
- always @(*)
- casez(sel)
- 4'b???1: sout_t = p0 ;
- 4'b??1?: sout_t = p1 ;
- 4'b?1??: sout_t = p2 ;
- 4'b1???: sout_t = p3 ;
- default: sout_t = 2'b0 ;
- endcase
- assign sout = sout_t ;
- endmodule