繁体   English   中英

Verilog中的初始块执行顺序

[英]initial block execution order in verilog

我已经制作了一个计数器模块,但似乎无法掌握计数器模块和testbench模块的初始块的执行顺序。

据我所知,我认为在verilog中, 始终会首先执行初始块。

在这种情况下,我将执行测试台模块和我假定initialtestbench_counter将被首先执行。

接下来,我认为将执行计数器模块C并将x_in值更新为temp ,而无需模块C #1延迟。

但是如果没有#1 ,或者没有将initial更改为always@(x_in)我会看到redline

所以问题是

  1. initial计数器模块块C被连之前首先执行initial为测试平台块?

  2. 如果我使用always@(x_in)为什么能正常工作?

提前致谢。

柜台代码

`timescale 1ns/1ns
module counter(x_in,clk,y_out);
    input [31:0] x_in;
    input clk;
    output [31:0] y_out;
    reg [31:0] y_out;
    reg [31:0] temp;

    initial begin
        #1 temp=x_in;
    end

    always@(posedge clk) begin
        temp<=temp+1;   
        y_out<=temp;
    end
endmodule

测试平台代码

`timescale 1ns/1ns

module testbench_conter();
    wire [31:0]y_out;
    wire [31:0]temp;
    reg [31:0]x_in;
    reg clk;

    counter C(x_in,clk,y_out);

    always begin
        #5 clk=~clk;
    end

    initial begin
        clk=1'b0; 
        x_in=32'd0;
        #0
        #10000
        $stop;
    end
endmodule

接下来,我认为计数器模块C将被执行...

您认为的主要缺陷是,在“执行”计数器时会执行计数器中的初始语句。 不是这种情况。 所有初始语句均在程序启动时运行,并且仅运行一次。 因此,您的两个初始语句构成了竞争条件。

通过使用#1或always@(x_in)可以将对temp1的分配延迟到定义x_in之后。

更好的方法是在您的计数器上添加一个“加载”信号,该信号在激活时会拾取x_in的值。

另外,您的y_out会延迟另一个时钟周期。

通常,可加载的计数器如下所示:

always@(posedge clk)
begin
   if (load)
      y_out <= x_in;
   else
      y_out <= y_out + 1;   
end

回答您的问题1: initial块之间绝对有保证的执行顺序。 Verilog仿真以任意不可预测的顺序启动它们。 同步的唯一方法是#delays和其他wait和delay语句。

Verilog保证任何过程性块(包括初始块和始终块)的执行将在等待条件下停止,直到满足为止。

Verilog还保证所有初始块都任何Always Block 之前开始。

始终在块灵敏度列表中指定的任何信号都扮演“延迟”语句的角色,从而使always块一直等到任何信号值发生变化。 之后它将继续执行该块。

因此,回答第二个问题时, always@(x_in)将一直等到信号值改变。

因此,在您的情况下:

 initial begin    << will start execution at time '0' before any always block
    clk=1'b0;     << change value of clk from 'x' -> '1' 
    x_in=32'd0;   << change value of x_in 'x' -> '0'
    #0            << makes absolutely no sense here. It is a special statement
    #10000        << pauses execution for 10000 time units
    $stop;        << stopps execution
end

当上面的初始块产生时,其他块开始执行。

initial begin     << starts execution at time 0, befor or after the block above
    #1 temp=x_in; << pauses for 1 time unit, then assigns temp
end 

上面的分配在第一个初始块等待#10000时发生。

如果您使用always块

always @(x_in)
   temp = x_in;

当x_in更改并且第一个初始块开始等待时,它将执行assignemt。 当信号被建立时,该总是块将以相同的周期“ 0”执行。 它与您使用的#1不同。 在您的情况下,更改将在周期“ 1”发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM