1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
4 from nmigen
import Const
, Array
, Signal
, Elaboratable
, Module
5 from nmutil
.iocontrol
import RecordObject
10 class RegFile(Elaboratable
):
11 def __init__(self
, width
, depth
):
18 bsz
= int(log(self
.width
) / log(2))
19 port
= RecordObject([("raddr", bsz
),
21 ("data_o", self
.width
)])
22 self
._rdports
.append(port
)
26 bsz
= int(log(self
.width
) / log(2))
27 port
= RecordObject([("waddr", bsz
),
29 ("data_i", self
.width
)])
30 self
._wrports
.append(port
)
33 def elaborate(self
, platform
):
35 bsz
= int(log(self
.width
) / log(2))
36 regs
= Array(Signal(self
.width
, name
="reg") for _
in range(self
.depth
))
38 # read ports. has write-through detection (returns data written)
39 for rp
in self
._rdports
:
40 wr_detect
= Signal(reset_less
=False)
42 m
.d
.comb
+= wr_detect
.eq(0)
43 for wp
in self
._wrports
:
44 addrmatch
= Signal(reset_less
=False)
45 m
.d
.comb
+= addrmatch
.eq(wp
.waddr
== rp
.raddr
)
46 with m
.If(wp
.wen
& addrmatch
):
47 m
.d
.comb
+= rp
.data_o
.eq(wp
.data_i
)
48 m
.d
.comb
+= wr_detect
.eq(1)
49 with m
.If(~wr_detect
):
50 m
.d
.comb
+= rp
.data_o
.eq(regs
[rp
.raddr
])
52 # write ports, don't allow write to address 0 (ignore it)
53 for wp
in self
._wrports
:
54 with m
.If(wp
.wen
& (wp
.waddr
!= Const(0, bsz
))):
55 m
.d
.sync
+= regs
[wp
.waddr
].eq(wp
.data_i
)
60 yield from self
._rdports
61 yield from self
._wrports
66 if isinstance(r
, RecordObject
):
71 def regfile_sim(dut
, rp
, wp
):
80 data
= yield rp
.data_o
89 data
= yield rp
.data_o
94 data
= yield rp
.data_o
98 data
= yield rp
.data_o
104 wp
= dut
.write_port()
105 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
106 with
open("test_regfile.il", "w") as f
:
109 run_simulation(dut
, regfile_sim(dut
, rp
, wp
), vcd_name
='test_regfile.vcd')
111 if __name__
== '__main__':