frontend/fifo: Simplify code and expose pre/post fifo_depth instead of writer/reader_fifo_depth.

This commit is contained in:
Florent Kermarrec 2021-09-24 09:52:24 +02:00
parent 3d3bf623aa
commit b24381ca4a
1 changed files with 36 additions and 41 deletions

View File

@ -77,7 +77,7 @@ class _LiteDRAMFIFOCtrl(Module):
# LiteDRAMFIFOWriter ------------------------------------------------------------------------------- # LiteDRAMFIFOWriter -------------------------------------------------------------------------------
class _LiteDRAMFIFOWriter(Module): class _LiteDRAMFIFOWriter(Module):
def __init__(self, data_width, port, ctrl, fifo_depth=32): def __init__(self, data_width, port, ctrl, fifo_depth=16):
self.sink = sink = stream.Endpoint([("data", data_width)]) self.sink = sink = stream.Endpoint([("data", data_width)])
# # # # # #
@ -98,7 +98,7 @@ class _LiteDRAMFIFOWriter(Module):
# LiteDRAMFIFOReader ------------------------------------------------------------------------------- # LiteDRAMFIFOReader -------------------------------------------------------------------------------
class _LiteDRAMFIFOReader(Module): class _LiteDRAMFIFOReader(Module):
def __init__(self, data_width, port, ctrl, fifo_depth=32): def __init__(self, data_width, port, ctrl, fifo_depth=16):
self.source = source = stream.Endpoint([("data", data_width)]) self.source = source = stream.Endpoint([("data", data_width)])
# # # # # #
@ -118,8 +118,8 @@ class _LiteDRAMFIFOReader(Module):
class _LiteDRAMFIFO(Module): class _LiteDRAMFIFO(Module):
"""LiteDRAM frontend that allows to use DRAM as a FIFO""" """LiteDRAM frontend that allows to use DRAM as a FIFO"""
def __init__(self, data_width, base, depth, write_port, read_port, def __init__(self, data_width, base, depth, write_port, read_port,
writer_fifo_depth = 32, writer_fifo_depth = 16,
reader_fifo_depth = 32): reader_fifo_depth = 16):
assert isinstance(write_port, LiteDRAMNativePort) assert isinstance(write_port, LiteDRAMNativePort)
assert isinstance(read_port, LiteDRAMNativePort) assert isinstance(read_port, LiteDRAMNativePort)
self.sink = stream.Endpoint([("data", data_width)]) self.sink = stream.Endpoint([("data", data_width)])
@ -213,8 +213,8 @@ class LiteDRAMFIFO(Module):
level is below threshold, the modules switches back to Bypass mode. level is below threshold, the modules switches back to Bypass mode.
""" """
def __init__(self, data_width, base, depth, write_port, read_port, with_bypass=False, def __init__(self, data_width, base, depth, write_port, read_port, with_bypass=False,
writer_fifo_depth = 32, pre_fifo_depth = 16,
reader_fifo_depth = 32): post_fifo_depth = 16):
assert isinstance(write_port, LiteDRAMNativePort) assert isinstance(write_port, LiteDRAMNativePort)
assert isinstance(read_port, LiteDRAMNativePort) assert isinstance(read_port, LiteDRAMNativePort)
self.sink = stream.Endpoint([("data", data_width)]) self.sink = stream.Endpoint([("data", data_width)])
@ -230,8 +230,8 @@ class LiteDRAMFIFO(Module):
data_width_ratio = port_data_width//data_width data_width_ratio = port_data_width//data_width
if not with_bypass: if not with_bypass:
assert data_width_ratio == 1 assert data_width_ratio == 1
pre_fifo_depth = 2*data_width_ratio # FIXME: Adjust. pre_fifo_depth = max( pre_fifo_depth, 2*data_width_ratio)
post_fifo_depth = 2*data_width_ratio # FIXME: Adjust. post_fifo_depth = max(post_fifo_depth, 2*data_width_ratio)
# Submodules. # Submodules.
# ----------- # -----------
@ -243,13 +243,11 @@ class LiteDRAMFIFO(Module):
# DRAM-FIFO. # DRAM-FIFO.
self.submodules.dram_fifo = dram_fifo = _LiteDRAMFIFO( self.submodules.dram_fifo = dram_fifo = _LiteDRAMFIFO(
data_width = port_data_width, data_width = port_data_width,
base = base, base = base,
depth = depth, depth = depth,
write_port = write_port, write_port = write_port,
read_port = read_port, read_port = read_port,
writer_fifo_depth = writer_fifo_depth,
reader_fifo_depth = reader_fifo_depth,
) )
# Post-Converter. # Post-Converter.
@ -260,20 +258,24 @@ class LiteDRAMFIFO(Module):
# Data-Flow. # Data-Flow.
# ---------- # ----------
bypass = Signal() dram_bypass = Signal()
store = Signal() dram_store = Signal()
count = Signal(8) dram_store_threshold = Signal()
self.comb += [ self.comb += [
# Sink --> Pre-FIFO. # Sink --> Pre-FIFO.
self.sink.connect(pre_fifo.sink), self.sink.connect(pre_fifo.sink),
# DRAM Threshold. We can only enable path to DRAAM when we have enough data for a full
# DRAM word.
dram_store_threshold.eq(pre_fifo.level > data_width_ratio),
# Bypass / DRAM. # Bypass / DRAM.
If(with_bypass & bypass, If(with_bypass & dram_bypass,
# Pre-FIFO --> Post-FIFO. # Pre-FIFO --> Post-FIFO.
pre_fifo.source.connect(post_fifo.sink), pre_fifo.source.connect(post_fifo.sink),
).Else( ).Else(
# Pre-FIFO --> Pre-Converter. # Pre-FIFO --> Pre-Converter.
If(store | (not with_bypass), If(dram_store | (not with_bypass),
pre_fifo.source.connect(pre_converter.sink), pre_fifo.source.connect(pre_converter.sink),
), ),
# Post-Converter --> Post-FIFO. # Post-Converter --> Post-FIFO.
@ -293,43 +295,36 @@ class LiteDRAMFIFO(Module):
# FSM. # FSM.
# ---- # ----
if with_bypass: if with_bypass:
can_store = Signal()
self.comb += can_store.eq(pre_fifo.level > data_width_ratio)
self.submodules.fsm = fsm = FSM(reset_state="BYPASS") self.submodules.fsm = fsm = FSM(reset_state="BYPASS")
fsm.act("BYPASS", fsm.act("BYPASS",
bypass.eq(1), dram_bypass.eq(1),
# Switch to DRAM mode when enough data to store a DRAM word. # Switch to DRAM mode when enough data to store a DRAM word.
If(can_store, If(dram_store_threshold,
NextValue(store, 1), NextValue(dram_store, 1),
NextValue(count, 0),
NextState("DRAM") NextState("DRAM")
) )
) )
data_inc = Signal() dram_cnt_inc = Signal()
data_dec = Signal() dram_cnt_dec = Signal()
data_cnt = Signal(int(math.log2(depth + writer_fifo_depth + reader_fifo_depth) + 1)) dram_cnt = Signal(int(math.log2(depth + pre_fifo_depth + post_fifo_depth) + 1))
self.sync += data_cnt.eq(data_cnt + data_inc - data_dec) self.sync += dram_cnt.eq(dram_cnt + dram_cnt_inc - dram_cnt_dec)
fsm.act("DRAM", fsm.act("DRAM",
# Increment DRAM Data Count on Pre-Converter's Sink cycle. # Increment DRAM Data Count on Pre-Converter's Sink cycle.
data_inc.eq(pre_converter.sink.valid & pre_converter.sink.ready), dram_cnt_inc.eq(pre_converter.sink.valid & pre_converter.sink.ready),
# Decrement DRAM Data Count on Post-Converter's Source cycle. # Decrement DRAM Data Count on Post-Converter's Source cycle.
data_dec.eq(post_converter.source.valid & post_converter.source.ready), dram_cnt_dec.eq(post_converter.source.valid & post_converter.source.ready),
# Update store. # Update DRAM store..
If(data_inc, If(pre_converter.source.valid,
NextValue(count, count + 1), NextValue(dram_store, dram_store_threshold),
If(count == (data_width_ratio - 1),
NextValue(count, 0),
NextValue(store, can_store),
)
), ),
# Maintain DRAM Data Count. # Maintain DRAM Data Count.
NextValue(data_cnt, data_cnt + data_inc - data_dec), NextValue(dram_cnt, dram_cnt + dram_cnt_inc - dram_cnt_dec),
# Switch back to Bypass mode when DRAM Data count # Switch back to Bypass mode when DRAM Data count
If((can_store == 0) & (data_cnt == 0), If((dram_store_threshold == 0) & (dram_cnt == 0),
NextState("BYPASS") NextState("BYPASS")
) )
) )