Verilog中的Concurrent Always块

时间:2017-08-08 16:38:50

标签: concurrency verilog fpga vivado

我对一些看似完全正常的verilog风格的代码进行了几次讨论,但对我来说看起来相当危险(我是Verilog的新手)。它总是关于并发总是块和/或分配。这是一个例子:

module some(input clk_i);

..
    module ram(
          input   wire                a_clk,
          input   wire                a_wr,
          input   wire    [ADDR-1:0]  a_addr,
          input   wire    [DATA-1:0]  a_din,
          output  reg     [DATA-1:0]  a_dout,
    );

    reg [DATA-1:0] mem [(2**ADDR)-1:0];


    always @(posedge a_clk) begin
          a_dout      <= mem[a_addr];
          if(a_wr) begin
              a_dout      <= a_din;
              mem[a_addr] <= a_din;
          end
    end

    endmodule
..

reg wrmem=1'b0;
reg[ADDR-1:0] memaddr;
reg[DATA-1:0] d_in;


ram mem(.a_clk(clk_i),.a_wr(wrmem),.a_addr(memaddr),.a_din(d_in),.a_dout(memout));

..

always @(posedge clk_i) begin
    wrmem <= 1'b0;
        ...
        if(..) begin
            d_in <= sth.
            memaddr <= some address
            wrmem <= 1b'1;
    end
end

endmodule;  

所以这里我们有两个并发的always-blocks。第一个(在模块“ram”中)对时钟作出反应并且'reg a_wr'为高。在第二个中,这个'reg'被设置为0,几个步骤再次被设置为1。为什么这不会导致模块“ram”的任意行为(因为第一个块不等到seconde完成)?

1 个答案:

答案 0 :(得分:1)

确切地说,非阻塞分配的原因确实存在于verilog中。

Verilog调度由每个delta周期的几个桶组成。大致非阻塞分配在阻止分配之后的单独调度存储区中执行。

所以,在你的情况下,你有两件事:

always @(posedge clk) 
    if (wreg)
       ...

always @(posedge clk)
    wreg <= 0;
    ...

在模拟中,第一个块将使用&#39; wreg&#39;的值。因为它在执行非阻塞存储桶之前存在,可能是1

第二个块将安排在非阻塞存储桶中将wreg的更新更新为0,尚未执行。所以,没有冲突。

因此,您可以确保在模拟过程中获得一致的结果。