|
13 | 13 | "LastInserter",
|
14 | 14 | "LastOnTimeout",
|
15 | 15 | "Arbiter",
|
| 16 | + "Gate", |
16 | 17 | ]
|
17 | 18 |
|
18 | 19 |
|
@@ -378,3 +379,52 @@ def elaborate(self, platform):
|
378 | 379 | m.d.comb += sink.connect(source)
|
379 | 380 |
|
380 | 381 | return m
|
| 382 | + |
| 383 | + |
| 384 | +class Gate(Elaboratable): |
| 385 | + """ This module enables or disables the data flow between |
| 386 | + sink and source streams. |
| 387 | +
|
| 388 | + param: drop_when_disabled: |
| 389 | + when set, data from the sink is dropped when the gate is closed. |
| 390 | + when not set, the data is not consumed from the sink when closed. |
| 391 | +
|
| 392 | + param: wait_last: |
| 393 | + when set, the gate state will be updated only when receiving |
| 394 | + the next `last` to avoid cutting in the middle of a packet. |
| 395 | + """ |
| 396 | + def __init__(self, layout, drop_when_disabled=False, wait_last=False): |
| 397 | + self.drop_when_disabled = drop_when_disabled |
| 398 | + self.wait_last = wait_last |
| 399 | + |
| 400 | + self.enable = Signal() |
| 401 | + self.sink = stream.Endpoint(layout) |
| 402 | + self.source = stream.Endpoint(layout) |
| 403 | + |
| 404 | + def elaborate(self, platform): |
| 405 | + sink = self.sink |
| 406 | + source = self.source |
| 407 | + |
| 408 | + m = Module() |
| 409 | + |
| 410 | + if self.wait_last: |
| 411 | + flowing = Signal() |
| 412 | + |
| 413 | + # Wait for the `last` signal to change the gate state. |
| 414 | + with m.If(flowing | self.drop_when_disabled): |
| 415 | + with m.If(sink.valid & sink.ready & sink.last): |
| 416 | + m.d.sync += flowing.eq(self.enable) |
| 417 | + with m.Else(): |
| 418 | + m.d.sync += flowing.eq(self.enable) |
| 419 | + |
| 420 | + else: |
| 421 | + flowing = self.enable |
| 422 | + |
| 423 | + # Connect streams when the gate is open, |
| 424 | + # or optionally drop data when closed. |
| 425 | + with m.If(flowing): |
| 426 | + m.d.comb += sink.connect(source) |
| 427 | + with m.Else(): |
| 428 | + m.d.comb += sink.ready.eq(self.drop_when_disabled) |
| 429 | + |
| 430 | + return m |
0 commit comments