集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1167|回复: 2

Verilog中阻塞和非阻塞赋值原则

[复制链接]
d643189658 发表于 2017-8-11 16:18:15 | 显示全部楼层 |阅读模式
Verilog中阻塞和非阻塞赋值原则
2017-02-01 模电数电
阻塞赋值

阻塞赋值操作符 =
阻塞赋值是指当前的赋值语句阻断了其后的语句,也就是说后面的语句必须等到当前的赋值语句执行完毕才能执行。阻塞赋值可以看成是一步完成的,即计算等号右边的值并同时赋给左边变量。

例如:采用阻塞赋值实现四选一多路选择器。
module mux4_to_1 (out, i0, i1, i2, i3, s0, s1);
    output out;
    input i0,i1,i2,i3,s0,s1;
    reg out;

    always @(s1 or s0 or i0 or i1 or i2 or i3)
    begin
        case ( {s1, s0} )
            2'b00: out = i0;
            2'b01: out = i1;
            2'b10: out = i2;
            2'b11: out = i3;
            default: out = 1'bx;
        endcase   
    end
endmodule

非阻塞赋值

非阻塞赋值操作符 <=
非阻塞赋值是指在过程块中,当前的赋值语句不会阻断其后的语句。非阻塞赋值操作只能用于对寄存器型变量进行赋值,因此只能用在"initial"块和"always"块等过程块中。非阻塞赋值不允许用于连续赋值。

例如:采用非阻塞赋值实现移位寄存器。
module mux4_to_1 (q3, d, clk);
    output [7:0] q3;
    input [7:0] d;
    input clk;
    reg [7:0] q3, q2, q1;

    always @(posedge or clk)
    begin
        q1 <= d;
        q2 <= q1;
        q3 <= q2;
    end
endmodule

简单理解就是,阻塞赋值是按需执行,非阻塞赋值是并行执行。

在编写Verilog代码时,要牢记:
时序电路建模时,用非阻塞赋值。
锁存器电路建模时,用非阻塞赋值。
用always块建立组合逻辑模型时,用阻塞赋值。
在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
在同一个always块中不要既用阻塞又用非阻塞赋值。
不要在一个以上的always块中为同一个变量赋值。
用$strobe系统任务来显示用非阻塞赋值的变量值。
在赋值时,不要使用#0延迟。


应用举例

用always块描述组合逻辑时,应采用阻塞赋值语句。例如,用阻塞赋值实现四输入与或非门。
module ex4_to_1 (y, a, b, c, d);
    output y;
    input a, b, c, d;
    reg y, tmp1, tmp2;

    always @(a or b or c or d)
    begin
        tmp1 = a & b;
        tmp2 = c & d;
        y = tmp1 | tmp2
    end
endmodule


当把组合逻辑和时序逻辑写入到同一个always块中时,应遵从时序逻辑建模原则,使用非阻塞赋值。例如,实现一个具有异步复位功能的触发器,该触发器利用时钟上升沿触发,输出q等于输入a、b的异或。
module nbex2 (q, a, b, clk, rst_n);
    output q;
    input a, b, clk, rst_n;
    reg q;

    always @(posedge clk  or  negedge rst_n)
        if ( !rst_n ) q <= 1'b0;    //时序逻辑
        else           q <= a^b;     //异或,组合逻辑
endmodule

也可以将组合和时序逻辑分写在两个always块中,不要在同一个always块中同时使用阻塞和非阻塞赋值。
module nbex2 (q, a, b, clk, rst_n);
    output q;
    input a, b, clk, rst_n;
    reg q, y;

    always @(a  or  b)
        y = a^b;
    always @(posedge clk  or  negedge rst_n)
        if ( !rst_n ) q <= 1'b0;
        else           q <= y;
endmodule

在一个以上的always块中对同一个变量进行多次赋值可能会导致竞争冒险,即使采用非阻塞赋值也可能会产生竞争冒险。


用Verilog HDL描述加法器电路很简单,综合器可以根据用户的配置自动综合成相应的加法器,比如配置成超前进位的并行加法器。四位加法器的行为描述方式如下:
module add_4 (cout, sum, a, b, cin);
    output cout;
    output [3:0]  sum;
    input [3:0]  a,b;
    input cin;

    assign {cout, sum} = a + b + cin;
endmodule


用Verilog HDL描述八位乘法器
module mult_8 (X, Y, Product);
    input [7:0]  X, Y;
    output [15:0]  Product;

    assign Product = X * Y;
endmodule

您也可以自己具体描述乘法器的实现方式:
    parameter size = 8, longsize = 16;
    reg [size:1]  opa, opb;
    reg [longsize:1]  result;

    begin: mult
         integer bindex;
         result = 0;
         for (bindex=1; bindex<=size; bindex=bindex+1)
             if (opb[bindex])
                 result = result + (opa<<(bindex-1));
    end


3-8译码器设计实例(无使能控制端)
module decoder (out, in);
    output [7:0]  out;
    input [2:0]  in;

    assign out = 1'b1<<in;
endmodule


简单的比较器设计实例
module compare (equal, a, b);
    parameter size = 1;
    output  equal;
    input [size-1:0]  a, b;

    assign equal = (a==b)? 1 : 0;
endmodule


多路选择器设计实例
module mux2 (out, a, b, sel);
    output  out;
    input  a, b,sel;
    reg out;

    always @( a or b or sel )
     begin
         case (sel)
             1'b0: out = a;
             1'b1: out = b;
             default: out = 'bx;
          endcase
      end   
endmodule


奇偶校验位生成器设计实例
module parity (even_bit, odd_bit, input_bus);
    output  even_bit, odd_bit;
    input [7:0]  input_bus;

    assign odd_bit = ^input_bus;
    assign even_bit = ~odd_bit;
endmodule


三态输出驱动器设计实例
module trist1 (out, in, enable);
    output  out;
    input in, enable;

    assign out = enable? in : 'bz;
endmodule

三态双向驱动器设计实例
module bidir (tri_inout, out, in, enable, b);
    inout  tri_inout;
    output  out;
    input in, enable, b;

    assign tri_inout = enable? in : 'bz;
    assign out = tri_inout ^ b;
endmodule


触发器设计实例
module dff (q, data, clk);
    output  q;
    input  data, clk;
    reg q;

    always @( posedge clk )
         begin
             q <= data;
          end   
endmodule

电平敏感型锁存器设计实例
module latch1 (q, data, clk);
    output  q;
    input  data, clk;
    assign q = clk ? data : q;
endmodule

带置位和复位端的电平敏感型锁存器设计实例
module latch2 (q, data, clk, set, reset);
    output  q;
    input  data, clk, set, reset;
    assign q = reset? 0 : (set? 1 : (clk ? data : q ));
endmodule


移位寄存器设计实例
module shifter ( din, clk, clr, dout );
    input  din, clk, clr;
    output [7:0] dout;
    reg [7:0] dout;

    always @( posedge clk )
         begin
             if (clr) dout <= 8'b0;
             else
                 begin
                     dout <= dout << 1;
                     dout[0] <= din;
                 end
          end   
endmodule


8位计数器设计实例
module counter1 ( out, cout, data, load, cin, clk );
    output [7:0] out;
    output cout;
    input [7:0] data;
    input load, cin, clk;
              reg [7:0] out;

    always @( posedge clk )
         begin
             if (load)
                 out <= data;
             else
                  out <= out + cin;
          end
    assign cout = (&out) & cin;
endmodule


Verilog HDL 三段式状态机模版

在用Verilog编写状态机时,建议分为三个alwaysk块完成。
三段式描述风格虽然代码结构复杂了一些,但这样做容易发现问题和改正模块编写中出现的问题。

//第一个always块,描述在时钟驱动下次态迁移到现态。
always @ (posedge clk or negedge rst_n)  //异步复位
if (!rst_n)
current_state<= IDLE;
else
current_state<= next_state; //注意,使用非阻塞赋值

//第二个always块,描述状态的转移关系
always @ (current_state)   //电平触发,将现态作为敏感信号
begin
    case (current_state)
S1: next_state = S2;  //阻塞赋值
       S2: next_state = S3;  //阻塞赋值
       ……
       default: next_state = ‘bx; //对多余状态的处理
    endcase
end

//第三个always块,描述每个状态对应的输出
always @ (current_state)
begin
     ...
    case (current_state)
S1: out1 = 1'b1; //对输出进行赋值
S2: out2 = 1'b1;
        ……
default: ...       // 避免综合出锁存器。
    endcase
end

这种风格的描述比较适合大型的状态机,查错和修改也比较容易,很多公司的综合器都建议使用这种风格来描述状态机,俗话说,学好数电,风光无限。
 楼主| d643189658 发表于 2017-8-11 22:32:08 | 显示全部楼层
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-4-20 12:42 , Processed in 0.060210 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表