51c920e2622446c03440e7d49a443b938dbd236c
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 Register(Elaboratable
):
11 def __init__(self
, width
):
16 def read_port(self
, name
=None):
17 port
= RecordObject([("ren", 1),
18 ("data_o", self
.width
)],
20 self
._rdports
.append(port
)
23 def write_port(self
, name
=None):
24 port
= RecordObject([("wen", 1),
25 ("data_i", self
.width
)],
27 self
._wrports
.append(port
)
30 def elaborate(self
, platform
):
32 reg
= Signal(self
.width
, name
="reg")
34 # read ports. has write-through detection (returns data written)
35 for rp
in self
._rdports
:
36 wr_detect
= Signal(reset_less
=False)
38 m
.d
.comb
+= wr_detect
.eq(0)
39 for wp
in self
._wrports
:
41 m
.d
.comb
+= rp
.data_o
.eq(wp
.data_i
)
42 m
.d
.comb
+= wr_detect
.eq(1)
43 with m
.If(~wr_detect
):
44 m
.d
.comb
+= rp
.data_o
.eq(reg
)
46 # write ports, don't allow write to address 0 (ignore it)
47 for wp
in self
._wrports
:
49 m
.d
.sync
+= reg
.eq(wp
.data_i
)
54 for p
in self
._rdports
:
56 for p
in self
._wrports
:
63 class RegFileArray(Elaboratable
):
64 """ an array-based register file (register having write-through capability)
65 that has no "address" decoder, instead it has individual write-en
66 and read-en signals (per port).
68 def __init__(self
, width
, depth
):
71 self
.regs
= Array(Register(width
) for _
in range(self
.depth
))
75 def read_port(self
, name
=None):
77 for i
in range(self
.depth
):
78 port
= self
.regs
[i
].read_port(name
)
81 self
._rdports
.append(regs
)
84 def write_port(self
, name
=None):
86 for i
in range(self
.depth
):
87 port
= self
.regs
[i
].write_port(name
)
90 self
._wrports
.append(regs
)
93 def elaborate(self
, platform
):
95 for i
, reg
in enumerate(self
.regs
):
96 setattr(m
.submodules
, "reg_%d" % i
, reg
)
107 class RegFile(Elaboratable
):
108 def __init__(self
, width
, depth
):
115 bsz
= int(log(self
.width
) / log(2))
116 port
= RecordObject([("raddr", bsz
),
118 ("data_o", self
.width
)])
119 self
._rdports
.append(port
)
122 def write_port(self
):
123 bsz
= int(log(self
.width
) / log(2))
124 port
= RecordObject([("waddr", bsz
),
126 ("data_i", self
.width
)])
127 self
._wrports
.append(port
)
130 def elaborate(self
, platform
):
132 bsz
= int(log(self
.width
) / log(2))
133 regs
= Array(Signal(self
.width
, name
="reg") for _
in range(self
.depth
))
135 # read ports. has write-through detection (returns data written)
136 for rp
in self
._rdports
:
137 wr_detect
= Signal(reset_less
=False)
139 m
.d
.comb
+= wr_detect
.eq(0)
140 for wp
in self
._wrports
:
141 addrmatch
= Signal(reset_less
=False)
142 m
.d
.comb
+= addrmatch
.eq(wp
.waddr
== rp
.raddr
)
143 with m
.If(wp
.wen
& addrmatch
):
144 m
.d
.comb
+= rp
.data_o
.eq(wp
.data_i
)
145 m
.d
.comb
+= wr_detect
.eq(1)
146 with m
.If(~wr_detect
):
147 m
.d
.comb
+= rp
.data_o
.eq(regs
[rp
.raddr
])
149 # write ports, don't allow write to address 0 (ignore it)
150 for wp
in self
._wrports
:
151 with m
.If(wp
.wen
& (wp
.waddr
!= Const(0, bsz
))):
152 m
.d
.sync
+= regs
[wp
.waddr
].eq(wp
.data_i
)
157 yield from self
._rdports
158 yield from self
._wrports
163 if isinstance(r
, RecordObject
):
168 def regfile_sim(dut
, rp
, wp
):
170 yield wp
.data_i
.eq(2)
177 data
= yield rp
.data_o
185 yield wp
.data_i
.eq(6)
186 data
= yield rp
.data_o
191 data
= yield rp
.data_o
195 data
= yield rp
.data_o
201 wp
= dut
.write_port()
202 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
203 with
open("test_regfile.il", "w") as f
:
206 run_simulation(dut
, regfile_sim(dut
, rp
, wp
), vcd_name
='test_regfile.vcd')
208 dut
= RegFileArray(32, 8)
210 wp
= dut
.write_port()
212 print ("ports", ports
)
213 vl
= rtlil
.convert(dut
, ports
=ports
)
214 with
open("test_regfile_array.il", "w") as f
:
217 #run_simulation(dut, regfile_sim(dut, rp, wp), vcd_name='test_regfile.vcd')
219 if __name__
== '__main__':