verilog 中非阻塞赋值,for循环
非阻塞赋值的例子:新赋值不会影响当前always中执行的语句,因为其综合成寄存器,有效输入是时钟上升沿到达前的数据。
reg c,b; clk) begin b <= a; c <= b; end
非阻塞赋值语句简述为:在一个always 块中,语句是并行执行的
module nonblockingassignment (clk ,q1,q2); input clk; output [2:0] q1,q2; reg[2:0] q1,q2; always @ (posedge clk) begin q1<=q1+3b1; 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 2b00 : c = a; 4 2b01 : 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] <= 1bz; end
上面的语句就是相当于8个选择器
assign data_out[0] = data_in[0]?1:1bz;
``````
assign data_out[7] = data_in[7]?1:1bz;
因为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。