Search code examples
scalachisel

Chisel synchronous read memory


I'm trying to generate the verilog for a memory with a synchronous read with the following chisel

val my_mem = Mem(Bits(width=64), 4096, seqRead=true)
val read_data = Reg(Bits(width=64))
when(io.re) {
 read_data := my_mem(io.addr)
}
io.ret_data := read_data

However, this generates verilog with this

wire[63:0] T1;
reg [63:0] read_data;
assign T1 = my_mem[io_addr];

always @(posedge clk) begin
if(io_re) begin
  read_data <= T1;
end

What I am doing wrong to get chisel to generate verilog that has the memory read inside the always block?


Solution

  • The Chisel manual state the proper way to create a synchronous memory is to register the ADDRESS, not the read data. Although slightly unintuitive, with register re-timing, it is conceptually the same thing.

     val my_mem    = Mem(Bits(width=64), 4096, seqRead=true)
     val reg_raddr = Reg(UInt())
     val rdata     = my_mem(reg_raddr)
     when (io.re) { reg_raddr := io.addr }
    

    Which generates this:

    assign io_out = T0;
    assign T0 = my_mem[reg_raddr];
    
    always @(posedge clk) begin
      if(io_re) begin
        reg_raddr <= io_addr;
      end
    end 
    

    The data read is not in the always block, but I don't believe that is necessary for the synthesis tools to pick up that you want a synchronous memory.