首页 > 解决方案 > SyncReadMem 生成的 verilog 与 Rocketchip 发出的 verilog

问题描述

我正在使用SyncReadMem()进行 sram 行为模拟。使用verilator 生成的 Verilog,我希望将其替换为商业 sram 编译器编译的 verilog,这样我就可以对包括 sram 在内的整个设计进行综合。

但是,我注意到 SyncReadMem() 发出的 verilog 不像 Rocketchip 中发出的 sram那样具有统一的 IO 。我想知道我们如何使用 SyncReadMem() 之类的 chisel mem API 生成一些 sram verilog,就像 Rocketchip 一样?

标签: chisel

解决方案


您可以使用 Scala FIRRTL 编译器的“替换顺序记忆”传递来黑盒记忆。这正是 Rocket Chip 正在发生的事情。

请注意,这仅限于仅在存储器具有单个读取端口和单个写入端口并且读取延迟为 1 和写入延迟为 1 时才有效。

例如,考虑以下 1r1w(一读,一写)SyncReadMem

import chisel3._ 

class Foo extends MultiIOModule {
  val read = IO(new Bundle {
    val en = Input(Bool())
    val addr = Input(UInt(8.W))
    val data = Output(UInt(1.W))
  })
  val write = IO(new Bundle{
    val en = Input(Bool())
    val addr = Input(UInt(8.W))
    val data = Input(UInt(1.W))
  })
  val bar = SyncReadMem(256, UInt(1.W))
  
  read.data := bar.read(read.addr, read.en)
  when (write.en) {
    bar.write(write.addr, write.data)
  }
}

如果您通过运行替换顺序内存传递的请求来编译它:

(new ChiselStage)
  .emitVerilog(new Foo, Array("--repl-seq-mem", "-c:Foo:-o:Foo.mem.conf"))

-c:<circuit>其中使用的参数<circuit>是您要在其上运行的电路-o:<mem-conf-file>的名称,以及要生成的文件的名称,该文件将包含被黑盒化的存储器的信息(例如,名称、宽度和深度)。

您最终将内存黑盒化在一个bar名为的新模块中bar_ext

module bar(
  input  [7:0] R0_addr,
  input        R0_en,
  input        R0_clk,
  output       R0_data,
  input  [7:0] W0_addr,
  input        W0_en,
  input        W0_clk,
  input        W0_data
);
  wire [7:0] bar_ext_R0_addr;
  wire  bar_ext_R0_en;
  wire  bar_ext_R0_clk;
  wire  bar_ext_R0_data;
  wire [7:0] bar_ext_W0_addr;
  wire  bar_ext_W0_en;
  wire  bar_ext_W0_clk;
  wire  bar_ext_W0_data;
  bar_ext bar_ext (
    .R0_addr(bar_ext_R0_addr),
    .R0_en(bar_ext_R0_en),
    .R0_clk(bar_ext_R0_clk),
    .R0_data(bar_ext_R0_data),
    .W0_addr(bar_ext_W0_addr),
    .W0_en(bar_ext_W0_en),
    .W0_clk(bar_ext_W0_clk),
    .W0_data(bar_ext_W0_data)
  );
  assign bar_ext_R0_clk = R0_clk;
  assign bar_ext_R0_en = R0_en;
  assign bar_ext_R0_addr = R0_addr;
  assign R0_data = bar_ext_R0_data;
  assign bar_ext_W0_clk = W0_clk;
  assign bar_ext_W0_en = W0_en;
  assign bar_ext_W0_addr = W0_addr;
  assign bar_ext_W0_data = W0_data;
endmodule

然后,您可以运行内存编译器来使用内存配置文件中的信息,并将输出替换为bar_ext.


推荐阅读