use new MiSoC UART with phase accumulators

this will allow to speed up MiLa reads
This commit is contained in:
Florent Kermarrec 2014-09-24 21:56:15 +02:00
parent 452a4a76f3
commit 2fb418a373

View file

@ -6,99 +6,36 @@ from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import split, displacer, chooser from migen.genlib.misc import split, displacer, chooser
from migen.bank.description import * from migen.bank.description import *
from migen.bus import wishbone from migen.bus import wishbone
from migen.flow.actor import Sink, Source
def rx_layout(): class UARTRX(Module):
return [ def __init__(self, pads, tuning_word):
("stb", 1, DIR_M_TO_S), self.source = Source([("d", 8)])
("dat", 8, DIR_M_TO_S)
]
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())
self.divisor = Signal(16, reset=int(clk_freq/baud/16))
pads.tx.reset = 1
### ###
enable16 = Signal() uart_clk_rxen = Signal()
enable16_counter = Signal(16) phase_accumulator_rx = Signal(32)
self.comb += enable16.eq(enable16_counter == 0)
self.sync += [
enable16_counter.eq(enable16_counter - 1),
If(enable16,
enable16_counter.eq(self.divisor - 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),
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))
)
)
)
]
# RX
rx = Signal() rx = Signal()
self.specials += MultiReg(pads.rx, rx, "sys") self.specials += MultiReg(pads.rx, rx)
rx_r = Signal() rx_r = Signal()
rx_reg = Signal(8) rx_reg = Signal(8)
rx_bitcount = Signal(4) rx_bitcount = Signal(4)
rx_count16 = Signal(4)
rx_busy = Signal() rx_busy = Signal()
rx_done = self.rx.stb rx_done = self.source.stb
rx_data = self.rx.dat rx_data = self.source.payload.d
self.sync += [ self.sync += [
rx_done.eq(0), rx_done.eq(0),
If(enable16,
rx_r.eq(rx), rx_r.eq(rx),
If(~rx_busy, If(~rx_busy,
If(~rx & rx_r, # look for start bit If(~rx & rx_r, # look for start bit
rx_busy.eq(1), rx_busy.eq(1),
rx_count16.eq(7), rx_bitcount.eq(0),
rx_bitcount.eq(0)
) )
).Else( ).Else(
rx_count16.eq(rx_count16 + 1), If(uart_clk_rxen,
If(rx_count16 == 0,
rx_bitcount.eq(rx_bitcount + 1), rx_bitcount.eq(rx_bitcount + 1),
If(rx_bitcount == 0, If(rx_bitcount == 0,
If(rx, # verify start bit If(rx, # verify start bit
rx_busy.eq(0) rx_busy.eq(0)
@ -114,8 +51,68 @@ class UART(Module):
) )
) )
) )
]
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)
)
class UARTTX(Module):
def __init__(self, pads, tuning_word):
self.sink = Sink([("d", 8)])
###
uart_clk_txen = Signal()
phase_accumulator_tx = Signal(32)
pads.tx.reset = 1
tx_reg = Signal(8)
tx_bitcount = Signal(4)
tx_busy = Signal()
self.sync += [
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_busy.eq(1),
pads.tx.eq(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))
)
) )
] ]
self.sync += [
If(tx_busy,
Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
).Else(
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): class Counter(Module):
def __init__(self, width): def __init__(self, width):
@ -194,33 +191,33 @@ class UART2Wishbone(Module, AutoCSR):
### ###
cmd = Signal(8) cmd = Signal(8)
fsm.act("WAIT_CMD", fsm.act("WAIT_CMD",
If(uart.rx.stb, If(uart.rx.source.stb,
If( (uart.rx.dat == self.WRITE_CMD) | If( (uart.rx.source.payload.d == self.WRITE_CMD) |
(uart.rx.dat == self.READ_CMD), (uart.rx.source.payload.d == self.READ_CMD),
NextState("RECEIVE_BURST_LENGTH") NextState("RECEIVE_BURST_LENGTH")
), ),
word_cnt.clr.eq(1), word_cnt.clr.eq(1),
burst_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) burst_length = Signal(8)
fsm.act("RECEIVE_BURST_LENGTH", fsm.act("RECEIVE_BURST_LENGTH",
word_cnt.inc.eq(uart.rx.stb), word_cnt.inc.eq(uart.rx.source.stb),
If(word_cnt.value == 1, If(word_cnt.value == 1,
word_cnt.clr.eq(1), word_cnt.clr.eq(1),
NextState("RECEIVE_ADDRESS") NextState("RECEIVE_ADDRESS")
) )
) )
self.sync += \ 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) address = Signal(32)
fsm.act("RECEIVE_ADDRESS", fsm.act("RECEIVE_ADDRESS",
word_cnt.inc.eq(uart.rx.stb), word_cnt.inc.eq(uart.rx.source.stb),
If(word_cnt.value == 4, If(word_cnt.value == 4,
word_cnt.clr.eq(1), word_cnt.clr.eq(1),
If(cmd == self.WRITE_CMD, If(cmd == self.WRITE_CMD,
@ -231,8 +228,8 @@ class UART2Wishbone(Module, AutoCSR):
) )
) )
self.sync += \ self.sync += \
If(fsm.ongoing("RECEIVE_ADDRESS") & uart.rx.stb, If(fsm.ongoing("RECEIVE_ADDRESS") & uart.rx.source.stb,
address.eq(Cat(uart.rx.dat, address[0:24])) address.eq(Cat(uart.rx.source.d, address[0:24]))
) )
### ###
@ -240,7 +237,7 @@ class UART2Wishbone(Module, AutoCSR):
### ###
fsm.act("RECEIVE_DATA", fsm.act("RECEIVE_DATA",
word_cnt.inc.eq(uart.rx.stb), word_cnt.inc.eq(uart.rx.source.stb),
If(word_cnt.value == 4, If(word_cnt.value == 4,
word_cnt.clr.eq(1), word_cnt.clr.eq(1),
NextState("WRITE_DATA") NextState("WRITE_DATA")
@ -279,7 +276,7 @@ class UART2Wishbone(Module, AutoCSR):
) )
fsm.act("SEND_DATA", fsm.act("SEND_DATA",
word_cnt.inc.eq(uart.tx.ack), word_cnt.inc.eq(uart.tx.sink.ack),
If(word_cnt.value == 4, If(word_cnt.value == 4,
burst_cnt.inc.eq(1), burst_cnt.inc.eq(1),
If(burst_cnt.value == (burst_length-1), If(burst_cnt.value == (burst_length-1),
@ -288,14 +285,14 @@ class UART2Wishbone(Module, AutoCSR):
NextState("READ_DATA") NextState("READ_DATA")
) )
), ),
uart.tx.stb.eq(1), uart.tx.sink.stb.eq(1),
chooser(data, word_cnt.value, uart.tx.dat, n=4, reverse=True) chooser(data, word_cnt.value, uart.tx.sink.d, n=4, reverse=True)
) )
### ###
self.sync += \ self.sync += \
If(fsm.ongoing("RECEIVE_DATA") & uart.rx.stb, If(fsm.ongoing("RECEIVE_DATA") & uart.rx.source.stb,
data.eq(Cat(uart.rx.dat, data[0:24])) data.eq(Cat(uart.rx.source.d, data[0:24]))
).Elif(fsm.ongoing("READ_DATA") & self.wishbone.stb & self.wishbone.ack, ).Elif(fsm.ongoing("READ_DATA") & self.wishbone.stb & self.wishbone.ack,
data.eq(self.wishbone.dat_r) data.eq(self.wishbone.dat_r)
) )