From 1e520202acafd5c8cd3320e7e56879e699e14ac2 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 7 May 2019 12:29:41 +0100 Subject: [PATCH] add a variant of a regfile that has individual read/write-enable lines --- src/regfile/regfile.py | 106 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/src/regfile/regfile.py b/src/regfile/regfile.py index cb3608ad..1bb5e287 100644 --- a/src/regfile/regfile.py +++ b/src/regfile/regfile.py @@ -7,6 +7,101 @@ from nmutil.iocontrol import RecordObject from math import log +class Register(Elaboratable): + def __init__(self, width): + self.width = width + self._rdports = [] + self._wrports = [] + + def read_port(self): + port = RecordObject([("ren", 1), + ("data_o", self.width)]) + self._rdports.append(port) + return port + + def write_port(self): + port = RecordObject([("wen", 1), + ("data_i", self.width)]) + self._wrports.append(port) + return port + + def elaborate(self, platform): + m = Module() + reg = Signal(self.width, name="reg") + + # read ports. has write-through detection (returns data written) + for rp in self._rdports: + wr_detect = Signal(reset_less=False) + with m.If(rp.ren): + m.d.comb += wr_detect.eq(0) + for wp in self._wrports: + with m.If(wp.wen): + m.d.comb += rp.data_o.eq(wp.data_i) + m.d.comb += wr_detect.eq(1) + with m.If(~wr_detect): + m.d.comb += rp.data_o.eq(reg) + + # write ports, don't allow write to address 0 (ignore it) + for wp in self._wrports: + with m.If(wp.wen): + m.d.sync += reg.eq(wp.data_i) + + return m + + def __iter__(self): + for p in self._rdports: + yield from p + for p in self._wrports: + yield from p + + def ports(self): + res = list(self) + + +class RegFileArray(Elaboratable): + """ an array-based register file (register having write-through capability) + that has no "address" decoder, instead it has individual write-en + and read-en signals (per port). + """ + def __init__(self, width, depth): + self.width = width + self.depth = depth + self.regs = Array(Register(width) for _ in range(self.depth)) + self._rdports = [] + self._wrports = [] + + def read_port(self): + regs = [] + for i in range(self.depth): + port = self.regs[i].read_port() + regs.append(port) + regs = Array(regs) + self._rdports.append(regs) + return regs + + def write_port(self): + regs = [] + for i in range(self.depth): + port = self.regs[i].write_port() + regs.append(port) + regs = Array(regs) + self._wrports.append(regs) + return regs + + def elaborate(self, platform): + m = Module() + for i, reg in enumerate(self.regs): + setattr(m.submodules, "reg_%d" % i, reg) + return m + + def __iter__(self): + for r in self.regs: + yield from r + + def ports(self): + return list(self) + + class RegFile(Elaboratable): def __init__(self, width, depth): self.width = width @@ -108,5 +203,16 @@ def test_regfile(): run_simulation(dut, regfile_sim(dut, rp, wp), vcd_name='test_regfile.vcd') + dut = RegFileArray(32, 8) + rp = dut.read_port() + wp = dut.write_port() + ports=dut.ports() + print ("ports", ports) + vl = rtlil.convert(dut, ports=ports) + with open("test_regfile_array.il", "w") as f: + f.write(vl) + + #run_simulation(dut, regfile_sim(dut, rp, wp), vcd_name='test_regfile.vcd') + if __name__ == '__main__': test_regfile() -- 2.30.2