verilog - 在 Intel Quartus 中,我可以使用字符串参数初始化 RAM 吗?

标签 verilog system-verilog fpga quartus intel-fpga

我需要使用不同的数据文件初始化同一内存模块的多个实例,我想按如下方式执行:

module ram #(
  string HEXFILE = "split1.mem"
)
(
  input  logic        clk,
  input  logic [31:0] a,
  input  logic [7:0]  wd,
  input  logic        we,
  output logic [7:0]  rd
);

logic [7:0] mem [3071:0];
integer fd;


initial $readmemh(HEXFILE, mem);

always_ff @(posedge clk) begin
  if (we) mem[a] <= wd;
  rd <= mem[a];
end

endmodule

在我的顶级实体中,按如下方式初始化它们:

ram #(
  .HEXFILE("split1.mem")
) M0 (
  .clk(clk),
  .a(a0),
  .wd(wd0),
  .we(we),
  .rd(rd0)
);

ram #(
  .HEXFILE("split2.mem")
) M1 (
  .clk(clk),
  .a(a1),
  .wd(wd1),
  .we(we),
  .rd(rd1)
);

// And so on ...

但是当我尝试执行此操作时,出现以下错误:

Error (10686): SystemVerilog error at ram.sv(18): HEXFILE has an aggregate value

如果我使用字符串文字作为文件名,效果很好:

initial $readmemh("split1.mem", mem)

关于如何在不创建同一文件的副本只是为了更改输入文件的情况下实现此目的,有什么想法吗?

编辑:我认为 Verilog 对待参数和字符串文字的方式不同。它将string视为logic的扩展,这就是为什么它说它需要扩展。

我不知道如何将它定义为字符串文字。以下似乎有效,但在我看来这是一种非常糟糕的方式:

generate
if      (HEXFILE == "split1.mem") initial $readmemh("split1.mem", mem);
else if (HEXFILE == "split2.mem") initial $readmemh("split2.mem", mem);
else if (HEXFILE == "split3.mem") initial $readmemh("split3.mem", mem);
else if (HEXFILE == "split4.mem") initial $readmemh("split4.mem", mem);
endgenerate

最佳答案

您看到的报告错误是针对 ram 模块中的第 18 行,即这一行:

always_ff @(posedge clk) begin

当我在不同的模拟器上运行时,我没有看到确切的错误消息,但使用 Synopsys VCS,我看到:

Error-[ICPD] Illegal combination of drivers
ram.sv, 12
  Illegal combination of procedural drivers
  Variable "mem" is driven by an invalid combination of procedural drivers. 
  Variables written on left-hand of "always_ff" cannot be written to by any 
  other processes, including other "always_ff" processes.
  This variable is declared at "ram.sv", 12: logic [7:0] mem[3071:0];
  The first driver is at "ram.sv", 16: $readmemh(HEXFILE, mem);
  The second driver is at "ram.sv", 18: always_ff @(posedge clk) begin
  if (we) begin
   ...

请参阅 IEEE Std 1800-2017,第 9.2.2.4 节顺序逻辑always_ff 过程:

Variables on the left-hand side of assignments within an always_ff procedure, including variables from the contents of a called function, shall not be written to by any other process.

错误消失:

always @(posedge clk) begin

除此之外,我没有发现使用传递给不同实例的 HEXFILE 的不同值有任何问题。如果您仍然遇到问题,可以尝试使用 parameter 而不是 string:

module ram #(
  parameter HEXFILE = "split1.mem"
)

关于verilog - 在 Intel Quartus 中,我可以使用字符串参数初始化 RAM 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70222864/

相关文章:

verilog - SystemVerilog `force` 是如何工作的?

system-verilog - Always block 中的 continue 有何作用?

arrays - case 语句中的 Verilog/SystemVerilog 推断锁存器

syntax - 此Assign语句中的语法有什么问题?

struct - System Verilog VPI 中的打包结构?

system-verilog - 如何在垃圾回收时执行 SystemVerilog 代码?

VHDL - 队列中的变量与信号行为

clock - VHDL 中的嵌套 if (rising_edge(clk)) 语句

verilog - 如何在verilog中将来自wire的输入存储到reg中?

verilog - 由于方向声明而编译代码时出错