Verilog初级教程(17)Verilog中的case语句
前言
case语句检查给定的表达式是否与列表中的其他表达式之一相匹配,并据此进行分支。它通常用于实现一个多路复用器。
如果要检查的条件很多,if-else结构可能不合适,因为它会综合成一个优先编码器而不是多路复用器。
正文
语法
一个Verilog case语句以case关键字开始,以endcase关键字结束。在括弧内的表达式将被精确地评估一次,并按其编写顺序与备选方案列表进行比较,与给定表达式匹配的备选方案的语句将被执行。一块多条语句必须分组,并在 begin 和 end 范围内。
// Here 'expression' should match one of the items (item 1,2,3 or 4)
case (<expression>)
case_item1 : <single statement>
case_item2,
case_item3 : <single statement>
case_item4 : begin
<multiple statements>
end
default : <statement>
endcase
如果所有的case项都不符合给定的表达式,则执行缺省项内的语句,缺省语句是可选的,在case语句中只能有一条缺省语句。case语句可以嵌套。
如果没有符合表达式的项目,也没有给出缺省语句,执行将不做任何事情就退出case块。
例子
下图所示的设计模块有一个2位选择信号,用于将其他三个3位输入中的一个信号连接到被调用的输出信号。根据sel的值,用case语句将正确的输入分配到输出。由于sel是一个2位信号,它可以有2^2种组合,从0到3。如果sel为3,默认语句有助于将输出设置为0。
module my_mux (input [2:0] a, b, c, // Three 3-bit inputs
[1:0] sel, // 2-bit select signal to choose from a, b, c
output reg [2:0] out); // Output 3-bit signal
// This always block is executed whenever a, b, c or sel changes in value
always @ (a, b, c, sel) begin
case(sel)
2'b00 : out = a; // If sel=0, output is a
2'b01 : out = b; // If sel=1, output is b
2'b10 : out = c; // If sel=2, output is c
default : out = 0; // If sel is anything else, out is always 0
endcase
end
endmodule
硬件原理图
通过对rtl代码进行RTL分析,得到一个表示4比1多路复用器的硬件原理图。
请看,当sel为3时,输出为零,sel为其他值时也有对应的输入。
在case语句中,只有当表达式中的每个位都与包括0、1、x和z在内的备选方案之一相匹配时,比较才会成功。在上图所示的例子中,如果sel中的任何位是x或z,默认语句将被执行,因为其他备选方案都不匹配。在这种情况下,输出将全部为0。
我们可以做下简单的仿真:
reg [2:0] a, b, c;
reg [1:0] sel;
wire [2:0] out;
my_mux m0 ( .a(a),
.b(b),
.c(c),
.sel(sel),
.out(out));
initial begin
$monitor ("[%0t] a=0x%0h b=0x%0h c=0x%0h sel=0b%b out=0x%0h", $time, a, b, c, sel, out);
for (int i = 0; i < 10; i = i+1) begin
a <= $random;
b <= $random;
c <= $random;
sel <= $random;
#10;
end
end
[0] a=0x4 b=0x1 c=0x1 sel=0bxx out=0x0
[10] a=0x3 b=0x5 c=0x5 sel=0bzx out=0x0
[20] a=0x5 b=0x2 c=0x1 sel=0bxx out=0x0
[30] a=0x5 b=0x6 c=0x5 sel=0bzx out=0x0
[40] a=0x5 b=0x4 c=0x1 sel=0bxz out=0x0
[50] a=0x6 b=0x5 c=0x2 sel=0bxz out=0x0
[60] a=0x5 b=0x7 c=0x2 sel=0bzx out=0x0
[70] a=0x7 b=0x2 c=0x6 sel=0bzz out=0x0
[80] a=0x0 b=0x5 c=0x4 sel=0bxx out=0x0
[90] a=0x5 b=0x5 c=0x5 sel=0bxz out=0x0
如果设计中的案例语句中案例项备选有x和z,结果就会大不相同。
module my_mux (input [2:0] a, b, c,
[1:0] sel,
output reg [2:0] out);
// Case items have x and z and sel has to match the exact value for
// output to be assigned with the corresponding input
always @ (a, b, c, sel) begin
case(sel)
2'bxz : out = a;
2'bzx : out = b;
2'bxx : out = c;
default : out = 0;
endcase
end
endmodule
结果为:
[0] a=0x4 b=0x1 c=0x1 sel=0bxx out=0x1
[10] a=0x3 b=0x5 c=0x5 sel=0bzx out=0x5
[20] a=0x5 b=0x2 c=0x1 sel=0bxx out=0x1
[30] a=0x5 b=0x6 c=0x5 sel=0bzx out=0x6
[40] a=0x5 b=0x4 c=0x1 sel=0bxz out=0x5
[50] a=0x6 b=0x5 c=0x2 sel=0bxz out=0x6
[60] a=0x5 b=0x7 c=0x2 sel=0bzx out=0x7
[70] a=0x7 b=0x2 c=0x6 sel=0bzz out=0x0
[80] a=0x0 b=0x5 c=0x4 sel=0bxx out=0x4
[90] a=0x5 b=0x5 c=0x5 sel=0bxz out=0x5
有关更多case的讨论,例如casex/casez等,跳转链接:【 Verilog HDL 】case, casez, casex 之干货总结
case与if-else有什么不同?
case语句与if-else-if有两点不同。
- 在if-else块中给出的表达式比较笼统 而在case块中,一个表达式要与多个项目相匹配。
- 当一个表达式中存在X和Z值时,case将提供一个明确的结果。
往期回顾
Verilog初级教程(15)Verilog中的阻塞与非阻塞语句
Verilog初级教程(12)Verilog中的generate块
Verilog初级教程(11)Verilog中的initial块
Verilog初级教程(10)Verilog的always块
Verilog初级教程(8)Verilog中的assign语句
Verilog初级教程(7)Verilog模块例化以及悬空端口的处理
Verilog初级教程(5)Verilog中的多维数组和存储器
Verilog初级教程(2)Verilog HDL的初级语法
FPGA/ASIC初学者应该学习Verilog还是VHDL?
参考资料及推荐关注
个人微信公众号: FPGA LAB