From 2fb418a373d754f9d67b7db252a99a055636e41a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 24 Sep 2014 21:56:15 +0200 Subject: [PATCH] use new MiSoC UART with phase accumulators this will allow to speed up MiLa reads --- miscope/uart2wishbone.py | 213 +++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 108 deletions(-) diff --git a/miscope/uart2wishbone.py b/miscope/uart2wishbone.py index 8a48ebcc..0576b258 100644 --- a/miscope/uart2wishbone.py +++ b/miscope/uart2wishbone.py @@ -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) ) -- 2.30.2