diff --git a/examples/simplesoc_ecp5.nix b/examples/simplesoc_ecp5.nix new file mode 100644 index 0000000..586c6e4 --- /dev/null +++ b/examples/simplesoc_ecp5.nix @@ -0,0 +1,26 @@ +{ pkgs ? import {} +, hx ? import ../default.nix { inherit pkgs; }}: + +let + symbiflowInput = pkgs.runCommand "simplesoc-symbiflow-input" { + buildInputs = [ (pkgs.python3.withPackages(ps: [hx.nmigen hx.heavycomps hx.minerva])) hx.yosys ]; + } + '' + mkdir $out + + python ${./simplesoc_ecp5.py} > $out/top.il + + cat > $out/top.lpf << EOF + LOCATE COMP "clk100" SITE "P3"; + IOBUF PORT "clk100" IO_TYPE=LVDS; + LOCATE COMP "serial_tx" SITE "A11"; + IOBUF PORT "serial_tx" IO_TYPE=LVCMOS33; + EOF + + echo -n "--um-45k --package CABGA381" > $out/device + ''; +in + hx.symbiflow.buildBitstream { + name = "simplesoc-bitstream"; + src = symbiflowInput; + } diff --git a/examples/simplesoc_ecp5.py b/examples/simplesoc_ecp5.py new file mode 100644 index 0000000..fa77d38 --- /dev/null +++ b/examples/simplesoc_ecp5.py @@ -0,0 +1,74 @@ +from nmigen import * +from nmigen.back import rtlil + +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): + self.clk100 = Signal() + self.serial_tx = Signal() + + def elaborate(self, platform): + m = Module() + + cd_sync = ClockDomain(reset_less=True) + m.domains += cd_sync + m.d.comb += cd_sync.clk.eq(self.clk100) + + m.submodules.cpu = cpu = Minerva(with_icache=False, with_dcache=False) + m.submodules.ram = ram = wishbone.SRAM(Memory(32, 1024)) + m.submodules.uart = uart = SimpleWishboneSerial(self.serial_tx, 100e6) + m.submodules.con = con = wishbone.InterconnectShared( + [cpu.ibus, cpu.dbus], + [ + (lambda a: ~a[20], ram.bus), + (lambda a: a[20], uart.bus) + ], register=True) + + # work around https://github.com/m-labs/nmigen/issues/30 + m.d.comb += [ + cpu.external_interrupt.eq(0), + cpu.timer_interrupt.eq(0), + cpu.fetch.ibus.dat_w.eq(0), + cpu.fetch.ibus.sel.eq(0b1111), + cpu.fetch.ibus.we.eq(0), + cpu.fetch.ibus.cti.eq(0), + cpu.fetch.ibus.bte.eq(0), + cpu.loadstore.dbus.cti.eq(0), + cpu.loadstore.dbus.bte.eq(0), + ram.bus.err.eq(0), + uart.bus.err.eq(0), + uart.bus.dat_r.eq(0) + ] + + return m + + +def main(): + top = Top() + output = rtlil.convert(Fragment.get(top, None), + ports=(top.clk100, top.serial_tx)) + print(output) + +if __name__ == "__main__": + main()