Skip to content

Instantly share code, notes, and snippets.

@lachlansneff
Last active November 22, 2020 18:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lachlansneff/e30fb4145b52059a348b811366798130 to your computer and use it in GitHub Desktop.
Save lachlansneff/e30fb4145b52059a348b811366798130 to your computer and use it in GitHub Desktop.
from os import write
from nmigen import Elaboratable, Module, Signal, Memory, ClockSignal, Instance, ResetSignal
import numpy as np
class Mapping:
def __init__(self, addr: int, signal: Signal, read: bool, write: bool):
self.addr = addr
self.signal = signal
self.read = read
self.write = write
class PicoRV32(Elaboratable):
def __init__(self, memory_mappings: list[Mapping]):
self.memory_mappings = memory_mappings
def elaborate(self, platform):
platform.add_file("picorv32.v", open("picorv32.v", "r"))
# TODO: build an application and load it into this memory + stack
with open("app/app.bin", "rb") as f:
b = bytearray(f.read())
b.extend([0] * (len(b) % 4))
app_init = np.frombuffer(b, dtype=np.uint32).tolist()
MEM_SIZE = 256 # words
mem = Memory(
width=32,
depth=MEM_SIZE,
init=app_init,
)
mem_valid = Signal()
mem_ready = Signal()
mem_addr = Signal(32)
mem_wdata = Signal(32)
mem_wstrb = Signal(4)
mem_rdata = Signal(32)
m = Module()
m.submodules.picorv32 = Instance("picorv32",
p_ENABLE_COUNTERS=0,
p_LATCHED_MEM_RDATA=1,
p_TWO_STAGE_SHIFT=0,
p_TWO_CYCLE_ALU=1,
p_CATCH_MISALIGN=0,
p_CATCH_ILLINSN=0,
i_clk=ClockSignal(),
i_resetn=~ResetSignal(),
o_mem_valid=mem_valid,
i_mem_ready=mem_ready,
o_mem_addr=mem_addr,
o_mem_wdata=mem_wdata,
o_mem_wstrb=mem_wstrb,
i_mem_rdata=mem_rdata,
)
m.submodules.read_port = read_port = mem.read_port(transparent=False)
m.submodules.write_port = write_port = mem.write_port(granularity=8)
delay = Signal()
m.d.sync += [
delay.eq(0),
mem_ready.eq(0),
]
m.d.comb += [
read_port.en.eq(0),
write_port.en.eq(0),
]
with m.If(mem_valid & ~mem_ready):
m.d.comb += [
read_port.addr.eq(mem_addr >> 2),
mem_rdata.eq(read_port.data),
read_port.en.eq((~mem_wstrb).bool()),
write_port.addr.eq(mem_addr >> 2),
write_port.data.eq(mem_wdata),
write_port.en.eq(mem_wstrb),
]
with m.If((mem_addr >> 2) < MEM_SIZE):
m.d.sync += [
delay.eq(1),
mem_ready.eq(delay),
]
for mapping in self.memory_mappings:
if mapping.write:
with m.If(mem_wstrb.bool() & (mem_addr == mapping.addr)):
m.d.sync += [
mapping.signal.eq(mem_wdata),
mem_ready.eq(1),
]
elif mapping.read:
with m.If((~mem_wstrb).bool() & (mem_addr == mapping.addr)):
m.d.comb += mem_rdata.eq(mapping.signal)
m.d.sync += mem_ready.eq(1)
else:
print("mapping doesn't specify read or write")
return m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment