Verilog基础语法——条件语句case、if-else
- 写在前面
- 一、if-else语句
- 二、case语句
- 2.1 case语句
- 2.2 casez语句
- 2.3 casex语句
- 写在后面
写在前面
在Verilog语法中,常用的条件语句有if-else语句和case语句,用于判断条件是否为真,并执行判断条件后面的表达式。
一、if-else语句
if-else语句的基本语法如下:
if(条件1)
// 表达式1...
else if(条件2)
// 表达式2...
else // 其他条件
// 表达式3...
if-else语句也可以嵌套使用,其语法如下:
if(条件1)
if(条件2)
// 表达式1...
else
// 表达式2...
else // 其他条件
// 表达式3...
在使用if-else语句时,若不补全else语句以及后面的表达式,则默认在除了所列出条件以外的其他条件下,保持变量原先的值。而对于组合逻辑而言,变量保持原先的值,电路综合时会综合出锁存器Latch。比如:
// 会产生锁存器Latch(组合逻辑中)
always @(*) begin
if(条件1)
// 表达式1
end
而在时序逻辑中,变量保持原先的值,不会产生锁存器Latch,所以对于else语句下变量保持原先的值的情况,可以不补全else语句(建议补全else条件后执行的表达式)。
// 不会产生锁存器Latch(时序逻辑中)
always @(posedge clk) begin
if(条件1)
// 表达式1
end
如果在组合逻辑中使用if-else语句,有一种等价写法,用连续赋值语句assign进行替换。比如:
reg [1:0] out;
always @(*) begin
if(a == 2'b11)
out = 2'b00;
else if(a == 2'b10)
out = 2'b11;
else
out = 2'b01;
end
可以使用三目运算符“ ?: ”进行替换,如下。需要注意的是连续赋值语句assign赋值的变量是wire型变量,而在always语句中赋值的变量是reg型变量。
wire [1:0] out;
assign out = (a == 2'b11) ? 2'b00 : (a == 2'b10) ? 2'b11 : 2'b01;
问题一:if-else语句中各个条件是否具有优先级?各个条件的判断是串行的还是并行的?条件互斥是否存在影响?
以下面这段代码为例,if-else语句中各个条件互斥。
// if-else(条件互斥)
module top(
input wire [1:0] din ,
input wire [3:0] din_a,
input wire [3:0] din_b,
input wire [3:0] din_c,
input wire [3:0] din_d,
output reg [3:0] dout
);
always @(*) begin
if(din == 2'b00)
dout = din_a;
else if(din == 2'b01)
dout = din_b;
else if(din == 2'b10)
dout = din_c;
else if(din == 2'b11)
dout = din_d;
else
dout = 4'b0000;
end
endmodule
上述代码对应的真值表如下所示:
其RTL Schematic如下图所示,可以看出这里5个条件所对应的4个MUX是串行的,存在优先级关系,其中优先级顺序为:第一级>第二级>第三级>第四级。
而在FPGA内部,MUX是由LUT构成的,综合后的电路是否存在优先级关系?下图为综合后的Schematic,可以看到综合后的实际电路是并行的。
这里if-else语句条件是互斥的,互斥是否会存在影响?对上述代码稍加修改(各个条件不互斥),如下:
// if-else(条件不互斥)
module top(
input wire [1:0] din ,
input wire [3:0] din_a,
input wire [3:0] din_b,
input wire [3:0] din_c,
output reg [3:0] dout
);
always @(*) begin
if(din[0] == 1'b1)
dout = din_a;
else if(din[1] == 1'b1)
dout = din_b;
else
dout = din_c;
end
endmodule
上述代码对应的真值表如下所示:
其RTL Schematic如下图所示,可以看出这里3个条件所对应的2个MUX同样是串行的,存在优先级关系,其中优先级顺序为:第一级>第二级。
再对上述代码进行综合,综合后的电路如下。可以看出综合后的电路是并行的,不存在优先级关系。
综上所述,在FPGA设计中,if-else语句综合后的电路无优先级关系,是并行执行的,与判断条件是否互斥无关。
二、case语句
if-else语句常用于判断条件较少的情况。对于判断条件较多的情况下,使用if-else语句会显得繁琐,使用case语句会更加简洁直观。本节介绍case语句、casez语句和casex语句三者的用法。
2.1 case语句
case语句的基本语法如下:
case(判断条件)
条件值1: 表达式1;
条件值2: 表达式2;
条件值3: 表达式3;
default: 表达式4; // 其他条件
endcase
case语句中只有当判断条件与条件值完全相等时,才为真值(True),执行条件值对应的表达式。case语句的真值表如下所示:
case | 1 | 0 | x | z |
---|---|---|---|---|
1 | 1 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
case语句中有两点需要注意:(1)case语句没有补全default,则对于未声明的情况,变量保持原先的值。在组合逻辑中,若未声明所有情况,则对于未声明的情况,变量保持原先的值,综合时会产生锁存器Latch。而在时序逻辑中,对于未声明的情况,变量保持原先的值,综合出来的是寄存器;(2)case语句中各个状态之间需要互斥,若各个状态不互斥,则比较电路的输出结果可能是不定态x。
问题: case语句是否具有优先级?是串行还是并行?
同样的,将前面if-else示例中的if-else语句替换为case语句,如下:
// case(条件互斥)
module top(
input wire [1:0] din ,
input wire [3:0] din_a,
input wire [3:0] din_b,
input wire [3:0] din_c,
input wire [3:0] din_d,
output reg [3:0] dout
);
always @(*) begin
case(din)
2'b00: dout = din_a;
2'b01: dout = din_b;
2'b10: dout = din_c;
2'b11: dout = din_d;
default : dout = 4'b0000;
endcase
end
endmodule
其RTL Schematic如下图所示,可以看到case对应的各个条件之间无优先级关系,是并行的。
综合后的电路如下图所示,是并行的。
综上所述,case语句的各个条件之间无优先级关系,是并行的。
2.2 casez语句
casez语句的基本语法如下:
casez(判断条件)
条件1: 表达式1;
条件2: 表达式2;
条件3: 表达式3;
default: 表达式4; // 其他条件
endcase
casez语句的语法与case语句一致,但是其真值表不一致,如下表所示。
casez | 1 | 0 | x | z |
---|---|---|---|---|
1 | 1 | 0 | 0 | 1 |
0 | 0 | 1 | 0 | 1 |
x | 0 | 0 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
在casez语句中,将高阻态z视为不关心的状态,即在进行比较时,高阻态z与任意状态的比较结果(==)均为真值1(True)。
2.3 casex语句
casex语句的基本语法如下:
casex(判断条件)
条件1: 表达式1;
条件2: 表达式2;
条件3: 表达式3;
default: 表达式4; // 其他条件
endcase
casex语句的真值表,如下表所示。在casex语句中将高阻态z和不定态x都视为不关心的状态,即在进行比较时,高阻态z、不定态x与任意状态的比较结果(==)均为真值1(True)。
casex | 1 | 0 | x | z |
---|---|---|---|---|
1 | 1 | 0 | 1 | 1 |
0 | 0 | 1 | 1 | 1 |
x | 1 | 1 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
写在后面
在本文中,我们学习了if-else语句和case语句(case/casez/casex)的基本用法以及两者之间的区别。通过实验对比if-else语句与case语句综合后的电路,结果表明,两种条件语句中的各个条件不存在优先级关系,综合后的电路是并行的。
🧐:以上为个人学习笔记,如有疑问,欢迎评论区交流探讨 !!!