verilog编程注意事项(阻塞/复位/异步/编码规范/常见错误)

来源:互联网 发布:攻城掠地神兵220数据 编辑:程序博客网 时间:2024/06/16 10:49
一、异步逻辑同步化处理,方法有:
1.采用握手信号进行同步
2.采用打2拍的方法进行同步处理
3.采用FIFO进行同步处理

二、阻塞式赋值和非阻塞式赋值的使用
1.在产生组合逻辑的always块中使用阻塞式赋值
2.在产生时序逻辑的always块中使用非阻塞式赋值
3.在普通的组合逻辑中,如assign语句中个,使用阻塞式赋值
4.在不清楚使用阻塞还是非阻塞的时候,采用非阻塞式赋值

阻塞式赋值:
阻塞赋值的操作符就是一个等号=,阻塞这个名称的由来因为阻塞的赋值必须求右运算符的值,并且在完成赋值之前不能被其他Verilog语句打断。这样的赋值语句在完成前一直”阻塞“其他赋值语句。

非阻塞式赋值:
1.非阻塞式赋值<=。在非阻塞赋值语句中,右运算符的值在时间步开始的时候计算,但是左运算符的更新却是发生在时间步的结束。在计算右运算符的值和更新左运算符表达式值之间,其他的Verilog语句也可以执行,非阻塞赋值不阻塞任何其他的Verilog语句。
2.非阻塞赋值语句的执行可以看做这样两步:1)在时间步开始时计算右运算符的值;2)在时间步结束时更新左运算符的值
3.非阻塞赋值语句只能用于register数据类型,因而只能出现在过程块中,不如”initial“或者”always“

三、异步复位与同步复位
asynchronous异步复位:
1.代码
always @(posedge clk or negedge reset)
  if(~reset)  q <= 1'b0;
  else  q  <= data;
2.优点:
a、大多数目标器件库的dff都有异步复位端口,不带组合逻辑电路,因此采用异步复位可以节省资源。
b、设计相对简单。
c、异步复位信号识别方便,而且可以很方便的使用FPGA的全局复位端口GSR(如果不是FPGA的全局复位端口,并且复位信号上没有上拉电阻,容易受到干扰而产生毛刺,这对异步复位时相当有害的)。
3.缺点:
a、在复位信号释放(release)的时候容易出现问题。具体就是说:倘若复位释放时恰恰在时钟有效沿附近,就很容易使寄存器输出出现亚稳态,从而导致亚稳态(在不同的always块中,不能保证每个always块被同时[恢复]复位,从而不能保证每个always块同时进入工作状态)。
b、复位信号容易受到毛刺的影响。
  
synchronous同步复位:  
1.代码
always @(posedge clk)
  if(~reset)  q = 1'b0;
  else  q = data;
2.优点:
a、有利于仿真器的仿真。
b、可以使所设计的系统成为100%的同步时序电路,这便大大有利于时序分析,而且综合出来的fmax一般较高。
c、因为他只有在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的毛刺.
3.缺点:
a、复位信号的有效时长必须大于时钟周期(否则的话有概率正好在2个上升沿之间而不被always块执行),才能真正被系统识别并完成复位任务。同时还要考虑,诸如:clk skew,组合逻辑路径延时,复位延时等因素。
b、由于大多数的逻辑器件的目标库内的DFF都只有异步复位端口,所以,倘若采用同步复位的话,综合器就会在寄存器的数据输入端口插入组合逻辑,这样就会耗费较多的逻辑资源。
  
异步复位同步释放
所谓异步复位和同步释放,是指复位信号是异步有效的,即复位的发生与clk无关。后半句“同步释放”是指复位信号的撤除(释放)则与clk相关,即同步的。

异步复位:显而易见,rst_async_n异步复位后,rst_sync_n将拉低,即实现异步复位。

同步释放:这个是关键,看如何实现同步释放,即当复位信号rst_async_n撤除时,由于双缓冲电路的作用,rst_sync_n复位信号不会随着rst_async_n的撤除而撤除。

1.实现代码:
reg rst_s1, rst_s2;  
always @ (posedge clk, posedge rst_async_n)  
  if (rst_async_n) begin   
    rst_s1 <= 1'b0;  
    rst_s2 <= 1'b0;  
  end  
  else begin  
    rst_s1 <= 1'b1;  
    rst_s2 <= rst_s1;  
  end  
  
assign rst_sync_n = rst_s2;  
其中rst_s2为二级D触发器,为rst_async_n打一个节拍

四、编码规范:
1.在程序内部,赋值中不要出现'bx,'bz等,对于三态输出,可以在最后一级通过assign语句实现。
2.敏感列表全部用always @(*)表示
3.注意寄存器的初始值,一般需要通过复位信号将其归为。

五、常见错误
1.妄图修改敏感列表或赋值方式,得到不同的综合结果。
2.敏感列表不全或者赋值方式的不正确,只是会影响综合结果和仿真结果不一致,并不会对综合结果产生影响。
3.出现锁存器,锁存器主要是在没有列全的if/else,case语句中出现。锁存器的危害是其让综合器对时序估算会出问题,以及组合逻辑的缺点其也有(延迟、竞争等)




  
0 0