use new MiSoC UART with phase accumulators
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 24 Sep 2014 19:56:15 +0000 (21:56 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 24 Sep 2014 19:56:15 +0000 (21:56 +0200)
this will allow to speed up MiLa reads

miscope/uart2wishbone.py

index 8a48ebcc8b5a9d27b767d6ecb2d0bf79054345f7..0576b2581512363031ba90f8caf29d723728a378 100644 (file)
@@ -6,117 +6,114 @@ from migen.genlib.fsm import FSM, NextState
 from migen.genlib.misc import split, displacer, chooser
 from migen.bank.description import *
 from migen.bus import wishbone
+from migen.flow.actor import Sink, Source
 
-def rx_layout():
-       return [
-                       ("stb", 1, DIR_M_TO_S),
-                       ("dat", 8, DIR_M_TO_S)
-       ]
+class UARTRX(Module):
+       def __init__(self, pads, tuning_word):
+               self.source = Source([("d", 8)])
 
-def tx_layout():
-       return [
-                       ("stb", 1, DIR_M_TO_S),
-                       ("ack", 1, DIR_S_TO_M),
-                       ("dat", 8, DIR_M_TO_S)
-       ]
+               ###
 
-class UART(Module):
-       def __init__(self, pads, clk_freq, baud=115200):
-               self.rx = Record(rx_layout())
-               self.tx = Record(tx_layout())
+               uart_clk_rxen = Signal()
+               phase_accumulator_rx = Signal(32)
 
-               self.divisor = Signal(16, reset=int(clk_freq/baud/16))
+               rx = Signal()
+               self.specials += MultiReg(pads.rx, rx)
+               rx_r = Signal()
+               rx_reg = Signal(8)
+               rx_bitcount = Signal(4)
+               rx_busy = Signal()
+               rx_done = self.source.stb
+               rx_data = self.source.payload.d
+               self.sync += [
+                       rx_done.eq(0),
+                       rx_r.eq(rx),
+                       If(~rx_busy,
+                               If(~rx & rx_r, # look for start bit
+                                       rx_busy.eq(1),
+                                       rx_bitcount.eq(0),
+                               )
+                       ).Else(
+                               If(uart_clk_rxen,
+                                       rx_bitcount.eq(rx_bitcount + 1),
+                                       If(rx_bitcount == 0,
+                                               If(rx, # verify start bit
+                                                       rx_busy.eq(0)
+                                               )
+                                       ).Elif(rx_bitcount == 9,
+                                               rx_busy.eq(0),
+                                               If(rx, # verify stop bit
+                                                       rx_data.eq(rx_reg),
+                                                       rx_done.eq(1)
+                                               )
+                                       ).Else(
+                                               rx_reg.eq(Cat(rx_reg[1:], rx))
+                                       )
+                               )
+                       )
+               ]
+               self.sync += \
+                               If(rx_busy,
+                                       Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
+                               ).Else(
+                                       Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
+                               )
 
-               pads.tx.reset = 1
+class UARTTX(Module):
+       def __init__(self, pads, tuning_word):
+               self.sink = Sink([("d", 8)])
 
                ###
 
-               enable16 = Signal()
-               enable16_counter = Signal(16)
-               self.comb += enable16.eq(enable16_counter == 0)
-               self.sync += [
-                       enable16_counter.eq(enable16_counter - 1),
-                       If(enable16,
-                               enable16_counter.eq(self.divisor - 1))
-               ]
+               uart_clk_txen = Signal()
+               phase_accumulator_tx = Signal(32)
+
+               pads.tx.reset = 1
 
-               # TX
                tx_reg = Signal(8)
                tx_bitcount = Signal(4)
-               tx_count16 = Signal(4)
-               tx_done = self.tx.ack
                tx_busy = Signal()
-               tx_stb_d = Signal()
                self.sync += [
-                       tx_stb_d.eq(self.tx.stb & ~tx_done),
-                       tx_done.eq(0),
-                       If(self.tx.stb & ~tx_stb_d,
-                               tx_reg.eq(self.tx.dat),
+                       self.sink.ack.eq(0),
+                       If(self.sink.stb & ~tx_busy & ~self.sink.ack,
+                               tx_reg.eq(self.sink.payload.d),
                                tx_bitcount.eq(0),
-                               tx_count16.eq(1),
                                tx_busy.eq(1),
                                pads.tx.eq(0)
-                       ).Elif(enable16 & tx_busy,
-                               tx_count16.eq(tx_count16 + 1),
-                               If(tx_count16 == 0,
-                                       tx_bitcount.eq(tx_bitcount + 1),
-                                       If(tx_bitcount == 8,
-                                               pads.tx.eq(1)
-                                       ).Elif(tx_bitcount == 9,
-                                               pads.tx.eq(1),
-                                               tx_busy.eq(0),
-                                               tx_done.eq(1)
-                                       ).Else(
-                                               pads.tx.eq(tx_reg[0]),
-                                               tx_reg.eq(Cat(tx_reg[1:], 0))
-                                       )
+                       ).Elif(uart_clk_txen & tx_busy,
+                               tx_bitcount.eq(tx_bitcount + 1),
+                               If(tx_bitcount == 8,
+                                       pads.tx.eq(1)
+                               ).Elif(tx_bitcount == 9,
+                                       pads.tx.eq(1),
+                                       tx_busy.eq(0),
+                                       self.sink.ack.eq(1),
+                               ).Else(
+                                       pads.tx.eq(tx_reg[0]),
+                                       tx_reg.eq(Cat(tx_reg[1:], 0))
                                )
                        )
                ]
-
-               # RX
-               rx = Signal()
-               self.specials += MultiReg(pads.rx, rx, "sys")
-               rx_r = Signal()
-               rx_reg = Signal(8)
-               rx_bitcount = Signal(4)
-               rx_count16 = Signal(4)
-               rx_busy = Signal()
-               rx_done = self.rx.stb
-               rx_data = self.rx.dat
                self.sync += [
-                       rx_done.eq(0),
-                       If(enable16,
-                               rx_r.eq(rx),
-                               If(~rx_busy,
-                                       If(~rx & rx_r, # look for start bit
-                                               rx_busy.eq(1),
-                                               rx_count16.eq(7),
-                                               rx_bitcount.eq(0)
-                                       )
+                               If(tx_busy,
+                                       Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
                                ).Else(
-                                       rx_count16.eq(rx_count16 + 1),
-                                       If(rx_count16 == 0,
-                                               rx_bitcount.eq(rx_bitcount + 1),
-
-                                               If(rx_bitcount == 0,
-                                                       If(rx, # verify start bit
-                                                               rx_busy.eq(0)
-                                                       )
-                                               ).Elif(rx_bitcount == 9,
-                                                       rx_busy.eq(0),
-                                                       If(rx, # verify stop bit
-                                                               rx_data.eq(rx_reg),
-                                                               rx_done.eq(1)
-                                                       )
-                                               ).Else(
-                                                       rx_reg.eq(Cat(rx_reg[1:], rx))
-                                               )
-                                       )
+                                       Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
                                )
-                       )
                ]
 
+class UART(Module, AutoCSR):
+       def __init__(self, pads, clk_freq, baud=115200):
+
+               # Tuning word value
+               self._tuning_word = CSRStorage(32, reset=int((baud/clk_freq)*2**32))
+               tuning_word = self._tuning_word.storage
+
+               ###
+
+               self.submodules.rx = UARTRX(pads, tuning_word)
+               self.submodules.tx = UARTTX(pads, tuning_word)
+
 class Counter(Module):
        def __init__(self, width):
                self.value = Signal(width)
@@ -141,7 +138,7 @@ class UARTMux(Module):
                self.shared_pads = UARTPads()
                self.bridge_pads = UARTPads()
 
-       ###     
+       ###
                # Route rx pad:
                # when sel==0, route it to shared rx and bridge rx
                # when sel==1, route it only to bridge rx
@@ -167,7 +164,7 @@ class UART2Wishbone(Module, AutoCSR):
        WRITE_CMD = 0x01
        READ_CMD = 0x02
        def __init__(self, pads, clk_freq, baud=115200, share_uart=False):
-               
+
                # Wishbone interface
                self.wishbone = wishbone.Interface()
                if share_uart:
@@ -194,34 +191,34 @@ class UART2Wishbone(Module, AutoCSR):
                ###
                cmd = Signal(8)
                fsm.act("WAIT_CMD",
-                       If(uart.rx.stb,
-                               If(     (uart.rx.dat == self.WRITE_CMD) |
-                                       (uart.rx.dat == self.READ_CMD),
+                       If(uart.rx.source.stb,
+                               If(     (uart.rx.source.payload.d == self.WRITE_CMD) |
+                                       (uart.rx.source.payload.d == self.READ_CMD),
                                        NextState("RECEIVE_BURST_LENGTH")
                                ),
                        word_cnt.clr.eq(1),
                        burst_cnt.clr.eq(1)
                        )
                )
-               self.sync += If(fsm.ongoing("WAIT_CMD") & uart.rx.stb, cmd.eq(uart.rx.dat))
+               self.sync += If(fsm.ongoing("WAIT_CMD") & uart.rx.source.stb, cmd.eq(uart.rx.source.d))
 
                ####
                burst_length = Signal(8)
                fsm.act("RECEIVE_BURST_LENGTH",
-                       word_cnt.inc.eq(uart.rx.stb),
-                       If(word_cnt.value == 1, 
+                       word_cnt.inc.eq(uart.rx.source.stb),
+                       If(word_cnt.value == 1,
                                word_cnt.clr.eq(1),
                                NextState("RECEIVE_ADDRESS")
                        )
                )
                self.sync += \
-                       If(fsm.ongoing("RECEIVE_BURST_LENGTH") & uart.rx.stb, burst_length.eq(uart.rx.dat)) 
+                       If(fsm.ongoing("RECEIVE_BURST_LENGTH") & uart.rx.source.stb, burst_length.eq(uart.rx.source.d))
 
                ####
                address = Signal(32)
                fsm.act("RECEIVE_ADDRESS",
-                       word_cnt.inc.eq(uart.rx.stb),
-                       If(word_cnt.value == 4, 
+                       word_cnt.inc.eq(uart.rx.source.stb),
+                       If(word_cnt.value == 4,
                                word_cnt.clr.eq(1),
                                If(cmd == self.WRITE_CMD,
                                        NextState("RECEIVE_DATA")
@@ -231,8 +228,8 @@ class UART2Wishbone(Module, AutoCSR):
                        )
                )
                self.sync += \
-                       If(fsm.ongoing("RECEIVE_ADDRESS") & uart.rx.stb,
-                                       address.eq(Cat(uart.rx.dat, address[0:24]))
+                       If(fsm.ongoing("RECEIVE_ADDRESS") & uart.rx.source.stb,
+                                       address.eq(Cat(uart.rx.source.d, address[0:24]))
                        )
 
                ###
@@ -240,8 +237,8 @@ class UART2Wishbone(Module, AutoCSR):
 
                ###
                fsm.act("RECEIVE_DATA",
-                       word_cnt.inc.eq(uart.rx.stb),
-                       If(word_cnt.value == 4, 
+                       word_cnt.inc.eq(uart.rx.source.stb),
+                       If(word_cnt.value == 4,
                                word_cnt.clr.eq(1),
                                NextState("WRITE_DATA")
                        )
@@ -279,8 +276,8 @@ class UART2Wishbone(Module, AutoCSR):
                )
 
                fsm.act("SEND_DATA",
-                       word_cnt.inc.eq(uart.tx.ack),
-                       If(word_cnt.value == 4, 
+                       word_cnt.inc.eq(uart.tx.sink.ack),
+                       If(word_cnt.value == 4,
                                burst_cnt.inc.eq(1),
                                If(burst_cnt.value == (burst_length-1),
                                        NextState("WAIT_CMD")
@@ -288,14 +285,14 @@ class UART2Wishbone(Module, AutoCSR):
                                        NextState("READ_DATA")
                                )
                        ),
-                       uart.tx.stb.eq(1),
-                       chooser(data, word_cnt.value, uart.tx.dat, n=4, reverse=True)
+                       uart.tx.sink.stb.eq(1),
+                       chooser(data, word_cnt.value, uart.tx.sink.d, n=4, reverse=True)
                )
 
                ###
                self.sync += \
-                       If(fsm.ongoing("RECEIVE_DATA") & uart.rx.stb,
-                               data.eq(Cat(uart.rx.dat, data[0:24]))
+                       If(fsm.ongoing("RECEIVE_DATA") & uart.rx.source.stb,
+                               data.eq(Cat(uart.rx.source.d, data[0:24]))
                        ).Elif(fsm.ongoing("READ_DATA") & self.wishbone.stb & self.wishbone.ack,
                                data.eq(self.wishbone.dat_r)
                        )