Verilog设计10项注意
1、不以if-else作为条件的区分
//不推荐的方式
Always@(posedge clk or negedge nrst)
If(condition1) sig1<=data;
If(~nrst) sig1<=0;
//推荐的方式
Always@(posedge clk or negedge nrst)
If(~nrst) sig1<=0;
Else if(condition1) sig1<=data;
2、
同时进行上升沿和下降沿的混合设计
Always@(posedge clk)
If(condition1) sig1<=data;
Always@(negede clk)
If(condition2) sig2<=data;
除非特殊情况(如DDR),一个设计中避免混合使用上升沿和下降沿触发,不利于时钟树综合,对自动测试向量产生也会有不利的影响。
3、
多multipledrivers,一个信号进行多个驱动
Always@(posedge clk1)
If(condition1) sig1<=data;
Always@(negede clk2)
If(condition2) sig2<=data;
一般设计中用到的触发器只有一个时钟,除非在工艺中有专门的器件,并且在设计中进行专门的指定,否则这种设计在综合的时候是通不过的。
4、
case语句里遗漏default的描述,这种情随盆况下一般会综合出锁存器。
//bad
Always(sel,a)
Case
2’b00:out=a;
2’b01:out=b;
2’b10:out=c;
Endcase
//good
Always(sel,a)
Case
2’b00:out=a;
2’b01:out=b;
2’b10:out=c;
Default:out=0;
Endcase
5、
绝对避免多重驱动
always@(posedge clk)
if (condition1) sig<=0;
always@(posedge clk)
if(condition2) sig<=1;
wire sig=condition1?A:0;
wire sig=condition2?B:0;
如果condition1和condition2同时成立的话,那么sig的值到底为多少呢,因而多重驱动在设计中必须要避免。
6、
混合同步与异步的reset语句,这种情况也不利于时序的分析
触发器的异步输入应该只有reset信号,不应合并其他同步信号,有些FPGA综合工具不允许酱材这样的语法。
//bad
Reg[3:0] cnt;
Always(posedge clk or negedge nrst)
If (~nrst) cnt<=0;
Else cnt<=cnt+1;
Wire syn_rst=(cnt>=10);
Always(posedge clk or negedge nrst)
If(~nrst | syn_rst)
Out<=0;
Else
Out<=in;
//good
Reg[3:0] cnt;
Always(posedge clk or negedge nrst)
If (~nrst) cnt<=0;
Else cnt<=cnt+1;
Wire syn_rst=(cnt>=10);
Always(posedge clk or negedge nrst)
If(~nrst)
Out<=0;
Else if (syn_rst)
Out<=0;
else
Out<=in;
7、
模块之间使用双向信号
双向信号会使用到三态缓冲器,这种缓冲器一般只在chip-level才会使用,在chip内部使用Tristate的缺点如下:
Tristate logic存驾裕帽在信号碰撞的风险(bus contention),目前为止,没有攻击能帮助我们解决这个问题,内部控制使能逻辑也难保证不产生错误,Tristate logic是完全不必要的,因而可以用两组信号进行取代。
当Tristate皆不被输入或者输出使能时,此时bus上会呈现floating的状态,这将导致巨大的功耗。
增加静态时序分析、DFT与布线的困难程度。
8、
状态机要有复位
没有初始状态的程序状态机,这样的程序状态机遗漏了reset描述,当系统开机时,无法确定进入哪个状态,有可能进入非预期的状态。

9、
最好用always@(*),敏感列表要完整
//bad
Reg a,b,c;
always@(a or b)
out=a & (b | c);
敏感列表不完整会导致前后仿不同。
10、
对组合逻辑进行了复位操作
//bad
Reg a,b,c;
always@(*)
if(~nrst)
out=0;
else
out=a & (b | c);
//good,应该使用时序进行打拍子处理
Always(posedge clk or negedge nrst)
If (~nrst)
Begin
a<=0;
b<=0;
c<=0;
end
else
begi
…
End
always@(*)
out=a & (b | c);