Verilog代码规范(五) -- if & case语句

代码规范(五)

这篇是代码规范最后一篇,主要讲讲if语句和case语句在代码规范中的一些注意点。请酌情食用~


一、if语句

1. if语句优先级由上而下,越靠近下面的输入在综合时越靠近输出:(不允许if并列写法)

Example

always @(*)
	begin
		if(sel_A) Data_out = Data_A;
		if(sel_B) Data_out = Data_B;
		if(sel_C) Data_out = Data_C;
  end

注:不推荐上述写法是因为没有else容易产生latch。同时,如果条件并非互斥,则可能会有意想不到的结果;

上述写法可以修改为如下可以避免latch:(Lint Latch Rules W18)

always @(*)
	begin
		Data_out = 1'b0;
		if(sel_A) Data_out = Data_A;
		if(sel_B) Data_out = Data_B;
		if(sel_C) Data_out = Data_C;
  end

2. if...else...if语句优先级由上向下,越靠近上面额度输入在综合时越靠近输出:(推荐写法)

Example

always @(*)
	begin
		if(sel_A) 
			Data_out = Data_A;
		else if(sel_B) 
			Data_out = Data_B;
		else 
			Data_out = Data_C;
  end

3. 条件语句中不要放置组合逻辑

Example

Example 1:
if (A && (B | C))  #not recommended 

Example 2:
assign D = A && (B | C); #recommended
if (D)

注:推荐的写法有利于进行验证波形分析;否则你得在工具中将这些组合逻辑使用公式产生对应的波形结果;

      代码修改和阅读更方便;

总结:列全if...else...避免产生latch;条件语句不宜复杂;

 

二、case语句

1. 加default值可预防latch产生

(1) case的条件必须列全(full case),如果不能列全就写default值,否则会产生latch。相关SPYGLASS错误:

always @(*)
begin
	case(select)
		sel_A: D_out = A;
		sel_B: D_out = B;
		sel_C: D_out = C;
		defalut: D_out = D;
	endcase
end

(2) 如果case结构中的selector的位宽会随着design变化,那么即便是当前case条件是完备的,那么也可能变得不完备,因此需要加入default;

总结:强烈建议写代码时一定要用default语句!

2. case和if嵌套,也容易产生latch

(1) 不完整的if嵌套会产生latch

always @(*)
begin
	case(valid)
		2'b00: begin if(flag) valid_data = data[0]; end
		2'b01: begin if(flag) valid_data = data[1]; end
		2'b10: begin if(flag) valid_data = data[2]; end
		2'b11: begin if(flag) valid_data = data[3]; end
		defalut: valid_data = 1'b0; 
	endcase
end

(2) 写全if...else...可以去除latch 

always @(*)
begin
	case(valid)
		2'b00: begin if(flag) valid_data = data[0]; 
									else valid_data = 1'b0;
					 end
		2'b01: begin if(flag) valid_data = data[1]; 
									else valid_data = 1'b0;
					 end
		2'b10: begin if(flag) valid_data = data[2]; 
									else valid_data = 1'b0;
					 end
		2'b11: begin if(flag) valid_data = data[3]; 
									else valid_data = 1'b0;
					 end
		defalut: valid_data = 1'b0; 
	endcase
end

(3) 在前面给一个初始赋值可以消除latch 

always @(*)
begin
	valid_data = 1'b0;
	case(valid)
		2'b00: begin if(flag) valid_data = data[0]; end
		2'b01: begin if(flag) valid_data = data[1]; end
		2'b10: begin if(flag) valid_data = data[2]; end
		2'b11: begin if(flag) valid_data = data[3]; end
		defalut: valid_data = 1'b0; 
	endcase
end

总结:case嵌套if...else...和if...else一样,不完整的if...else...会导致latch,注意列全或者在前面进行一次设置初始值;否则即便有default值也没有用;

3. 有多信号赋值时,需对所有条件下的所有信号进行描述。

(1) 如下有些case中缺少对某些输出的描述,会产生latch;

always @(*)
begin
	valid_data = 1'b0;
	case(valid)
		2'b00: begin valid_data1 = data[0]; valid_data2 = data[0]; valid_data3 = data[0]; end
		2'b01: begin valid_data1 = data[1]; valid_data3 = data[1]; end                          #没有data2的描述
		2'b10: begin valid_data1 = data[2]; valid_data2 = data[2]; end                          #没有data3的描述
		2'b11: begin valid_data1 = data[3]; end                                                 #没有data2和data3的描述
		defalut: valid_data1 = 1'b0; 
	endcase
end

 (2) 如果描述完全则不会产生latch;

always @(*)
begin
	valid_data = 1'b0;
	case(valid)
		2'b00: begin valid_data1 = data[0]; valid_data2 = data[0]; valid_data3 = data[0]; end
		2'b01: begin valid_data1 = data[1]; valid_data2 = data[1]; valid_data3 = data[1]; end
		2'b10: begin valid_data1 = data[2]; valid_data2 = data[2]; valid_data3 = data[2]; end
		2'b11: begin valid_data1 = data[3]; valid_data2 = data[3]; valid_data3 = data[3]; end
		defalut: valid_data1 = 1'b0; 
	endcase
end

总结:在一个if...else语句中或case语句中,最好只对一个变量进行赋值,可以大大降低产生latch的风险;

 

4. case中只可以使用case和casez,不能使用casex

三、其他

1. 组合逻辑的输出不可以用double flop进行同步。

原因就是组合逻辑的输出可能会有毛刺,这些毛刺会增大第一级flop产生metastable的概率,

进而影响整个synchronizer的MTBF,更严重的问题是由于第一级flop可能稳定在和输入adata不同的值,会导致bdata出现一个不该出现的值。

所以对于任何单bit信号,在跨时钟域之前一定要先寄存(flop),只有flop的输出才能经过下面的图就是不flop的情形。

 

2. 不依赖Verilog默认的优先级,每个运算都加括号。

 

 

  • 7
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: Verilog代码规范包括以下几个方面。首先,推荐使用Verilog 2001语法格式,而不是Verilog 95。\[1\]其次,在一个always块中只产生一个信号,并且一个信号只能在一个always块中赋值。\[2\]条件判断应该只使用if-else/if-else if-else和case语句。\[2\]敏感列表中含有posedge或negedge的一定是时序逻辑。\[2\]在设计时,如果想立即有结果,应使用组合逻辑;如果想要延时一拍再输出,应使用时序逻辑。\[2\]always块中的信号应该用reg定义,非always块中的信号应该用wire定义。\[2\]时序逻辑应使用非阻塞(<=)赋值,组合逻辑应使用阻塞(=)赋值。\[2\]最后,添加注释可以增加代码的可读性和易于维护。注释应该清晰、简洁,使用"//",并对齐。\[3\] #### 引用[.reference_title] - *1* *3* [Verilog 编程规范](https://blog.csdn.net/yishuihanq/article/details/131287810)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [verilog基础语法及规范](https://blog.csdn.net/LTLOVELN/article/details/125898274)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值