\;\;\;\;\; 本文通过对比实验,深入分析Verilog中if-else与case语句在条件互斥与不互斥情况下综合出来的电路。实验结果表明:条件互斥时两种语句综合结果相同,均无优先级;条件不互斥时两种语句均会产生优先级电路。文章揭示了优先级电路产生的根本原因在于条件本身,而非语句类型。
一、引言
\;\;\;\;\; 在FPGA设计中,if-else和case是最常用的两种条件判断语句。经常会听到if-else有优先级、case无优先级。这个说法真的正确吗?
\;\;\;\;\; 实际上,这是一个需要深入分析的误区。优先级电路的产生并非取决于语句类型,而是取决于条件之间是否互斥。
\;\;\;\;\; 本文通过两个典型示例,分别验证条件互斥和条件不互斥两种情况下if-else与case语句的综合结果,揭示优先级电路的真正产生机制。
\;\;\;\;\; 请注意本文所用综合工具为VIVADO,不同的工具综合效果可能会有差异。
二、条件互斥情况分析
\;\;\;\;\; 条件互斥 是指各个判断条件之间不存在重叠,任何时刻最多只有一个条件成立。例如,对于一个3位选择信号sel,条件sel == 3'b100和sel == 3'b010就是互斥的,因为sel不可能同时等于100和010。
\;\;\;\;\; 设计如下测试模块,其中if-else和case语句使用完全相同的互斥条件:
verilog
module test_huchi(
input wire clk,
input wire [2:0] sel,
input wire a,
input wire b,
input wire c,
output reg y_if,
output reg y_case
);
always @(posedge clk)
begin
if(sel == 3'b100)
y_if <= a;
else if(sel == 3'b010)
y_if <= b;
else
y_if <= c;
end
always @(posedge clk)
begin
case(sel)
3'b100: y_case <= a;
3'b010: y_case <= b;
default: y_case <= c;
endcase
end
endmodule
\;\;\;\;\; 综合得到的电路如图1所示。

\;\;\;\;\; 观察电路图可以发现,当条件互斥时,两种语句的综合结果完全相同。
\;\;\;\;\; 二者均只是用了一个查找表,打开查找表的真值表就能发现是不存在优先级的,如图2所示。

\;\;\;\;\; 这是因为综合工具能够识别出条件互斥的特性,从而将串行的if-else链优化为并行的选择器结构。此时,if-else和case语句在硬件实现上没有本质区别。
三、条件不互斥情况分析
\;\;\;\;\; 条件不互斥 是指各判断条件之间存在重叠,某些情况下多个条件可能同时成立。例如,条件sel[2]==1和sel[1]==1就是不互斥的,因为当sel=3'b110时,两个条件同时成立。
\;\;\;\;\; 我们修改测试模块,使用不互斥的条件:
verilog
module test_no_huchi(
input wire clk,
input wire [2:0] sel,
input wire a,
input wire b,
input wire c,
output reg y_if,
output reg y_case
);
always @(posedge clk)
begin
if(sel[2]==1)
y_if <= a;
else if(sel[1] == 1)
y_if <= b;
else
y_if <= c;
end
always @(posedge clk)
begin
casez(sel)
3'b1??: y_case <= a;
3'b?1?: y_case <= b;
default: y_case <= c;
endcase
end
endmodule
\;\;\;\;\; 注意这里使用了casez语句。
\;\;\;\;\; 这里使用case不可行,如果直接用case,只会执行语句default: y_case <= c,这是因为case会严格判断0/1/z/x是否相等。
\;\;\;\;\; 使用以上代码综合得到的电路如图3所示。

\;\;\;\;\; if-else的真值表如图4所示。

\;\;\;\;\; 分析图4,I1接的sel[2],I3接的sel[1],I0接的a,I2接的b。所以当I1=1时,O=I0,当I1=0且I3=1时,O=I2。
\;\;\;\;\; 可见条件不互斥时,if-else电路是有优先级的,sel[2]==1和sel[1]==1都成立时执行的y_if <= a。
\;\;\;\;\; case的真值表如图5所示。

\;\;\;\;\; 分析图5,I3接的sel[2],I2接的sel[1],I0接的a,I4接的b。所以当I3=1时,O=I0,当I3=0且I2=1时,O=I4。
\;\;\;\;\; 可见,条件不互斥时,case电路也存在优先级,这时候匹配就是从上到下。
\;\;\;\;\; 如图6所示,当sel=3'b110时,左边的case执行的是y_case <= a,右边的case执行的是y_case <= b。
\;\;\;\;\; 图6中两段代码的真值表是不一样的,感兴趣的读者可自行在vivado验证,笔者这里不过多赘述。

\;\;\;\;\; 由此可见,当条件不互斥时,即使是case语句也会产生优先级电路!
\;\;\;\;\; 这是因为当sel=3'b110时,两个条件同时满足,硬件必须有确定的输出,因此综合工具会按照代码书写顺序确定优先级。
四、总结
\;\;\;\;\; 通过两个典型实验,可得出:
\;\;\;\;\; 条件互斥时,if-else和case语句的综合结果完全相同,都无优先级。综合工具能够识别条件互斥特性并进行优化。
\;\;\;\;\; 条件不互斥时,两种语句都会产生优先级电路,综合结果也基本相同。但case语句的优先级取决于分支项的顺序。
\;\;\;\;\; 这一结论纠正了if-else有优先级、case无优先级的片面理解。在实际设计中,工程师应根据条件互斥性和设计需求选择合适的语句。