|
11 | 11 | "Splitter",
|
12 | 12 | "Merger",
|
13 | 13 | "LastInserter",
|
| 14 | + "LastOnTimeout", |
14 | 15 | "Arbiter",
|
15 | 16 | ]
|
16 | 17 |
|
@@ -252,6 +253,54 @@ def elaborate(self, platform):
|
252 | 253 | return m
|
253 | 254 |
|
254 | 255 |
|
| 256 | +class LastOnTimeout(Elaboratable): |
| 257 | + """ This module injects a `last` signal into the source stream |
| 258 | + if no more data is received from the sink stream since more than |
| 259 | + `timeout` clock cycles. |
| 260 | +
|
| 261 | + Typically this module can be connected to a UART receiver to delimit |
| 262 | + packets based on the idle time between packets, or to to realign |
| 263 | + a converter when no more data is received. |
| 264 | + """ |
| 265 | + def __init__(self, layout, timeout=1): |
| 266 | + self.timeout = timeout |
| 267 | + self.sink = stream.Endpoint(layout) |
| 268 | + self.source = stream.Endpoint(layout) |
| 269 | + |
| 270 | + def elaborate(self, platform): |
| 271 | + sink = self.sink |
| 272 | + source = self.source |
| 273 | + |
| 274 | + m = Module() |
| 275 | + |
| 276 | + m.submodules.timer = timer = WaitTimer(self.timeout) |
| 277 | + m.d.comb += timer.wait.eq(~sink.valid) |
| 278 | + |
| 279 | + last_r = Signal() |
| 280 | + loaded = Signal() |
| 281 | + |
| 282 | + with m.If(sink.valid & sink.ready): |
| 283 | + m.d.sync += [ |
| 284 | + source.data.eq(sink.data), |
| 285 | + last_r .eq(sink.last), |
| 286 | + loaded .eq(1), |
| 287 | + ] |
| 288 | + with m.Elif(source.valid & source.ready): |
| 289 | + m.d.sync += loaded.eq(0) |
| 290 | + |
| 291 | + with m.If(~source.valid | source.ready): |
| 292 | + m.d.comb += sink.ready.eq(1) |
| 293 | + |
| 294 | + # We send the data to the source stream immediately |
| 295 | + # when it was the last data, or when more data is incoming, |
| 296 | + # or if we waited until the timeout expired. |
| 297 | + with m.If(loaded & (last_r | sink.valid | timer.done)): |
| 298 | + m.d.comb += source.valid.eq(1) |
| 299 | + m.d.comb += source.last.eq(last_r | timer.done) |
| 300 | + |
| 301 | + return m |
| 302 | + |
| 303 | + |
255 | 304 | class RoundRobin(Elaboratable):
|
256 | 305 | """ Fair round robin.
|
257 | 306 | """
|
|
0 commit comments