Verilog第四章

Verilog 过程结构

关键词:initial,always

  • 过程结构语句有 2 种,initial 与 always 语句。它们是行为级建模的 2 种基本语句。
    一个模块中可以包含多个 initial 和 always 语句,但 2 种语句不能嵌套使用。
    这些语句在模块间并行执行,与其在模块的前后顺序没有关系。
    但是 initial 语句或 always 语句内部可以理解为是顺序执行的(非阻塞赋值除外)。
    每个 initial 语句或 always 语句都会产生一个独立的控制流,执行时间都是从 0 时刻开始。

initial 语句

  • initial 语句从 0 时刻开始执行,只执行一次,多个 initial 块之间是相互独立的。
  • 如果 initial 块内包含多个语句,需要使用关键字 begin 和 end 组成一个块语句。
  • 如果 initial 块内只要一条语句,关键字 begin 和 end 可使用也可不使用。
  • initial 理论上来讲是不可综合的,多用于初始化、信号检测等

always 语句

  • 与 initial 语句相反,always 语句是重复执行的。always 语句块从 0 时刻开始执行其中的行为语句;当执行完最后一条语句后,便再次执行语句块中的第一条语句,如此循环反复。
  • 由于循环执行的特点,always 语句多用于仿真时钟的产生,信号行为的检测等

下面用 always 产生一个 100MHz 时钟源,并在 1010ns 时停止仿真代码如下:

`timescale 1ns/1ns
 
module test ;
 
    parameter CLK_FREQ   = 100 ; //100MHz
    parameter CLK_CYCLE  = 1e9 / (CLK_FREQ * 1e6) ;   //switch to ns
 
    reg  clk ;
    initial      clk = 1'b0 ;      //clk is initialized to "0"
    always     # (CLK_CYCLE/2) clk = ~clk ;       //generating a real clock by reversing
 
    always begin
        #10;
        if ($time >= 1000) begin
            $finish ;
        end
    end

endmodule

仿真结果:
可见,时钟周期是我们想要得到的 100MHz。而且仿真在 1010ns 时停止。
在这里插入图片描述

Verilog 过程赋值

关键词:阻塞赋值,非阻塞赋值,并行

  • 过程性赋值是在 initial 或 always 语句块里的赋值,赋值对象是寄存器、整数、实数等类型。
  • 这些变量在被赋值后,其值将保持不变,直到重新被赋予新值。
  • 连续性赋值总是处于激活状态,任何操作数的改变都会影响表达式的结果;过程赋值只有在语句执行的时候,才会起作用。这是连续性赋值与过程性赋值的区别。

Verilog 过程赋值包括 2 种语句:阻塞赋值与非阻塞赋值。

阻塞赋值

阻塞赋值属于顺序执行,即下一条语句执行前,当前语句一定会执行完毕。
阻塞赋值语句使用等号 = 作为赋值符。
前面的仿真中,initial 里面的赋值语句都是用的阻塞赋值。

非阻塞赋值

非阻塞赋值属于并行执行语句,即下一条语句的执行和当前语句的执行是同时进行的,它不会阻塞位于同一个语句块中后面语句的执行。
非阻塞赋值语句使用小于等于号 <= 作为赋值符。

利用下面代码,对阻塞、非阻塞赋值进行仿真,来说明 2 种过程赋值的区别。

`timescale 1ns/1ns
 
module test ;
    reg [3:0]   ai, bi ;
    reg [3:0]   ai2, bi2 ;
    reg [3:0]   value_blk ;
    reg [3:0]   value_non ;
    reg [3:0]   value_non2 ;
 
    initial begin
        ai            = 4'd1 ;   //(1)
        bi            = 4'd2 ;   //(2)
        ai2           = 4'd7 ;   //(3)
        bi2           = 4'd8 ;   //(4)
        #20 ;                    //(5)
 
        //non-block-assigment with block-assignment
        ai            = 4'd3 ;     //(6)
        bi            = 4'd4 ;     //(7)
        value_blk     = ai + bi ;  //(8)
        value_non     <= ai + bi ; //(9)
 
        //non-block-assigment itself
        ai2           <= 4'd5 ;           //(10)
        bi2           <= 4'd6 ;           //(11)
        value_non2    <= ai2 + bi2 ;      //(12)
    end
 
   //stop the simulation
    always begin
        #10 ;
        if ($time >= 1000) $finish ;
    end
 
endmodule

仿真结果如下:
语句(1)-(8)都是阻塞赋值,按照顺序执行。
20ns 之前,信号 ai,bi 值改变。由于过程赋值的特点,value_blk = ai + bi 并没有执行到,所以 20ns 之前,value_blk 值为 X(不确定状态)。
20ns 之后,信号 ai,bi 值再次改变。执行到 value_blk = ai + bi,信号 value_blk 利用信号 ai,bi 的新值得到计算结果 7。
语句(9)-(12)都是非阻塞赋值,并行执行。
首先,(9)-(12)虽然都是并发执行,但是执行顺序也是在(8)之后,所以信号 value_non = ai + bi 计算是也会使用信号 ai,bi 的新值,结果为 7。
其次,(10)-(12)是并发执行,所以 value_non2 = ai2 + bi2 计算时,并不关心信号 ai2,bi2 的最新非阻塞赋值结果。即 value_non2 计算时使用的是信号 ai2,bi2 的旧值,结果为 4’hF。

使用非阻塞赋值避免竞争冒险

实际 Verilog 代码设计时,切记不要在一个过程结构中混合使用阻塞赋值与非阻塞赋值。两种赋值方式混用时,时序不容易控制,很容易得到意外的结果。
更多时候,在设计电路时,always 时序逻辑块中多用非阻塞赋值&#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值