Nmigen UART Notes

I’ve been stumbling my way through nmigen. As I slowly figure things out, I’m dumping my notes here in case they prove useful…

The following is for the ICE40 HX8K evaluation board. It uses the uart.py example from the nmigen repository. The code will write bursts of a’s at 9600bps.

#!/usr/bin/python3

from nmigen import *
from uart import *
from nmigen_boards.ice40_hx8k_b_evn import *

class Top(Elaboratable):

    def elaborate(self, platform):

        m = Module()
        timer = Signal(26)

        #Connect TX to B12
        muart = platform.request('uart')

        m.d.sync += [
            timer.eq(timer + 1)
        ]

        uart = UART(divisor=1250)
        uart.tx_o = muart.tx

        m.d.comb += [
            uart.tx_data.eq(0x61),
            uart.tx_rdy.eq(timer[-1])
        ]

        m.submodules += [uart]

        return m

if __name__ == '__main__':
    platform = ICE40HX8KBEVNPlatform()

    platform.build(Top(), do_program=True)

This code sets tx_rdy high based on a counter. This means that tx_rdy stays high for multiple clock cycles. And as I understand it, the uart will continue to output for this period. The code above is available in this tarball.

The following code uses the uart to write data from some pins on the header of the ICE40 HX8K evaluation board. It adds 0x60 to the value from these pins so low values are in a readable range. A counter is used to set the UART ready signal high once every ~0.7s. There’s probably a better way of doing this… the code is also available in the tarball here.

#!/usr/bin/python3

from nmigen import *
from uart import *
from nmigen_boards.ice40_hx8k_b_evn import *
from nmigen.build import *

class Top(Elaboratable):

    def elaborate(self, platform):
        inpins = [ Resource("inpins", 0, Pins("B1 B2 C1 C2 D1 D2 E2 F1"), Attrs(IO_STANDARD="SB_LVCMOS")) ]
        platform.add_resources(inpins)

        m = Module()

        timer = Signal(24)

        #Connect TX to B12
        led0 = platform.request('led', 0)
        muart = platform.request('uart')
        data  = platform.request('inpins',0)
        dataA = Signal(8)
        rdy   = Signal(1)

        with m.If(timer[-1]):
            m.d.sync += [
              rdy.eq(1),
              timer.eq(0)
            ]
        with m.Else():
            m.d.sync += [
                timer.eq(timer + 1)
            ]

        with m.If(rdy == 1):
            m.d.sync += [
                rdy.eq(0)
            ]

        m.d.sync += [
            dataA.eq(data.i[0:8] + 0x60)
        ]

        m.d.comb += [
            led0.eq(timer[-1])
        ]

        # UART
        uart = UART(divisor=1250)
        uart.tx_o = muart.tx


        m.d.comb += [
            uart.tx_data.eq(dataA),
            uart.tx_rdy.eq(rdy)
        ]

        m.submodules += [uart]

        return m

if __name__ == '__main__':
    platform = ICE40HX8KBEVNPlatform()
    platform.build(Top(), do_program=True)