当前位置:   article > 正文

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

verilog if语句

代码规范(五)

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


一、if语句

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

Example

  1. always @(*)
  2. begin
  3. if(sel_A) Data_out = Data_A;
  4. if(sel_B) Data_out = Data_B;
  5. if(sel_C) Data_out = Data_C;
  6. end

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

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

  1. always @(*)
  2. begin
  3. Data_out = 1'b0;
  4. if(sel_A) Data_out = Data_A;
  5. if(sel_B) Data_out = Data_B;
  6. if(sel_C) Data_out = Data_C;
  7. end

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

Example

  1. always @(*)
  2. begin
  3. if(sel_A)
  4. Data_out = Data_A;
  5. else if(sel_B)
  6. Data_out = Data_B;
  7. else
  8. Data_out = Data_C;
  9. end

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

Example

  1. Example 1:
  2. if (A && (B | C)) #not recommended
  3. Example 2:
  4. assign D = A && (B | C); #recommended
  5. if (D)

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

  1. 代码修改和阅读更方便;

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

 

二、case语句

1. 加default值可预防latch产生

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

  1. always @(*)
  2. begin
  3. case(select)
  4. sel_A: D_out = A;
  5. sel_B: D_out = B;
  6. sel_C: D_out = C;
  7. defalut: D_out = D;
  8. endcase
  9. end

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

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

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

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

  1. always @(*)
  2. begin
  3. case(valid)
  4. 2'b00: begin if(flag) valid_data = data[0]; end
  5. 2'b01: begin if(flag) valid_data = data[1]; end
  6. 2'b10: begin if(flag) valid_data = data[2]; end
  7. 2'b11: begin if(flag) valid_data = data[3]; end
  8. defalut: valid_data = 1'b0;
  9. endcase
  10. end

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

  1. always @(*)
  2. begin
  3. case(valid)
  4. 2'b00: begin if(flag) valid_data = data[0];
  5. else valid_data = 1'b0;
  6. end
  7. 2'b01: begin if(flag) valid_data = data[1];
  8. else valid_data = 1'b0;
  9. end
  10. 2'b10: begin if(flag) valid_data = data[2];
  11. else valid_data = 1'b0;
  12. end
  13. 2'b11: begin if(flag) valid_data = data[3];
  14. else valid_data = 1'b0;
  15. end
  16. defalut: valid_data = 1'b0;
  17. endcase
  18. end

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

  1. always @(*)
  2. begin
  3. valid_data = 1'b0;
  4. case(valid)
  5. 2'b00: begin if(flag) valid_data = data[0]; end
  6. 2'b01: begin if(flag) valid_data = data[1]; end
  7. 2'b10: begin if(flag) valid_data = data[2]; end
  8. 2'b11: begin if(flag) valid_data = data[3]; end
  9. defalut: valid_data = 1'b0;
  10. endcase
  11. end

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

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

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

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

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

  1. always @(*)
  2. begin
  3. valid_data = 1'b0;
  4. case(valid)
  5. 2'b00: begin valid_data1 = data[0]; valid_data2 = data[0]; valid_data3 = data[0]; end
  6. 2'b01: begin valid_data1 = data[1]; valid_data2 = data[1]; valid_data3 = data[1]; end
  7. 2'b10: begin valid_data1 = data[2]; valid_data2 = data[2]; valid_data3 = data[2]; end
  8. 2'b11: begin valid_data1 = data[3]; valid_data2 = data[3]; valid_data3 = data[3]; end
  9. defalut: valid_data1 = 1'b0;
  10. endcase
  11. 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默认的优先级,每个运算都加括号。

 

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号