Concurrency Verilog中的并发始终块

Concurrency Verilog中的并发始终块,concurrency,verilog,fpga,vivado,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

我曾几次纠结于一些代码,这些代码似乎是完全正常的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;  
模块部分(输入时钟i);
..
模块ram(
输入线a_clk,
输入线a_wr,
输入线[ADDR-1:0]a_ADDR,
输入线[DATA-1:0]a_-din,
输出寄存器[DATA-1:0]a\u dout,
);
注册[数据-1:0]mem[(2**ADDR)-1:0];
始终@(按下按钮)开始

这正是verilog中存在非阻塞分配的原因

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

因此,在你的情况下,你有两件事:

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

始终@(posedge clk)

在第二个“reg”中,此“reg”设置为0,几步后再次设置为1-在哪里?我看到两个不同的名字
wrmem
wrem
。不管怎么说,看起来就像是一个重复的输入错误,所以在第二个始终块中将wreg设置为1后,if(wreg)-块执行一个周期,对吗?这是同一个模拟周期,但在同一个周期中有不同的存储桶。但是,假设我们从wreg=0开始,在第一个周期中将wreg设置为1:1。循环:[1.如果(wreg)为false,则为2.wregyes。这是正确的。这就是触发器设计在硅中的工作原理。第二条语句表示wreg上的触发器。
always @(posedge clk)
    wreg <= 0;
    ...