-
Notifications
You must be signed in to change notification settings - Fork 17
Memories in Chisel
Memories in Chisel In chisel there are three different ways to specify a memory:
- Vector: Vec(DEPTH, Reg(Bits(width=WIDTH)))
- SeqMem(DEPTH, WIDTH)
- Mem(DEPTH, WIDTH) -- See Mem keyword in Chisel
-] The first — Chisel generates individual flip flops in verilog.
-] The second — Chisel generates verilog of this form “module XYZ: reg DEPTH:0 ram WIDTH:0” Then, we modify the verilog and insert a reference to a wrapper. We also write the wrapper, ties “module XYZ” to a specific file that was generated by the memory compiler. The backend take the wrapper and substitutes the memory layout in place of “module XYZ”
-] The third — Chisel generates verilog of the form “reg DEPTH:0 ram WIDTH:0” but this is also the form that is matched by backend tools and instantiated with a compiled SRAM. See [Mem in Chisel]
2- SeqMem
“SeqMem(DEPTH, WIDTH)” in Chisel, generates this verilog:
====
module XYZ(
input CLK,
input RST,
input init,
input 2:0 W0A,
input W0E,
input 73:0 W0I,
input 2:0 R1A,
input R1E,
output 73:0 R1O
);
reg 2:0 reg_R1A;
reg 73:0 ram 7:0;
ifndef SYNTHESIS ` `integer initvar; ` `initial begin ` `#0.002; ` `for (initvar = 0; initvar < 8; initvar = initvar+1) ` `raminitvar = {3 {$random}}; ` `reg_R1A = {1 {$random}}; ` `end `
endif
integer i;
always @(posedge CLK) begin
if (R1E) reg_R1A <= R1A;
for (i = 0; i < 74; i=i+1) begin
if (W0E) ramW0Ai <= W0Ii;
end
end
assign R1O = ramreg_R1A;`
endmodule
====
During simulation, the variable SYNTHESIS is not defined, so it simulates this as a collection of flip flops.
During synthesis, though, SYNTHESIS is defined, so the ifndef statement is false.. in that case, some magic happens that we haven’t quite figured out yet..
Somehow the synthesizer decides to use registers and generates registers to implement this.
However, if you modify the generated Verilog and insert a reference to a wrapper, and make the wrapper reference a specific name of a memory array that was generated by a compiler, then it will include the memory array.
The modified verilog file, which invokes a wrapper, looks like this:
======
module XYZ
(
<SAME INTERFACE as above>
);
assign wea_b = ~(|wea);
SRAM2RW128x32
SRAM2RW128x32_0
(
.A1 (addra),
.CE1 (clka),
.WEB1 (wea_b),
.OEB1 (),
.CSB1 (wea_b),
.I1 (dina0 +: 32),
.O1 (),
.A2 (addrb),
.CE2 (clka),
.WEB2 (enb),
.OEB2 (~enb),
.CSB2 (~enb),
.I2 (),
.O2 (doutb0 +: 32)
);
SRAM2RW128x32
SRAM2RW128x32_1
(
.A1 (addra),
.CE1 (clka),
.WEB1 (wea_b),
.OEB1 (),
.CSB1 (wea_b),
.I1 (dina32 +: 32),
.O1 (),
.A2 (addrb),
.CE2 (clka),
.WEB2 (enb),
.OEB2 (~enb),
.CSB2 (~enb),
.I2 (),
.O2 (doutb32 +: 32)
);
endmodule
If we removed this file, which defines module XYZ, then the memory XYZ will be a hole. It will then not be considered in timing and area.