case语句,是包含在case和endcase之间的代码,逻辑上等价于if-else语句,使用方法如下:
case (case_expression)
case_item1 : case_item_statement1;
case_item2 : case_item_statement2;
case_item3 : case_item_statement3;
case_item4 : case_item_statement4;
default : case_item_statement5;
endcase
casez语句,允许"z" 和 "?"值在比较时被当作不关心,"z" 和 "?"时等价的。
注意:当编写可综合代码时,要小心使用casez;使用casez时,最好使用"?" 表示不关心,不能使用"z" 表示不关心。
casex语句,允许"x" "z" 和 "?"值在比较时被当作不关心.
注意:当编写可综合代码时,不要使用casez
case语句执行过程:
1. 每次执行case语句时,括号内case expression 只计算一次,然后按照从上到下的顺序与每个case item比较。
2. 如果有case default ,那么在这个从上到下的比较过程中忽略它。
3. 如果有一个case item 与 case expression 匹配上,那么就执行此case item语句,然后终止case语句。
· 4. 如果所有比较都失败,而且有case default,那么就执行case default语句,然后终止case语句。
5.如果所有比较都失败,而且没有case default,那么就终止case语句。
注意:1 排在前面的case item 具有更高的优先级。
2 所有的case expression 和 case item的位长都将调整到最长的位长。
3 如果有一个时unsigned,那么所有都按照unsigned调整。
case应用
case可以检查x和z
case (sig)
1'bz : $display ("signal is floating");
1'bx : $display ("signal is unknown");
default : $display ("signal is %b" ,sig);
endcase
case item中有x和z时,这段代码时不可综合的
可使用反向case语句,而且是优先级编码器。
reg [2:0] encode;
case (1)
encode[2] :$display ("Select Line 2");
encode[1] :$display ("Select Line 1");
encode[0] :$display ("Select Line 0");
default :$display ("Error: Only one of the bits is expected ON");
endcase
case 语句可以时full 和parallel :若是full,就不会产生latch ; 若是parallel ,就不会产生优先级编码器。综合工具一般可以自由推导出是否是full 或parallel。
// 这段代码就是full 又是 parallel ,因此既不会生产Latch 也不会生成优先级编码器
always @ (*)
begin
case (sel)
2'b00: outc = a;
2'b01: outc = b;
2'b10: outc = c;
2'b11: outc = d;
endcase
end
// 若使用if ,就会生成优先级编码器。
always @ (*)
begin
if(sel == 2'b00) outi = a;
else if (sel == 2'b01) outi = b;
else if (sel == 2'b10) outi = c;
else outi = d;
end
casez应用
在case item中,0 1 z x都要进行比较,z和?对应的bit在比较时忽略,x不会被忽略。常用于实现优先编码器。
//实现指令译码,优先级编码器
reg [7:0] ir;
casez (ir)
8'b1??????? : instruction1(ir);
8'b01?????? : instruction2(ir);
8'b00010??? : instruction3(ir);
8'b000001?? : instruction4(ir);
endcase
casex 会导致设计出现问题, 把x当作不关心,前后防结果不一致。复位前的高阻值在复位后将初始化错误隐藏。
// 在case语句前给输出赋一个默认值,综合会当成full的case语句,不会产生Latch
// 在case前给出输出信号默认值,不会出现前后仿真不一致的情况。
module mux3c (y, a, b, c, sel);
output y;
input [1:0] sel;
input a, b, c;
reg y;
always @ ( a or b or c or sel )
y = 1'b0 ; //<====== default value
case (sel)
2'b00 : y = a;
2'b01 : y = b;
2'b10 :y = c;
endcase
endmodule
//使用full_case综合指令
//仿真时,sel = 2'b11 ,y 表现为Latch;综合时,工具把sel == 2'b11时y输出当做不关心,从而导致前后防真不一致。
module mux3c (y, a, b, c, sel);
output y;
input [1:0] sel;
input a, b, c;
reg y;
always @ ( a or b or c or sel )
case (sel) // synopsys full_case
2'b00 : y = a;
2'b01 : y = b;
2'b10 :y = c;
endcase
endmodule
full_case会优化设计,导致设计结果出错。
full_case还是有可能生成Latch(case中对多个输出进行赋值)
消除Latch最简单的方法:在always块的敏感表下面,在执行case语句之前为每个输出都赋一个默认值。
parallel_case是指case expression只能匹配一个case item的语句。如果发现case expression能够匹配超过一个的case item,那么这些匹配的case item被称为overlapping case item,这个case语句就不是parallel
// Synopsys dc_shell 在读入Verilog文件时,如果full_case语句用在不是full的case语句上会报告warning
// Non_full case statement with "full_case" directive
// parallel_case同样会出现警告。
//该警告会使设计崩溃。
case语句的编码原则
1 对于编写表达式并行的设计,case语句是不错的选择,可使代码更加整洁
2 在设计可综合代码时,要小心使用casez语句,不要是要casex语句
3 要小心使用反向case语句,最好只针对时parallel的case语句使用
4 要小心使用casez设计优先级编码器,可以用if-else-if语句实现优先级编码器,这样意图更明显
5 在使用casez语句时,用?表示不关心的位。文章来源:https://www.toymoban.com/news/detail-447696.html
6 最好为case语句添加case default,而且不要把输出值赋值未x文章来源地址https://www.toymoban.com/news/detail-447696.html
到了这里,关于Verilog编程之道 - case语句的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!