Verilog语法回顾--case语句

目录

特性:

case语句定义:

case语句的执行:

case的应用:

casez的应用:

描述状态机:

casex的误用:

casez的误用:

full_case:

parallel_case:

case语句的编码原则:


参考《Verilog 编程艺术》魏家明著

用于检查一个表达式是否与多个其他的表达式匹配,如果发现匹配,就做对应的跳转。

特性:

1.除了case,还支持casex和casez变种。

2.case_expression和case_item可以多种组合,变量/常数,常数/变量,变量/变量

3.既可以实现parrallel,也可以实现优先级编码

4.支持反向case,就是让case_expression是常量

5.如果使用时不仔细,就可能生成latch

6.仿真器和综合工具对x和z理解不同,容易导致前后仿真不一致

case语句定义:

包含在case和endcase之间的代码(也包括casex和casez)

case (case_expression)
    case_item : case_item_expression1;
    case_item : case_item_expression2;
    ..
    default   : case_item_expression;
endcase

casez语句是case语句的一个变种。casez语句允许“z”和“?”值在比较时被当作不关心的值。如果“z”和“?”在case_expression和case_item中,那么就不关心对应的位。“z”和“?”的等价的。注意:当编写可综合的代码时,要小心使用casez;使用casez时,最好使用?表示不关心

casex语句是case语句的一个变种。casex语句允许“x”和“z”和“?”值在比较时被当作不关心的值。注意:在编写可综合代码时不要使用casex。

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语句

在做case比较时,只有当每bit都是精确匹配的(0,1,z,x)比较才算成功。所有表达式的位长应该相等,这样才能精确的匹配。case提供精确匹配就是为了提供一种能够检测出x和z的机制。但是casez和casex这两个变种提供了比较时不关心x,z的机制。

case的应用:

例子:这段说明case可以检查x和z

case (sig)
	1'bz : $display("signal is floating");
	1'bx : $disolay("signal is unknwon");
	default : $display("signal is %b", sig);
endcase

例子:case_item中有x和z,不可综合

case (select[2:1])
	2'b00 : result = 0;
	2'b01 : result = flaga;
	2'b0x, 2'b0z : result = flaga ? 'bx : 0;
	2'b10 : result = flagb;
	2'bx0, 2'bz0 : result = flagb ? 'bx : 0;
	default : result = 'bx;
endcase

casez的应用:

例子:优先级编码器

reg [7:0] ir;
casez (ir)
	8'b1??????? : instruction1(ir);
	8'b01?????? : instruction2(ir);
	8'b00010??? : instruction3(ir);
	8'b000001?? : instruction4(ir);
endcase

描述状态机:

module mealy (
	input in1, in2, clk, reset,
	output out
);
	reg current_state, next_state, out;
	always @(*) begin
		next_state = current_state;
		case (current_state)
			0 : begin
				if (in1)
					next_state = 1;
				out = 1'b0;
			end
			1 : if (in1) begin
				next_state = 1'b0;
				out = in2;
			end
			else begin
				next_state = 1'b1;
				out = !in2;
			end
		endcase
	end
	always @(posedge clk or negedge reset) begin
		if (!reset)
			current_state = 0;
		else
			current_state = next_state;
	end
endmodule

casex的误用:

当case_expression中出现了x时,这时就会发生问题,因为前仿真在计算casex语句把x值的输入当作不关心,而后仿真在检查条件时会把x在门级模型中传播。

casez的误用:

当case_expression中出现了z时,这时就会发生问题,因为前仿真在计算casez语句把z值的输入当作不关心。

full_case:

是指每个可能的case_expression的取值都有case_itemcase_default与之相匹配。即使case语句没有包含default,如果每个case_expression能够找到一个与之匹配的case_item,那么还是full_case.

例子:不是full的case

对于下面的3to1multiplexer,当sel=2'b11时,没有对应的y输出赋值。仿真时,当sel=2'b11,时y就表现为一个latch

module mux3a (y, a, b, c, sel);
	output y;
	input [1:0] sel;
	input a, b, c;
	reg y;
	always @(*) begin
		case (sel)
			2'b00 : y = a;
			2'b01 : y = b;
			2'b10 : y = c;
		endcase
	end
endmodule

例子:是full的case

使用case_default变为full,但可能出现前后仿真不一致

module mux3a (y, a, b, c, sel);
	output y;
	input [1:0] sel;
	input a, b, c;
	reg y;
	always @(*) begin
		case (sel)
			2'b00 : y = a;
			2'b01 : y = b;
			2'b10 : y = c;
			default : y = 1'bx;
		endcase
	end
endmodule

如果在case语句前给输出一个默认值,那么这也被当作full的case语句,不会生成latch

module mux3a (y, a, b, c, sel);
	output y;
	input [1:0] sel;
	input a, b, c;
	reg y;
	always @(*) begin
		y = 1'b0;
		case (sel)
			2'b00 : y = a;
			2'b01 : y = b;
			2'b10 : y = c;
		endcase
	end
endmodule

parallel_case:

是指case_expression只能匹配一个case_item语句,如果发现case_expression匹配超过1个的case_item,那么这些匹配的case_item被称为overlapping case item,这个case语句就不是parallel

例子:不是parallel的case

当irq=3'b011,3'b101,3'b110或1'b111,就会有多余1个case_item与irq匹配。这在仿真时就像一个优先级编码器,irq[2]的优先级大于irq[1],irq[1]的优先级大于irq[0]。

module intctlla (int2, int1, int0, irq);
	output int2, int1, int0, irq;
	input [2:0] irq;
	reg int2, int1, int0;
	always @(irq) begin
		{int2, int1, int0} = 3'b0;
		casez (irq)
			3'b1?? : int2 = 1'b1;
			3'b?1? : int1 = 1'b1;
			3'b??1 : int0 = 1'b1;
		endcase
	end
endmodule

例子:是parallel的case

每个case_item都是独立的。

module intctlla (int2, int1, int0, irq);
	output int2, int1, int0, irq;
	input [2:0] irq;
	reg int2, int1, int0;
	always @(irq) begin
		{int2, int1, int0} = 3'b0;
		casez (irq)
			3'b1?? : int2 = 1'b1;
			3'b01? : int1 = 1'b1;
			3'b001 : int0 = 1'b1;
		endcase
	end
endmodule

case语句的编码原则

1.对于编写表达式并行(像真值表一样)的设计,case语句是不错的选择,而且代码等价简洁清楚。

2.在设计可综合的代码时,要小心使用casez语句,不要使用casex

3.要小心使用反向case语句,最好只针对是parallel的case语句使用

4.要小心使用casez语句设计优先级编码器,也可以用if-else-if语句实现优先级编码器

5.使用casez语句时,用?表示不关心的位,最好不用z

6.最好为case语句添加case_default,而且不要把输出值赋值为x,当前也可以在case语句前面给所有的输出赋默认值

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值