diff --git a/migen/fpga_config.py b/migen/fpga_config.py new file mode 100644 index 0000000..6d089d3 --- /dev/null +++ b/migen/fpga_config.py @@ -0,0 +1,34 @@ +from humpback import HumpbackPlatform +from migen.fhdl.module import Module + +class UrukulConnector(Module): + def __init__(self, platform): + # Request EEM I/O & SPI + eem = platform.request("eem", 1) + spi = platform.request("spi") + + # Assert signal length + assert len(eem.p) == 8 + assert len(eem.n) == 8 + assert len(spi.sclk) == 1 + assert len(spi.mosi) == 1 + assert len(spi.miso) == 1 + assert len(spi.cs) == 3 + + # Flip positive signal as negative output + self.comb += eem.n.eq(~eem.p) + + # Link EEM to SPI + self.comb += [ + eem.p[0].eq(spi.sclk), + eem.p[1].eq(spi.mosi), + eem.p[2].eq(spi.miso), + eem.p[3].eq(spi.cs[0]), + eem.p[4].eq(spi.cs[1]), + eem.p[5].eq(spi.cs[2]), + ] + + +if __name__ == "__main__": + platform = HumpbackPlatform() + platform.build(UrukulConnector(platform)) diff --git a/migen/humpback.py b/migen/humpback.py new file mode 100644 index 0000000..926727a --- /dev/null +++ b/migen/humpback.py @@ -0,0 +1,42 @@ +# Import built in I/O, Connectors & Platform template +from migen.build.platforms.sinara.humpback import _io, _connectors, Platform + +# Import migen platform for Lattice Products +from migen.build.lattice import LatticePlatform + +# Import migen pin record structure +from migen.build.generic_platform import * + +# Modify the SPI record, to include all 3 CS pins +''' + sclk -> PA5 : C8 + mosi -> PB5 : N5 + miso -> PA6 : T2 + cs_0 -> PB12: B13 + cs_1 -> PA15: B14 + cs_2 -> PC7 : B15 +''' + +# Filter out SPI record +_io = [record for record in _io if record[0] != "spi"] + +# Reinsert new SPI record +_io.append( + ("spi", 0, + Subsignal("cs" , Pins("B13 B14 B15")), + Subsignal("sclk", Pins("C8")), + Subsignal("mosi", Pins("N5")), + Subsignal("miso", Pins("T2")), + IOStandard("LVCMOS33"), + ) +) + + +# Inherit Platform to gain the programmed clock attribute +class HumpbackPlatform(Platform): + def __init__(self): + LatticePlatform.__init__(self, "ice40-hx8k-ct256", _io, _connectors, toolchain="icestorm") + +# Syntax check for direct execution +if __name__ == "__main__": + platform = HumpbackPlatform() diff --git a/nix/migen.nix b/nix/migen.nix new file mode 100644 index 0000000..e554017 --- /dev/null +++ b/nix/migen.nix @@ -0,0 +1,22 @@ +{ stdenv, fetchFromGitHub, python3Packages }: + +python3Packages.buildPythonPackage rec { + name = "migen"; + + src = fetchFromGitHub { + owner = "m-labs"; + repo = "migen"; + rev = "7bc4eb1387b39159a74c1dbd1b820728e0bfbbaa"; + sha256 = "039jk8y7f0vhr32svg3nd23i88c0bhws8ngxwk9bdznfxvhiy1h6"; + fetchSubmodules = true; + }; + + propagatedBuildInputs = with python3Packages; [ colorama ]; + + meta = with stdenv.lib; { + description = "A refreshed Python toolbox for building complex digital hardware"; + homepage = "https://m-labs.hk"; + license = licenses.bsd2; + maintainers = [ maintainers.sb0 ]; + }; +} diff --git a/nmigen/fpga_config.py b/nmigen/fpga_config.py index 3d9bf38..158c86d 100644 --- a/nmigen/fpga_config.py +++ b/nmigen/fpga_config.py @@ -6,19 +6,38 @@ from nmigen import * from humpback import * -class SimpleBlink(Elaboratable): - def elaborate(self, platform): - led = platform.request("user_led", 0) - counter = Signal(24) - pin = platform.request("gpioa", 0) +#class SimpleBlinky(Elaboratable): +# def elaborate(self, platform): +# led = platform.request("user_led", 0) +# counter = Signal(24) +# m = Module() +# m.d.sync += counter.eq(counter + 1) +# m.d.comb += led.o.eq(counter[23]) +# return m + + +# Simple connector from STM32 SPI to Humpback SPI +class UrukulConnector(Elaboratable): + def elaborate(self, platform): + # Acquire SPI slave, EEM port 1 output + spi = platform.request("spi") + print(spi) + eem = platform.request("eem", 1) + print(eem) + clk25 = platform.request("clk25") + counter = Signal(25) + + m = Module() + m.domains.sync = ClockDomain() + m.d.comb += ClockSignal().eq(clk25.i) + m.d.sync += counter.eq(counter + 1) + return m + - m = Module() - m.d.sync += counter.eq(counter + 1) - m.d.comb += led.o.eq(counter[23]) - m.d.comb += pin.o.eq(led) - return m if __name__ == "__main__": - platform = HumpbackPlatform() - platform.build(SimpleBlink(), do_program=False) + platform = HumpbackPlatform() + platform.add_resources(platform.eem_to_urukul) + platform.add_resources(platform.spi) + platform.build(UrukulConnector(), do_program=False) diff --git a/nmigen/humpback.py b/nmigen/humpback.py index cf202af..78ebdcf 100644 --- a/nmigen/humpback.py +++ b/nmigen/humpback.py @@ -285,27 +285,49 @@ class HumpbackPlatform(LatticeICE40Platform): }), ] + # Half completed, second EEM resource to be added + # Appears that DiffPairs cause build problem +# eem_to_urukul_diffpairs = [ +# Resource("eem", 1, +# Subsignal("sclk", DiffPairs("L6", "L3", dir="o")), +# Subsignal("mosi", DiffPairs("H6", "F1", dir="o")), +# Subsignal("miso", DiffPairs("H4", "G2", dir="i"), +# Attrs(IO_STANDARD="SB_LVDS_INPUT")), +# Subsignal("cs", DiffPairs("K1 J2 J4", "K3 J1 H2", dir="o")), +# Subsignal("io_update", DiffPairs("L4", "L1", dir="o")), +# Subsignal("sync_out", DiffPairs("K4", "M1", dir="o")), +# Attrs(IO_STANDARD="SB_LVCMOS") +# ) +# ] + eem_to_urukul = [ Resource("eem", 1, - Subsignal("sclk", DiffPairs("L6", "L3", dir="o", conn=("eem", 1))), - Subsignal("mosi", DiffPairs("H6", "F1", dir="o", conn=("eem", 1))), - Subsignal("miso", DiffPairs("H4", "G2", dir="i", conn=("eem", 1)), - Attrs(IO_STANDARD="SB_LVDS_INPUT")), - Subsignal("cs", DiffPairs("J4 J2 K1", "H2 J1 K3", dir="o", conn=("eem", 1))), - Subsignal("io_update", DiffPairs("L4", "L1", dir="o", conn=("eem", 1))), - Subsignal("sync_out", DiffPairs("K4", "M1", dir="o", conn=("emm", 1))), - Attrs(IO_STANDARD="SB_LVCMOS") - ) + Subsignal("sclk_p", Pins("L6", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("sclk_n", Pins("L3", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), +# Subsignal("sclk", DiffPairs("L6", "L3", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("mosi_p", Pins("H6", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("mosi_n", Pins("F1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), +# Subsignal("miso_p", Pins("H4", dir="i"), Attrs(IO_STANDARD="SB_IDK")), +# Subsignal("miso_n", Pins("G2", dir="i"), Attrs(IO_STANDARD="SB_LOL")), + Subsignal("miso", DiffPairs("H4", "G2", dir="i"), Attrs(IO_STANDARD="SB_LVDS_INPUT")), + Subsignal("cs_p", Pins("J4 J2 K1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("cs_n", Pins("H2 J1 K3", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("io_update_p", Pins("L4", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("io_update_n", Pins("L1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("sync_out_p", Pins("K4", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + Subsignal("sync_out_n", Pins("M1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")), + ), ] - # SPI Connection + # SPI Connection to Urukul, using (PD14, PA15, PC7) as connection pins spi = [ Resource("spi", 0, - Subsignal("cs", PinsN("R2", dir="i", conn=("stm32", 0))), - Subsignal("mosi", Pins("N5", dir="i", conn=("stm32", 0))), - Subsignal("miso", Pins("T2", dir="oe", conn=("stm32", 0))), - Subsignal("sck", Pins("C8", dir="i", conn=("stn32", 0))), + Subsignal("cs", Pins("R2 B14 B15", dir="i")), + Subsignal("mosi", Pins("N5", dir="i")), + Subsignal("miso", Pins("T2", dir="oe")), + Subsignal("sck", Pins("C8", dir="i"), + Attrs(GLOBAL=True)), Attrs(IO_STANDARD="SB_LVCMOS") ) ] @@ -315,11 +337,3 @@ class HumpbackPlatform(LatticeICE40Platform): iceprog = os.environ.get("ICEPROG", "iceprog") with products.extract("{}.bin".format(name)) as bitstream_filename: subprocess.check_call([iceprog, "-S", bitstream_filename]) - -if __name__ == "__main__": - from nmigen_boards.test.blinky import * - platform = HumpbackPlatform() - platform.add_resources(platform.eem_to_urukul) - platform.add_resources(platform.spi) - platform.build(Blinky(), do_program=False) - diff --git a/nmigen/resources.py b/nmigen/resources.py index 0eeb3bc..d3da795 100644 --- a/nmigen/resources.py +++ b/nmigen/resources.py @@ -1,7 +1,7 @@ from nmigen.build import * -__all__ = ["I2CResource", "GPIOResources", "DiffResources"] +__all__ = ["I2CResource"] def I2CResource(*args, sda, scl, conn=None, attrs=None, role="host"): @@ -22,6 +22,7 @@ def I2CResource(*args, sda, scl, conn=None, attrs=None, role="host"): io.append(attrs) return Resource.family(*args, default_name="i2c", ios=io) +''' # Auto create a resource list given a set of iCE40 pins and STM32 pin names (pins_dict) def GPIOResources(*args, pins_dict, dir = "o", invert=False, conn=None, attrs=None): @@ -79,8 +80,7 @@ if __name__ == "__main__": DiffResources(eem_pins = eem, dir = "o", attrs=Attrs(IO_STANDARD="SB_LVCMOS") ) - - +''' diff --git a/shell.nix b/shell.nix index b6189d7..f319c42 100644 --- a/shell.nix +++ b/shell.nix @@ -3,11 +3,13 @@ let pkgs = import {overlays = [mozillaOverlay];}; in with pkgs; let - nmigen = callPackage ./nix/nmigen.nix {}; - nmigen-boards = callPackage ./nix/nmigen-boards.nix { inherit nmigen; }; - openocd = callPackage ./nix/openocd.nix {}; - rustPlatform = callPackage ./nix/rustPlatform.nix {}; - itm = callPackage ./nix/itm.nix {inherit rustPlatform;}; + migen = callPackage ./nix/migen.nix {}; + # nMigen support for DiffPairs and IO_STANDARD="SB_LVDS_INPUT" seems questionable + nmigen = callPackage ./nix/nmigen.nix {}; + nmigen-boards = callPackage ./nix/nmigen-boards.nix { inherit nmigen; }; + openocd = callPackage ./nix/openocd.nix {}; + rustPlatform = callPackage ./nix/rustPlatform.nix {}; + itm = callPackage ./nix/itm.nix {inherit rustPlatform;}; runOpenOcd = writeShellScriptBin "run-openocd" '' openocd \ @@ -70,7 +72,7 @@ in stdenv.mkDerivation { name = "nix-shell"; buildInputs = with rustPlatform.rust; [ - (pkgs.python3.withPackages(ps: [nmigen nmigen-boards])) + (pkgs.python3.withPackages(ps: [ migen nmigen nmigen-boards])) pkgs.yosys pkgs.nextpnr pkgs.icestorm