verilog 中非阻塞赋值,for循环

本文介绍了Verilog中非阻塞赋值的概念,强调了其在时序逻辑描述中的应用,并提供了示例代码。同时,讨论了在always块中避免混合使用阻塞和非阻塞赋值的重要性,以及如何正确使用for循环来表示硬件行为。最后,提到了在for循环中的变量类型选择和其在always模块与generate模块中的差异。
AI助手已提取文章相关产品:

非阻塞赋值的例子:新赋值不会影响当前always中执行的语句,因为其综合成寄存器,有效输入是时钟上升沿到达前的数据。

reg c,b;

always@(posedge clk)

begin

b <= a;

c <= b;

end

aa


非阻塞赋值语句简述为:在一个always 块中,语句是并行执行的

module nonblockingassignment (clk ,q1,q2);
    input clk;
    output [2:0] q1,q2;
    reg[2:0] q1,q2;
    always @ (posedge clk)
    begin
    q1<=q1+3'b1;
    q2<=q1;
    end
    endmodule


寄存器是clk边沿触发,在clk边沿时更新寄存器输出,根据其时钟特性,在clk脉冲到来前,输入值就必须提前到达寄存器输入端。所以在新的clk时更新的输入值不可能影响到寄存器输出。这也就是always中的非阻塞赋值不会影响同一clk中其他的非阻塞赋值。

以下是使用阻塞和非阻塞赋值应遵循的一些基本原则,这些原则有利于防止竞态(race condition)的发生。

1)当用always块来描述组合逻辑(combinational logic)时,即不是由clk触发的应当使用阻塞赋值。

1 always@(sel or a or b) begin
2   case (sel)
3     2'b00 : c = a;
4     2'b01 : c = b;
5   endcase
6 end

(2)对于时序逻辑(sequential logic)的描述和建模,即由clk触发的应当使用非阻塞赋值。

reg c,b;
always@(posedge clk)
begin
b <= a;
c <= b;
end

(3)在同一个always模块中,不要混合使用阻塞赋值和非阻塞赋值,对同一变量既进行阻塞赋值,又进行非阻塞赋值,在综合时会出错。所以在由clk触发的always中全部使用非阻塞赋值,电平触发的always中使用阻塞赋值,把阻塞赋值和非阻塞赋值分在不同的always中书写。

(4)尽量不要再在多个不同的always块中对同一变量赋值。

(5)使用$strobe显示使用非阻塞赋值的变量。


verilog中的for循环和C语言中的for循环不一样,表示的是电路的硬件行为,循环几次,就是将相同的电路复制几次!

integer i; //be careful, i should be integer!

  for(i = 0;i <= 7 ;i = i+1)begin
   if(data_in[i])
    data_out[i] <= 1;
   else
    data_out[i] <= 1'bz; 
  end

上面的语句就是相当于8个选择器

assign data_out[0] =  data_in[0]?1:1'bz;

``````

assign data_out[7] = data_in[7]?1:1'bz;

因为for loop是复制电路行为,所以互相之间并行,可将其放在always中或者generate模块中。在两种模块中的i类型与赋值方式均不同,示例如下。

Example:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 08/14/2014 11:10:33 AM
// Design Name: 
// Module Name: top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module top(
  input clk,
  input[7:0] data,
  output reg[7:0] q //for always,reg q
  //output [7:0] q //for generate,net q

    );
    
    integer i;     //always format                                             
    always@(posedge clk)     begin       
        for(i=0;i<8;i=i+1)begin
            q[i]<=data[i];                              
        end    
     end         
    
  /*  genvar i; //generate format 
    generate
        for(i=0;i<8;i=i+1)begin
        assign    q[i]=data[i];                              
        end    
     endgenerate*/
    
endmodule                               


由RTL图可知,生成了八个register。

对于loop中的 integer i: integer类型一般只是用于loop,其他时候基本不用此类型,其默认是32bit。


您可能感兴趣的与本文相关内容

### Verilog 中非阻塞赋值的常用语法 在 Verilog 设计中,对于时序逻辑部分推荐使用非阻塞赋值 `<=`。这种赋值方式允许信号更新在同一时间点内并行完成,从而更贴近实际硬件行为。 #### 非阻塞赋值的特点 - 并行执行,在同一仿真时刻所有非阻塞赋值会同时发生。 - 主要应用于时钟边沿触发的情况,比如寄存器操作。 - 使用场景通常是 `always @(posedge clk)` 或者类似的敏感列表中[^2]。 #### 语法结构 ```verilog always @(posedge clk or negedge rst_n) begin if (!rst_n) reg_signal <= 0; else reg_signal <= next_value; end ``` 这段代码展示了如何在一个上升沿触发的时钟域里利用非阻塞赋值来实现状态机转换或数据存储功能。当复位有效(`!rst_n`)时,将寄存器清零;否则,在下一个时钟周期到来之际赋予新的计算结果给目标寄存器变量。 #### 实际应用案例 下面是一个简单的四位二进制计算器的例子: ```verilog module counter ( input wire clk, input wire reset, output reg [3:0] count ); // Using non-blocking assignment within a clocked process always @(posedge clk or posedge reset) begin if (reset) count <= 4'b0000; // Reset to zero on active high reset signal else count <= count + 1; // Increment the counter value at each rising edge of clk end endmodule ``` 此模块定义了一个基于正沿触发的四比特加法计数器,每当接收到一次时钟脉冲就增加其内部数值直到溢出循环回初始态。这里采用的是非阻塞形式来进行状态维护,确保每次变化都在同一个模拟瞬间同步完成。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值