soc/core/uart: move WishboneStreamingBridge in it and rename to Stream2Wishbone.

This commit is contained in:
Florent Kermarrec 2020-05-27 18:40:45 +02:00
parent 0a3d649ad8
commit ab80606036
2 changed files with 123 additions and 130 deletions

View File

@ -4,14 +4,17 @@
# This file is Copyright (c) 2018 Tim 'mithro' Ansell <me@mith.ro> # This file is Copyright (c) 2018 Tim 'mithro' Ansell <me@mith.ro>
# License: BSD # License: BSD
from math import log2
from migen import * from migen import *
from migen.genlib.record import Record from migen.genlib.record import Record
from migen.genlib.cdc import MultiReg from migen.genlib.cdc import MultiReg
from migen.genlib.misc import WaitTimer
from litex.soc.interconnect.csr import * from litex.soc.interconnect.csr import *
from litex.soc.interconnect.csr_eventmanager import * from litex.soc.interconnect.csr_eventmanager import *
from litex.soc.interconnect import wishbone
from litex.soc.interconnect import stream from litex.soc.interconnect import stream
from litex.soc.interconnect.wishbonebridge import WishboneStreamingBridge
# Common ------------------------------------------------------------------------------------------- # Common -------------------------------------------------------------------------------------------
@ -239,10 +242,127 @@ class UART(Module, AutoCSR, UARTInterface):
self.ev.rx.trigger.eq(~rx_fifo.source.valid) self.ev.rx.trigger.eq(~rx_fifo.source.valid)
] ]
class UARTBone(WishboneStreamingBridge): # UART Bone ----------------------------------------------------------------------------------------
CMD_WRITE = 0x01
CMD_READ = 0x02
class Stream2Wishbone(Module):
def __init__(self, phy, clk_freq, data_width=32, address_width=32):
self.wishbone = wishbone.Interface()
self.comb += phy.source.ready.eq(1) # Always accept incoming stream.
# # #
cmd = Signal(8, reset_less=True)
length = Signal(8, reset_less=True)
address = Signal(address_width, reset_less=True)
data = Signal(data_width, reset_less=True)
bytes_count = Signal(int(log2(data_width//8)), reset_less=True)
words_count = Signal(8, reset_less=True)
bytes_count_done = (bytes_count == (data_width//8 - 1))
words_count_done = (words_count == (length - 1))
fsm = ResetInserter()(FSM(reset_state="RECEIVE-CMD"))
timer = WaitTimer(int(100e-3*clk_freq))
self.comb += timer.wait.eq(~fsm.ongoing("RECEIVE-CMD"))
self.submodules += fsm, timer
self.comb += fsm.reset.eq(timer.done)
fsm.act("RECEIVE-CMD",
NextValue(bytes_count, 0),
NextValue(words_count, 0),
If(phy.source.valid,
NextValue(cmd, phy.source.data),
NextState("RECEIVE-LENGTH")
)
)
fsm.act("RECEIVE-LENGTH",
If(phy.source.valid,
NextValue(length, phy.source.data),
NextState("RECEIVE-ADDRESS")
)
)
fsm.act("RECEIVE-ADDRESS",
If(phy.source.valid,
NextValue(address, Cat(phy.source.data, address)),
NextValue(bytes_count, bytes_count + 1),
If(bytes_count_done,
If(cmd == CMD_WRITE,
NextState("RECEIVE-DATA")
).Elif(cmd == CMD_READ,
NextState("READ-DATA")
).Else(
NextState("RECEIVE-CMD")
)
)
)
)
fsm.act("RECEIVE-DATA",
If(phy.source.valid,
NextValue(data, Cat(phy.source.data, data)),
NextValue(bytes_count, bytes_count + 1),
If(bytes_count_done,
NextState("WRITE-DATA")
)
)
)
self.comb += [
self.wishbone.adr.eq(address),
self.wishbone.dat_w.eq(data),
self.wishbone.sel.eq(2**(data_width//8) - 1)
]
fsm.act("WRITE-DATA",
self.wishbone.stb.eq(1),
self.wishbone.we.eq(1),
self.wishbone.cyc.eq(1),
If(self.wishbone.ack,
NextValue(words_count, words_count + 1),
NextValue(address, address + 1),
If(words_count_done,
NextState("RECEIVE-CMD")
).Else(
NextState("RECEIVE-DATA")
)
)
)
fsm.act("READ-DATA",
self.wishbone.stb.eq(1),
self.wishbone.we.eq(0),
self.wishbone.cyc.eq(1),
If(self.wishbone.ack,
NextValue(data, self.wishbone.dat_r),
NextState("SEND-DATA")
)
)
cases = {}
for i, n in enumerate(reversed(range(data_width//8))):
cases[i] = phy.sink.data.eq(data[8*n:])
self.comb += Case(bytes_count, cases)
fsm.act("SEND-DATA",
phy.sink.valid.eq(1),
If(phy.sink.ready,
NextValue(bytes_count, bytes_count + 1),
If(bytes_count_done,
NextValue(words_count, words_count + 1),
NextValue(address, address + 1),
If(words_count_done,
NextState("RECEIVE-CMD")
).Else(
NextState("READ-DATA")
)
)
)
)
self.comb += phy.sink.last.eq(bytes_count_done & words_count_done)
if hasattr(phy.sink, "length"):
self.comb += phy.sink.length.eq((data_width//8)*length)
class UARTBone(Stream2Wishbone):
def __init__(self, pads, clk_freq, baudrate=115200): def __init__(self, pads, clk_freq, baudrate=115200):
self.submodules.phy = RS232PHY(pads, clk_freq, baudrate) self.submodules.phy = RS232PHY(pads, clk_freq, baudrate)
WishboneStreamingBridge.__init__(self, self.phy, clk_freq) Stream2Wishbone.__init__(self, self.phy, clk_freq)
class UARTWishboneBridge(UARTBone): pass class UARTWishboneBridge(UARTBone): pass

View File

@ -1,127 +0,0 @@
# This file is Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
from math import log2
from migen import *
from migen.genlib.misc import WaitTimer
from litex.soc.interconnect import wishbone
from litex.soc.interconnect import stream
# Wishbone Streaming Bridge ------------------------------------------------------------------------
CMD_WRITE = 0x01
CMD_READ = 0x02
class WishboneStreamingBridge(Module):
def __init__(self, phy, clk_freq, data_width=32, address_width=32):
self.wishbone = wishbone.Interface()
self.comb += phy.source.ready.eq(1) # Always accept incoming stream.
# # #
cmd = Signal(8, reset_less=True)
length = Signal(8, reset_less=True)
address = Signal(address_width, reset_less=True)
data = Signal(data_width, reset_less=True)
bytes_count = Signal(int(log2(data_width//8)), reset_less=True)
words_count = Signal(8, reset_less=True)
bytes_count_done = (bytes_count == (data_width//8 - 1))
words_count_done = (words_count == (length - 1))
fsm = ResetInserter()(FSM(reset_state="RECEIVE-CMD"))
timer = WaitTimer(int(100e-3*clk_freq))
self.comb += timer.wait.eq(~fsm.ongoing("RECEIVE-CMD"))
self.submodules += fsm, timer
self.comb += fsm.reset.eq(timer.done)
fsm.act("RECEIVE-CMD",
NextValue(bytes_count, 0),
NextValue(words_count, 0),
If(phy.source.valid,
NextValue(cmd, phy.source.data),
NextState("RECEIVE-LENGTH")
)
)
fsm.act("RECEIVE-LENGTH",
If(phy.source.valid,
NextValue(length, phy.source.data),
NextState("RECEIVE-ADDRESS")
)
)
fsm.act("RECEIVE-ADDRESS",
If(phy.source.valid,
NextValue(address, Cat(phy.source.data, address)),
NextValue(bytes_count, bytes_count + 1),
If(bytes_count_done,
If(cmd == CMD_WRITE,
NextState("RECEIVE-DATA")
).Elif(cmd == CMD_READ,
NextState("READ-DATA")
).Else(
NextState("RECEIVE-CMD")
)
)
)
)
fsm.act("RECEIVE-DATA",
If(phy.source.valid,
NextValue(data, Cat(phy.source.data, data)),
NextValue(bytes_count, bytes_count + 1),
If(bytes_count_done,
NextState("WRITE-DATA")
)
)
)
self.comb += [
self.wishbone.adr.eq(address),
self.wishbone.dat_w.eq(data),
self.wishbone.sel.eq(2**(data_width//8) - 1)
]
fsm.act("WRITE-DATA",
self.wishbone.stb.eq(1),
self.wishbone.we.eq(1),
self.wishbone.cyc.eq(1),
If(self.wishbone.ack,
NextValue(words_count, words_count + 1),
NextValue(address, address + 1),
If(words_count_done,
NextState("RECEIVE-CMD")
).Else(
NextState("RECEIVE-DATA")
)
)
)
fsm.act("READ-DATA",
self.wishbone.stb.eq(1),
self.wishbone.we.eq(0),
self.wishbone.cyc.eq(1),
If(self.wishbone.ack,
NextValue(data, self.wishbone.dat_r),
NextState("SEND-DATA")
)
)
cases = {}
for i, n in enumerate(reversed(range(data_width//8))):
cases[i] = phy.sink.data.eq(data[8*n:])
self.comb += Case(bytes_count, cases)
fsm.act("SEND-DATA",
phy.sink.valid.eq(1),
If(phy.sink.ready,
NextValue(bytes_count, bytes_count + 1),
If(bytes_count_done,
NextValue(words_count, words_count + 1),
NextValue(address, address + 1),
If(words_count_done,
NextState("RECEIVE-CMD")
).Else(
NextState("READ-DATA")
)
)
)
)
self.comb += phy.sink.last.eq(bytes_count_done & words_count_done)
if hasattr(phy.sink, "length"):
self.comb += phy.sink.length.eq((data_width//8)*length)