Skip to content

Commit fa141c6

Browse files
occheungsbourdeauducq
authored andcommitted
SyncFIFO: relax lo_wm implementation
Burst validity should be enforced by the master.
1 parent 0b140fe commit fa141c6

File tree

1 file changed

+20
-30
lines changed

1 file changed

+20
-30
lines changed

misoc/interconnect/stream.py

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,18 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
8585
self.fifo.re.eq(self.source.ack)
8686
]
8787

88-
# Watermarks:
89-
# FIFO only signals only signals availability when a complete
90-
# burst/buffered packet can be transferred.
91-
#
88+
# Burst transfer with the use of watermarks:
89+
# FIFO would expect complete bursts to be written to/read from, when
90+
# given the corresponding watermark arguments, unless the burst is
91+
# prematurely terminated by asserting sink.eop.
9292
# A complete burst is a continuous lo_wm/hi_wm of words written to/
9393
# read from the FIFO.
94-
#
95-
# The EoP bit from the sink endpoint signals the end of packet.
9694

95+
# With high watermark, FIFO mandates hi_wm length burst read.
96+
#
97+
# source.stb is held low if no complete burst/buffered packet could
98+
# be transferred.
99+
# source.last is driven high to signal end of burst.
97100
if hi_wm is not None:
98101
transfer_count = Signal(max=hi_wm, reset=hi_wm-1)
99102
transfer_count_ce = Signal()
@@ -104,7 +107,6 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
104107
has_pending_eop = Signal()
105108

106109
# helper signals
107-
last = Signal()
108110
do_write = Signal()
109111
do_read = Signal()
110112

@@ -121,7 +123,6 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
121123
# Avoid downstream overreading
122124
self.fifo.re.eq(self.source.stb & self.source.ack),
123125

124-
last.eq((transfer_count == 0) | fifo_out.eop),
125126
do_write.eq(self.fifo.we & self.fifo.writable),
126127
do_read.eq(self.fifo.re & self.fifo.readable),
127128
has_pending_eop.eq(eop_count_next != 0),
@@ -139,61 +140,50 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
139140

140141
# Stream control
141142
self.comb += [
143+
self.source.last.eq((transfer_count == 0) | fifo_out.eop),
142144
self.source.stb.eq(self.fifo.readable & (self.fifo.almost_full | activated)),
143145
transfer_count_ce.eq(do_read),
144-
transfer_count_rst.eq(do_read & last),
146+
transfer_count_rst.eq(do_read & self.source.last),
145147
]
146148

147149
self.sync += [
148150
If(~activated,
149151
activated.eq(self.fifo.almost_full | (self.sink.eop & do_write))
150-
).Elif(do_read & last,
152+
).Elif(do_read & self.source.last,
151153
activated.eq(has_pending_eop),
152154
),
153155
]
154156

157+
# With low watermark, FIFO accepts lo_wm length burst write.
158+
#
159+
# sink.last must indicate the end of burst
160+
#
161+
# It is the upstream's duty to drive sink.last signal appropriately.
155162
if lo_wm is not None:
156-
recv_burst_len = depth-lo_wm
157-
recv_count = Signal(max=recv_burst_len, reset=recv_burst_len-1)
158-
recv_count_ce = Signal()
159-
recv_count_rst = Signal()
160163
recv_activated = Signal()
161164

162165
# helper signals
163166
do_write = Signal()
164-
recv_last = Signal()
165167

166168
self.comb += [
167169
do_write.eq(self.fifo.we & self.fifo.writable),
168-
recv_last.eq((recv_count == 0) | self.sink.eop),
169170

170171
# Avoid upstream overwriting
171172
self.fifo.we.eq(self.sink.stb & self.sink.ack),
172173
]
173174

174-
self.sync += [
175-
If(recv_count_rst,
176-
recv_count.eq(recv_count.reset),
177-
).Elif(recv_count_ce,
178-
recv_count.eq(recv_count - 1),
179-
),
180-
]
181-
182175
# recv stream control
183-
self.comb += [
176+
self.comb += \
184177
self.sink.ack.eq(self.fifo.writable & (
185178
self.fifo.almost_empty # Can accept long burst
186179
| recv_activated # In the middle of a burst
187-
)),
188-
recv_count_ce.eq(do_write),
189-
recv_count_rst.eq(do_write & recv_last),
190-
]
180+
))
191181

192182
self.sync += \
193183
If(~recv_activated,
194184
# Avoid entry to burst state if it is a 1 word burst
195185
recv_activated.eq(self.fifo.almost_empty & ~(do_write & self.sink.eop)),
196-
).Elif(recv_activated & (do_write & recv_last),
186+
).Elif(recv_activated & (do_write & (self.sink.last | self.sink.eop)),
197187
# almost_empty needs 1 cycle to update
198188
recv_activated.eq(0),
199189
)

0 commit comments

Comments
 (0)