繁体   English   中英

Quartus 不允许在 Verilog 中使用 Generate 模块

[英]Quartus does not allow using a Generate block in Verilog

很简单的问题。 给定以下代码:

module main(
    output reg  [1:0][DATA_WIDTH-1:0] dOut,
    input  wire [1:0][DATA_WIDTH-1:0] dIn,
    input  wire [1:0][ADDR_WIDTH-1:0] addr,
    input  wire [1:0] wren,
    input  wire clk
);
    parameter DATA_WIDTH = 16;
    parameter ADDR_WIDTH = 6;

    reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];

    generate
        genvar k;
        for(k=0; k<2; k=k+1) begin: m
            always @(posedge clk) begin
                if(wren[k])
                    ram[addr[k]] <= dIn[k];
                dOut[k] <= ram[addr[k]];
            end
        end
    endgenerate
endmodule

quarus 13.0sp1 给出了这个错误(以及它的其他 20 个不正当的兄弟等价的兄弟姐妹):

错误 (10028): 无法在 main.v(42) 解析网络“ram [63] [14]”的多个常量驱动程序

但是,如果我手动展开生成循环:

module main(
    output reg  [1:0][DATA_WIDTH-1:0] dOut,
    input  wire [1:0][DATA_WIDTH-1:0] dIn,
    input  wire [1:0][ADDR_WIDTH-1:0] addr,
    input  wire [1:0] wren,
    input  wire clk
);
    parameter DATA_WIDTH = 16;
    parameter ADDR_WIDTH = 6;

    reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];

    always @(posedge clk) begin
        if(wren[0])
            ram[addr[0]] <= dIn[0];
        dOut[0] <= ram[addr[0]];
    end

    always @(posedge clk) begin
        if(wren[1])
            ram[addr[1]] <= dIn[1];
        dOut[1] <= ram[addr[1]];
    end
endmodule

分析和合成步骤一切顺利。

有什么办法可以让生成循环运行?

我认为正确的方法是在这个问题中解释的内容: Using a generate with for loop in verilog

这将被转移到您的代码中,如下所示:

module main(
    output reg  [1:0][DATA_WIDTH-1:0] dOut,
    input  wire [1:0][DATA_WIDTH-1:0] dIn,
    input  wire [1:0][ADDR_WIDTH-1:0] addr,
    input  wire [1:0] wren,
    input  wire clk
);
    parameter DATA_WIDTH = 16;
    parameter ADDR_WIDTH = 6;

    reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];    
    integer k;

    always @(posedge clk) begin
      for(k=0; k<2; k=k+1) begin:
        if(wren[k])
          ram[addr[k]] <= dIn[k];
        dOut[k] <= ram[addr[k]];
      end
    end
endmodule

将所有对双端口 RAM 的访问保持在一个always块中很方便,因此合成器可以安全地检测到您正在有效地在寄存器ram处使用双端口 RAM。

生成循环和展开版本都不应该通过综合。 在这两种情况下,两个 always 块都可以分配ram中的相同地址。 更糟糕的是,如果wren的两个位都为高且两个地址相同而数据不同,则结果无法确定。 Verilog LRM 声明寄存器上的最后一次分配获胜,并且始终可以以任何顺序评估具有相同触发器的块。

综合要求对寄存器的分配是确定性的。 两个(或更多)总是对同一位具有写访问权限的块是非法的,因为具有不确定性。 如果展开的合成正确,那么这意味着wrenaddr上存在所示模块之外的常量,这使得写冲突在逻辑上是不可能的; 由于某种原因,生成循环版本没有得到相同的优化。 允许优化以防止多始终阻止写入访问的约束示例:

  1. 一个wren被硬编码为 0。因此只有一个块具有独占访问权限
  2. 地址具有不重叠的可能值集。 例如addr[0]只能是偶数,而addr[1]只能是奇数,或者addr[0] < 2**(ADDR_WIDTH/2)addr[1] >= 2**(ADDR_WIDTH/2)

dOut由两个 always 块分配是可以的,因为每个块都对其目标位(可能的地址值的非重叠集)具有独占的写访问权限。

mcleod_ideafix 答案中的单个始终块是首选解决方案。 如果wren的两个位都为高且两个地址相同,则wren[1]将始终获胜。 如果wren[0]应该具有优先级,则使 for 循环倒计时。

暂无
暂无

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

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