本文
主要介绍Verilog语法中case,casex,casez的区别,以及建议使用方法。
关于case
1
2
3
4
5
6
7
8
9
|
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
|
sel |
y |
case item |
00 |
a |
00 |
11 |
g |
default |
xx |
g |
default |
x0 |
c |
x0 |
1z |
f |
1? |
z1 |
g |
default |
可见,case语法对四值0 1 X Z是严格匹配的,并且语义中“?”代表Z值。
关于casez
1
2
3
4
5
6
7
8
9
|
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
|
sel |
y |
case item |
00 |
a |
00 |
11 |
f |
1? |
xx |
g |
default |
x0 |
c |
x0 (would have matched with z0(item 5) if item 3 is not present.) |
1z |
d |
1x (would have matched with z0(item 5) & 1?(item 6) also.) |
z1 |
b |
01 (would have matched with 1?(item 6) also.) |
首先,casez的匹配顺序是从上到下。根据上面casez的匹配列表,可见casez语法将表达式的“z/?”与输入的任意值(0 1 X Z)匹配,而表达式的“x 0 1”和输入的“x 0 1”还是严格匹配。所以,一般我们对于不关心的信号位使用casez语句,并在选项中将该位设为"z/?"。这也是最推荐的写法。
关于casex
1
2
3
4
5
6
7
8
9
|
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
|
sel |
y |
case item |
00 |
a |
00 |
11 |
d |
1x (would have matched with 1? also) |
xx |
a |
00 (would have matched with all) |
x0 |
a |
00 (would have matched with all items except 01) |
1z |
c |
x0 (would have matched with all items except 00,01) |
z1 |
b |
01 (would have matched with 1x, 1? also) |
同样,casex的匹配顺序也是从上到下。根据上面casex的匹配列表,可见casex语法将将表达式中“z/?/x”与输入的任意值(0 1 X Z)匹配,而表达式中的“0 1”与输入的“0 1”严格匹配。
总结
总结如下:
- case、casex、casez的匹配顺序都是从上到下。
- case严格匹配,casez中表达式z/?代表不关心该位的状态值(最好使用?),casex中表达式x/z/?代表不关心该位的状态值。
- case、casex、casez都是可综合的,不过在case中综合电路无法解析x/z/?,会将其认为不关心,这样会使RTL语义和综合电路间产生偏差,所以case语句表达式中不建议使用x/z/?。
- 尽量不使用casex,因为在初始条件下,控制信号可能存在大量x,使用casex会对电路的选择功能造成混乱,隐藏选择信号x值对电路功能的影响。
推荐使用casez,代码格式如下:
1
2
3
4
5
6
|
casez (sel)
2'b00: y = a;
2'b01: y = b;
2'b1?: y = c;
default : y = d;
endcase
|
代码功能等同于:
1
2
3
4
5
6
|
case (sel)
2'b00: y = a;
2'b01: y = b;
2'b10,2'b11: y = c;
default : y = d;
endcase
|
文章原创,可能存在部分错误,欢迎指正,联系邮箱 cao_arvin@163.com。