关于full_case和parallel_case属性

许多SystemVerilog设计者在使用case语句时,不认真考虑,随便乱用full_case和parallel_case属性。这是一个很不好的习惯,在一般情况下,不应该使用这些属性。这两个属性只适合用于综合,并且有可能造成综合后产生的硬件电路功能不同于RTL仿真时的行为。

一、full_case属性

在SystemVerilog语言中,case语句的每个case项(即每个分支项的冒号左边的判断条件)依次与case表达式进行比较,如果相等,则执行该分支的表达式。所谓“full case”语句是指case表达式中由0、1、z、x组成的每个组合都可以与某个或多个case项匹配(完全相等)。这一点适用于casez及casex语句,这两种case语句的判断中包括无关项。case语句的条件项并非必须是齐全的,只要在条件项中包括一个默认项,就可以将所有条件都包括在内。若case语句的条件项不齐全,没有覆盖的条件中包括了1和0的组合,且没有包括默认的条件项,则综合工具必然正确地推断出电路中存在着锁存器。例如,下面这一小段程序中,若省略默认项,则当a=4'b0000或4'b000z或等于包括一个x的任何值时,就找不到匹配项目,所以该case语句就不齐全。

always @(a)
    casez (a)
        4'b1??? : y = 2'b11;
        4'b01?? : y = 2'b10;
        4'b001? : y = 2'b01;
        4'b0001 : y = 2'b00;
        default : y = 2'b00;
    endcase

如果在case语句中添加了full_case属性,相当于设计者告诉综合工具必须把那些尚未指定的输入组合当做无关项条件进行处理,换言之,相当于假设默认项的存在。因此,这段程序的RTL仿真和综合后网表的仿真行为将出现不一致。当然,若源程序中早就有默认项,则添加full_case属性就是多余的。

因此,建议不要使用full_case属性,而代之以在代码中包括默认项来表示case语句的判断条件是齐全的。默认项的输出值应该是有意义的值(不是z或x),否则会产生锁存器。在前面的例子中,把默认项的输出值设置为2'bxx,意味着默认项不会产生有效的硬件,因此隐含表示有可能产生锁存器。通常应该在case语句的最后的判断分支添加一个有确定输出的赋值语句。

 

二、parallel_case属性

并行case语句是这样一种case语句,其中每个输入组合正好被覆盖一次。在编写case语句时,若输入的参数值与两个或更多的分支条件匹配,则该语句是完全符合语法的。因为分支的判断是遵循代码中判断条件出现的先后顺序进行的,这就意味着电路中存在优先逻辑。然而,使用parallel_case属性,则意味着使用并行逻辑。添加parallel_case属性将迫使综合工具生成并行逻辑来满足case语句的要求。因此,这将不可避免地使得综合后生成的硬件网表的行为与RTL代码的仿真行为出现不一致。

前面所举的例子都是并行的,因此,添加parallel_case属性是多余的。下面这个例子不是并行的:

always @(a)
    casez (a)
        4'b1??? : y = 2'b11;
        4'b?1?? : y = 2'b10;
        4'b??1? : y = 2'b01;
        4'b???1 : y = 2'b00;
        default : y = 2'b00;
    endcase

在仿真的时候,上述代码的功能与前面介绍过的例子完全一致。若输入a=4'b1011,则必定匹配第一个分支,所以产生的输出是y=2'b11。这个输入也能与第三和第四个分支匹配,因此,若产生这个输出,则表明该case语句不是并行的。若指定了parallel_case属性,则有可能使综合工具不明白设计者的意图,综合的结果很可能出错。

因此,建议不要使用parallel_case属性来生成并行的逻辑。若必须使用有优先排序的逻辑,则请使用if-else语句。若使用case语句,则需注意综合工具反馈的信息,若综合工具报告case语句不是并行的,则应修改case语句使其变成并行结构。

 

三、参考文档

《SystemVerilog数字系统设计》

【Arcanis the Omnipotent】从今天起弄明白case/casez/casex

你可能感兴趣的:(verilog,verilog)