决策语句允许程序块的执行流程

描述

数字硬件建模SystemVerilog-决策语句-case语句

 

经过几周的更新,SV核心部分用户自定义类型和包内容已更新完毕,接下来就是RTL表达式和运算符。

马上HDLBits-SystemVerilog版本也开始准备了,基本这一部分完成后就开始更新~

RTL

决策语句(Decision statements)允许程序块的执行流程根据设计中信号的当前值分支到特定语句。SystemVerilog有两个主要的决策语句:if…else语句和case语句,使用关键字case、case…inside,casex和casez。

介绍

case语句提供了一种简洁的方式来表示一系列决策选择。例如:

RTL

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项可以是逗号分隔的列表,如以下代码段所示:

RTL

如果操作码的值为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值)

RTL

在case…inside语句中,使用(==?)通配符case相等运算符的行为将case表达式与case项进行比较(case使用===运算符)。(==?)运算符允许从比较中屏蔽某一位(即不进行某一位的比较)。case项中的任何位被设置为x或z或?当case表达式与case项进行比较时,该位位置将被忽略。

在以下示例中,如果selector的最高有效位置1,将执行第一个分支,忽略case项的所有剩余位,如果selector的上两位的值为01,将执行第二个分支,并忽略剩余位,依此类推:

RTL

过时的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 
 end 
endmodule: mux4to1
//`end_keywords 
RTL 图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;
             end
  endcase 
end 
endmodule: priority_4to2_encoder
//`end_keywords 

RTL 图6-6:示例6-6的综合结果:case…inside作为优先编码器

 

优先级逻辑的效果可以在一系列门电路中看到,d_in的不同位通过这些门传播。当使用一系列if-else-if语句时,综合编译器综合出来的电路非常相似,如上一章节的例程。

唯一和优先决策修饰符

SystemVerilog为case和if-else决策语句提供三个修饰符:unique、unique0和priority。后面章节将详细讨论RTL模型中使用的修饰符。

简而言之,unique、unigue0和priority修饰符有两个功能:

它们影响综合编译器在门级电路实现case语句的方式。

他们在仿真中将会报告警告消息,帮助验证综合效果是否会按预期工作。

这些决策修饰符的一个示例用法是:

RTL

对于综合,本例中的unique修饰符通知综合编译器case语句可以被认为是完整的,即使2位状态变量的四个可能值中只有三个被解码。同时还通知综合编译器,对case项并行评估是可以的。

对于仿真,unique关键字在仿真中启用两个检查例程,如果对case语句进行了评估,并且state的值与任何case项都不匹配,则将生成违规报告。此检查有助于验证将case语句视为完整的综合是否安全。如果state的值同时与多个案例项匹配,则还会生成违规报告。该检查有助于验证对case项并行评估是安全的,而不是按照case项列出的顺序,  

      审核编辑:彭静
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分