Skip to content

Instantly share code, notes, and snippets.

@Ravenslofty
Last active January 1, 2020 18:21
Show Gist options
  • Save Ravenslofty/14382e4c0493147b5d265376e9b8300a to your computer and use it in GitHub Desktop.
Save Ravenslofty/14382e4c0493147b5d265376e9b8300a to your computer and use it in GitHub Desktop.
from nmigen import *
from nmigen.back import rtlil, verilog
READ_PORTS_PER_CHANNEL = 2
WRITE_PORTS_PER_CHANNEL = 1
CHANNELS = 2
REGISTERS = 32
class Gpr(Elaboratable):
def __init__(self, rwidth=32):
self.rwidth = rwidth
self.rdepth = (REGISTERS - 1).bit_length()
self.i_wr_a = Array(Array(Signal(self.rdepth) for _ in range(WRITE_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
self.i_wr_d = Array(Array(Signal(rwidth) for _ in range(WRITE_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
self.i_rd_a = Array(Array(Signal(self.rdepth) for _ in range(READ_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
self.o_rd_d = Array(Array(Signal(rwidth) for _ in range(READ_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
def elaborate(self, platform):
m = Module()
select = Memory(width=CHANNELS, depth=self.rdepth)
regfile = Array(Memory(width=self.rwidth, depth=self.rdepth) for _ in range(CHANNELS))
readmux = Array(Array(Array(Signal(self.rwidth)) for _ in range(CHANNELS) for _ in range(READ_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
for chan in range(CHANNELS):
# Write ports
for port in range(WRITE_PORTS_PER_CHANNEL):
m.submodules["reg_write_c{}p{}".format(chan, port)] = reg_write_port = regfile[chan].write_port()
m.submodules["sel_write_c{}p{}".format(chan, port)] = sel_write_port = select.write_port()
m.d.comb += [
reg_write_port.addr.eq(self.i_wr_a[chan][port]),
reg_write_port.data.eq(self.i_wr_d[chan][port]),
sel_write_port.addr.eq(self.i_wr_a[chan][port]),
sel_write_port.data.eq(port)
]
# Read ports
for port in range(READ_PORTS_PER_CHANNEL):
m.submodules["reg_read_c{}p{}".format(chan, port)] = reg_read_port = regfile[chan].read_port()
m.submodules["sel_read_c{}p{}".format(chan, port)] = sel_read_port = select.read_port()
for otherchan in range(CHANNELS):
m.d.comb += readmux[otherchan][port][chan].eq(reg_read_port.data)
m.d.comb += [
reg_read_port.addr.eq(self.i_rd_a[chan][port]),
sel_read_port.addr.eq(self.i_rd_a[chan][port]),
self.o_rd_d[chan][port].eq(readmux[chan][port][sel_read_port.data])
]
return m
dut = Gpr()
ports = [
dut.i_wr_a, dut.i_wr_d,
dut.i_rd_a, dut.o_rd_d
]
print(verilog.convert(dut, ports=ports))
Traceback (most recent call last):
File "gpr.py", line 64, in <module>
print(verilog.convert(dut, ports=ports))
File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/back/verilog.py", line 76, in convert
rtlil_text = rtlil.convert(*args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/back/rtlil.py", line 1010, in convert
fragment = ir.Fragment.get(elaboratable, platform).prepare(**kwargs)
File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/hdl/ir.py", line 556, in prepare
fragment._propagate_ports(ports=(*ports, *new_ports), all_undef_as_ports=False)
File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/hdl/xfrm.py", line 128, in on_value
new_value = self.on_unknown_value(value)
File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/hdl/xfrm.py", line 86, in on_unknown_value
raise TypeError("Cannot transform value {!r}".format(value)) # :nocov:
TypeError: Cannot transform value (array mutable [(array mutable [(sig $signal)]), (array mutable [(sig $signal)])])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment