-
-
Save lachlansneff/e30fb4145b52059a348b811366798130 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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