diff --git a/default.nix b/default.nix index 9c279ca..0edaf2c 100644 --- a/default.nix +++ b/default.nix @@ -1,6 +1,7 @@ { pkgs ? import {}}: rec { - nmigen = pkgs.callPackage ./nmigen.nix {}; - jtagtap = pkgs.callPackage ./jtagtap.nix { inherit nmigen; }; - minerva = pkgs.callPackage ./minerva.nix { inherit nmigen; inherit jtagtap; }; + nmigen = pkgs.callPackage ./nmigen.nix {}; + jtagtap = pkgs.callPackage ./jtagtap.nix { inherit nmigen; }; + minerva = pkgs.callPackage ./minerva.nix { inherit nmigen; inherit jtagtap; }; + heavycomps = pkgs.callPackage ./heavycomps.nix { inherit nmigen; }; } diff --git a/heavycomps.nix b/heavycomps.nix new file mode 100644 index 0000000..4442112 --- /dev/null +++ b/heavycomps.nix @@ -0,0 +1,16 @@ +{ stdenv, python3Packages, nmigen }: + +python3Packages.buildPythonPackage { + name = "heavycomps"; + + src = ./heavycomps; + + propagatedBuildInputs = [ nmigen ]; + + meta = with stdenv.lib; { + description = "Components for the HeavyX SoC toolkit"; + homepage = "https://m-labs.hk/migen"; + license = licenses.bsd2; + maintainers = [ maintainers.sb0 ]; + }; +} diff --git a/heavycomps/heavycomps/__init__.py b/heavycomps/heavycomps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/heavycomps/heavycomps/uart.py b/heavycomps/heavycomps/uart.py new file mode 100644 index 0000000..b4195ba --- /dev/null +++ b/heavycomps/heavycomps/uart.py @@ -0,0 +1,110 @@ +from nmigen import * +from nmigen.lib.cdc import MultiReg +from nmigen.cli import main + + +class RS232RX: + def __init__(self, tuning_word): + self.rx = Signal() + self.data = Signal(8) + self.stb = Signal() + self.tuning_word = tuning_word + + def elaborate(self, platform): + m = Module() + + uart_clk_rxen = Signal() + phase_accumulator_rx = Signal(32) + + rx = Signal() + m.submodules += MultiReg(self.rx, rx) + rx_r = Signal() + rx_reg = Signal(8) + rx_bitcount = Signal(4) + rx_busy = Signal() + rx_done = self.stb + rx_data = self.data + m.d.sync += rx_done.eq(0) + m.d.sync += rx_r.eq(rx) + with m.If(~rx_busy): + with m.If(~rx & rx_r): # look for start bit + m.d.sync += rx_busy.eq(1) + m.d.sync += rx_bitcount.eq(0) + with m.Else(): + with m.If(uart_clk_rxen): + m.d.sync += rx_bitcount.eq(rx_bitcount + 1) + with m.If(rx_bitcount == 0): + with m.If(rx): # verify start bit + m.d.sync += rx_busy.eq(0) + with m.Elif(rx_bitcount == 9): + m.d.sync += rx_busy.eq(0) + with m.If(rx): # verify stop bit + m.d.sync += rx_data.eq(rx_reg) + m.d.sync += rx_done.eq(1) + with m.Else(): + m.d.sync += rx_reg.eq(Cat(rx_reg[1:], rx)) + with m.If(rx_busy): + m.d.sync += Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + self.tuning_word) + with m.Else(): + m.d.sync += Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31) + + return m + + +class RS232TX: + def __init__(self, tuning_word): + self.tx = Signal(reset=1) + self.data = Signal(8) + self.stb = Signal() + self.ack = Signal() + self.tuning_word = tuning_word + + def elaborate(self, platform): + m = Module() + + uart_clk_txen = Signal() + phase_accumulator_tx = Signal(32) + + tx_reg = Signal(8) + tx_bitcount = Signal(4) + tx_busy = Signal() + m.d.sync += self.ack.eq(0), + with m.If(self.stb & ~tx_busy & ~self.ack): + m.d.sync += tx_reg.eq(self.data) + m.d.sync += tx_bitcount.eq(0) + m.d.sync += tx_busy.eq(1) + m.d.sync += self.tx.eq(0) + with m.Elif(uart_clk_txen & tx_busy): + m.d.sync += tx_bitcount.eq(tx_bitcount + 1) + with m.If(tx_bitcount == 8): + m.d.sync += self.tx.eq(1) + with m.Elif(tx_bitcount == 9): + m.d.sync += self.tx.eq(1) + m.d.sync += tx_busy.eq(0) + m.d.sync += self.ack.eq(1), + with m.Else(): + m.d.sync += self.tx.eq(tx_reg[0]) + m.d.sync += tx_reg.eq(Cat(tx_reg[1:], 0)) + with m.If(tx_busy): + m.d.sync += Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + self.tuning_word) + with m.Else(): + m.d.sync += Cat(phase_accumulator_tx, uart_clk_txen).eq(0) + + return m + + +class Loopback: + def elaborate(self, platform): + m = Module() + tuning_word = 2**31 + tx = RS232TX(tuning_word) + rx = RS232RX(tuning_word) + m.submodules += tx, rx + m.d.comb += rx.rx.eq(tx.tx) + m.d.comb += tx.data.eq(42) + m.d.comb += tx.stb.eq(1) + return m + +if __name__ == "__main__": + uart = Loopback() + main(uart) diff --git a/heavycomps/setup.py b/heavycomps/setup.py new file mode 100644 index 0000000..63af452 --- /dev/null +++ b/heavycomps/setup.py @@ -0,0 +1,7 @@ +from setuptools import setup, find_packages + +setup( + name="heavycomps", + install_requires=["nmigen"], + packages=find_packages() +)