@@ -85,15 +85,18 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
85
85
self .fifo .re .eq (self .source .ack )
86
86
]
87
87
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.
92
92
# A complete burst is a continuous lo_wm/hi_wm of words written to/
93
93
# read from the FIFO.
94
- #
95
- # The EoP bit from the sink endpoint signals the end of packet.
96
94
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.
97
100
if hi_wm is not None :
98
101
transfer_count = Signal (max = hi_wm , reset = hi_wm - 1 )
99
102
transfer_count_ce = Signal ()
@@ -104,7 +107,6 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
104
107
has_pending_eop = Signal ()
105
108
106
109
# helper signals
107
- last = Signal ()
108
110
do_write = Signal ()
109
111
do_read = Signal ()
110
112
@@ -121,7 +123,6 @@ def __init__(self, fifo_class, layout, depth, hi_wm=None, lo_wm=None):
121
123
# Avoid downstream overreading
122
124
self .fifo .re .eq (self .source .stb & self .source .ack ),
123
125
124
- last .eq ((transfer_count == 0 ) | fifo_out .eop ),
125
126
do_write .eq (self .fifo .we & self .fifo .writable ),
126
127
do_read .eq (self .fifo .re & self .fifo .readable ),
127
128
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):
139
140
140
141
# Stream control
141
142
self .comb += [
143
+ self .source .last .eq ((transfer_count == 0 ) | fifo_out .eop ),
142
144
self .source .stb .eq (self .fifo .readable & (self .fifo .almost_full | activated )),
143
145
transfer_count_ce .eq (do_read ),
144
- transfer_count_rst .eq (do_read & last ),
146
+ transfer_count_rst .eq (do_read & self . source . last ),
145
147
]
146
148
147
149
self .sync += [
148
150
If (~ activated ,
149
151
activated .eq (self .fifo .almost_full | (self .sink .eop & do_write ))
150
- ).Elif (do_read & last ,
152
+ ).Elif (do_read & self . source . last ,
151
153
activated .eq (has_pending_eop ),
152
154
),
153
155
]
154
156
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.
155
162
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 ()
160
163
recv_activated = Signal ()
161
164
162
165
# helper signals
163
166
do_write = Signal ()
164
- recv_last = Signal ()
165
167
166
168
self .comb += [
167
169
do_write .eq (self .fifo .we & self .fifo .writable ),
168
- recv_last .eq ((recv_count == 0 ) | self .sink .eop ),
169
170
170
171
# Avoid upstream overwriting
171
172
self .fifo .we .eq (self .sink .stb & self .sink .ack ),
172
173
]
173
174
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
-
182
175
# recv stream control
183
- self .comb += [
176
+ self .comb += \
184
177
self .sink .ack .eq (self .fifo .writable & (
185
178
self .fifo .almost_empty # Can accept long burst
186
179
| 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
+ ))
191
181
192
182
self .sync += \
193
183
If (~ recv_activated ,
194
184
# Avoid entry to burst state if it is a 1 word burst
195
185
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 ) ),
197
187
# almost_empty needs 1 cycle to update
198
188
recv_activated .eq (0 ),
199
189
)
0 commit comments