HeavyX/examples/simplesoc_ecp5.py

100 lines
3.0 KiB
Python
Raw Normal View History

import os
2019-06-06 18:11:54 +08:00
import argparse
import struct
2019-05-02 12:53:28 +08:00
from nmigen import *
from nmigen.back import pysim
from nmigen_boards.versa_ecp5 import VersaECP5Platform
2019-05-02 12:53:28 +08:00
from heavycomps import uart, wishbone
from minerva.core import Minerva
class SimpleWishboneSerial(Elaboratable):
def __init__(self, tx, sys_clk_freq, baudrate=115200):
self.tx = tx
self.bus = wishbone.Interface()
self.ftw = round(2**32*baudrate/sys_clk_freq)
def elaborate(self, platform):
m = Module()
m.submodules.tx = tx = uart.RS232TX(self.ftw)
m.d.comb += [
tx.stb.eq(self.bus.cyc & self.bus.stb & self.bus.we),
tx.data.eq(self.bus.dat_w),
self.bus.ack.eq(tx.ack),
self.tx.eq(tx.tx)
]
return m
class Top(Elaboratable):
def __init__(self, firmware, simulate):
2019-06-06 18:11:54 +08:00
self.firmware = firmware
self.simulate = simulate
2019-05-02 12:53:28 +08:00
def elaborate(self, platform):
m = Module()
if self.simulate:
io_user_led = Signal()
io_uart_tx = Signal()
else:
2019-06-08 17:30:49 +08:00
cd_sync = ClockDomain(reset_less=True)
m.domains += cd_sync
m.d.comb += cd_sync.clk.eq(platform.request("clk100").i)
io_user_led = platform.request("led").o
io_uart_tx = platform.request("uart").tx.o
2019-05-02 12:53:28 +08:00
2019-06-07 23:17:19 +08:00
counter = Signal(27)
m.d.sync += counter.eq(counter + 1)
m.d.comb += io_user_led.eq(counter[-1])
2019-06-07 23:17:19 +08:00
2019-05-13 00:46:52 +08:00
m.submodules.cpu = cpu = Minerva(with_icache=False, with_dcache=False, with_muldiv=False)
m.submodules.ram = ram = wishbone.SRAM(Memory(width=32, depth=1024, init=self.firmware))
m.submodules.uart = uart = SimpleWishboneSerial(io_uart_tx, 100e6)
2019-05-02 12:53:28 +08:00
m.submodules.con = con = wishbone.InterconnectShared(
[cpu.ibus, cpu.dbus],
[
(lambda a: ~a[20], ram.bus),
(lambda a: a[20], uart.bus)
], register=True)
return m
2019-06-06 18:11:54 +08:00
def read_firmware(file):
firmware = []
with open(file, "rb") as f:
while True:
word = f.read(4)
if len(word) < 4:
break
2019-06-08 17:30:49 +08:00
firmware.append(struct.unpack("<I", word)[0])
2019-06-06 18:11:54 +08:00
return firmware
2019-05-02 12:53:28 +08:00
def main():
2019-06-06 18:11:54 +08:00
parser = argparse.ArgumentParser()
2019-06-08 17:30:49 +08:00
parser.add_argument("--simulate", action="store_true")
2019-06-06 18:11:54 +08:00
parser.add_argument("firmware_bin")
parser.add_argument("build_dir")
2019-06-06 18:11:54 +08:00
args = parser.parse_args()
firmware = read_firmware(args.firmware_bin)
top = Top(firmware, args.simulate)
2019-06-08 17:30:49 +08:00
if args.simulate:
os.makedirs(args.build_dir, exist_ok=True)
2019-06-08 17:30:49 +08:00
with pysim.Simulator(top,
vcd_file=open(os.path.join(args.build_dir, "simplesoc.vcd"), "w"),
gtkw_file=open(os.path.join(args.build_dir, "simplesoc.gtkw"), "w")) as sim:
2019-06-08 17:30:49 +08:00
sim.add_clock(1e-6)
2019-06-08 23:00:57 +08:00
sim.run_until(1000e-6, run_passive=True)
2019-06-08 17:30:49 +08:00
else:
VersaECP5Platform().build(top, build_dir=args.build_dir)
2019-05-02 12:53:28 +08:00
if __name__ == "__main__":
main()