SystemVerilog-决策语句-case语句
数字硬件建模SystemVerilog-决策语句-case语句
经过几周的更新,SV核心部分用户自定义类型和包内容已更新完毕,接下来就是RTL表达式和运算符。
马上HDLBits-SystemVerilog版本也开始准备了,基本这一部分完成后就开始更新~
决策语句(Decision statements)允许程序块的执行流程根据设计中信号的当前值分支到特定语句。SystemVerilog有两个主要的决策语句:if…else语句和case语句,使用关键字case、case…inside,casex和casez。
介绍
case语句提供了一种简洁的方式来表示一系列决策选择。例如:
SystemVerilog case语句与C switch语句类似,但有重要区别。SystemVerilog不能使用break语句(C使用break从switch语句的分支退出)。case语句在执行分支后自动退出(使用break退出case语句是非法的。),不能执行break语句。
SystemVerilog有4种不同的case语句,关键字为case、case…inside casex和casez。这些不同case语句的一般语法和用法是相同的。这些区别将在本文后面介绍。
case、casex或casez关键字后面跟一个用括号括起来的case表达式。case表达式可以是网络、变量、用户定义类型、参数常量、文字值或运算结果。case表达式后面跟一个冒号,如果case表达式与case项匹配,后续执行是可以是一条语句或者begin-end包含的系列语句。
默认case项 。可以使用default关键字指定可选的默认case项。如果case表达式与任何case项不匹配,将执行默认case项。在上面的例子中,case项覆盖了2位操作码的所有可能的2-state值。但是,如果操作码是4-state类型,则会有额外的X和Z值未被case项覆盖。如果操作码的任何位都是X或Z,则将执行默认case项,在前面的示例中,该分支将把X值传播到结果变量上。默认情况下的case项不需要是最后一个case项。语法上,默认case项可以是第一个case项,或者在case项中的任何地方,代码可读性的最佳实践编码风格是默认case项为最后一个case项。
以逗号分隔的case项列表。case项可以是逗号分隔的列表,如以下代码段所示:
如果操作码的值为2’b00或2’b01,则执行case语句的第一个分支,如果值为2’b10或2’b11,则执行第二个分支。
case与case…inside
当只使用case关键字时, case表达式将与case项进行比较,比较的运算符为(===)。(===)运算符将比较表达式的每一位,这将获得4-state值的精确匹配。在下面的代码段中,如果select的值为1’bz,则执行第三个分支,如果select的值为1’bx,则执行第四个分支(此示例不可综合;综合不允许比较X和Z值)
在case…inside语句中,使用(==?)通配符case相等运算符的行为将case表达式与case项进行比较(case使用===运算符)。(==?)运算符允许从比较中屏蔽某一位(即不进行某一位的比较)。case项中的任何位被设置为x或z或?当case表达式与case项进行比较时,该位位置将被忽略。
在以下示例中,如果selector的最高有效位置1,将执行第一个分支,忽略case项的所有剩余位,如果selector的上两位的值为01,将执行第二个分支,并忽略剩余位,依此类推:
过时的casex和casez语句
在SystemVerilog于2005年扩展Verilog语言之前,最初的Verilog语言使用casex和casez关键字来屏蔽比较中的位。SystemVerilog将casex和casez替换为case…inside关键字。casex和casez语句屏蔽了设置为x、z或?的任何位。Casez语句仅屏蔽设置为z或?的位
最佳实践指南6-2 |
---|
用case…inside在决策语句中忽略case项中的特定位。不要使用过时的casex和casez语句。 |
SystemVerilog取代casex和casez的原因是,它们在仿真时存在严重缺陷,在综合逻辑门后,其行为与RTL仿真非常不同。简而言之,casex和casez不仅允许在case项中屏蔽位,还允许在case表达式中屏蔽位,这种双重掩蔽可能会导致执行一个非预期的分支,而这可能不是由综合创建的门级电路实现时采用的同一个分支。casex和casez的缺点在本系列文章中没有详细讨论,因为没有必要使用这些过时的语句。
case项优先级和综合优化
case项按其列出的顺序进行评估。因此,第一个case项的优先级高于所有后续case项。在评估case语句时,仿真将始终遵循此优先级。
这种推断出的优先级编码在ASIC或FPGA实现中通常是不可取的。与 并行计算 相比,优先级编码逻辑需要更多的逻辑门和更长的传播路径。在将case语句转换为逻辑门之前,综合编译器将分析case项的值。如果两个case项不可能同时为真,则综合编译器将自动优化门级实现,以并行评估case项,而不是作为优先级编码功能。
然而,如果两个或多个case项可能同时为真,那么综合将实现case语句仿真中固有的优先级编码逻辑。通过实施优先级编码,综合时将确保ASIC或FPGA的门级行为与RTL仿真行为匹配。
例6-5显示了一个4选1的多路复用器。在本例中,四个case表达式具有唯一的、不重叠的值。综合器将识别到两个case表达式不可能同时为真,并自动删除case项的优先级编码。图6-5显示了综合器如何实现case语句。
示例6-5:使用case语句对4选1多路复用器建模
//`begin_keywords "1800-2012" // use SystemVerilog-2012 keywords
module mux4to1
#(parameter N=8)
input logic [N-1:0] a, b, c, d,
input logic [ 1:0] select,
output logic [N-1:0] y
always_comb begin
case (select)
2'b00: y = a;
2'b01: y = b;
2'b10: y = c;
2'b11: y = d;
endcase
endmodule: mux4to1
//`end_keywords
图6-5:示例6-5的综合结果:综合4选1多路复用器的case语句
例6-5中的case项是互斥的,这意味着其中两个case项不可能同时成立。因此,综合编译器删除了case语句的优先级编码行为,并以多路复用器的形式对case项实现了更高效的并行计算,
综合编译器自动删除优先级逻辑,只要综合可以确定所有case项都是互斥的(不会有两个或多个case项同时计算结果为true)。如果综合编译器不能确定case项是互斥的,那么它将保留case项的优先级方式。
示例6-6类似于示例6-3中所示的4选2优先级编码器,但这次使用case…inside,只允许检查4位d_in值中的特定位。由于忽略了其他位,因此可能存在不止一个位case项同时为true,仿真将执行第一个匹配分支,综合编译器将通过“保留case语句固有的优先级编码”来匹配该行为。
示例6-6:使用内部的case项来仿真优先级编码器
//`begin_keywords "1800-2012" // use SystemVerilog-2012 keywords
module priority_4to2_encoder (
input logic [3:0] d_in,
output logic [1:0] d_out,
output logic error
timeunit 1ns; timeprecision 1ns;
always_comb begin
error = '0;
case (d_in) inside
4'b1???: d_out = 2'h3; // bit 3 is set
4'b01??: d_out = 2'h2; // bit 2 is set
4'b001?: d_out = 2'h1; // bit 1 is set
4'b0001: d_out = 2'h0; // bit 0 is set
4'b0000: begin // no bits set
d_out = 2'b0;
error = '1;