-
Notifications
You must be signed in to change notification settings - Fork 574
Streams
LiteX's streams are group of signals (Migen's Record) used to create Sink/Source Endpoints on Modules and easily transfer data between them. LiteX's streams are a simplified compromise between AXI-4/Avalon-ST:
-
valid
: similar to AXI-4'stvalid
. -
ready
: similar to AXI-4'stready
. -
first
(used for packets only when needed): similar to Avalon-ST'ssop
, because it's sometimes useful to just easily know the start of a packet instead of deducing it from last as done in AXI-4. -
last
(used for packets) : similar to AXI-4'slast
. -
payload
: a Record with its own layout, similar to AXI-4'stdata
that can evolve at each valid/ready transaction. -
param
(optional): a Record with its own layout, similar to AXI-4'stuser
that can evolve at each start of packet.
LiteX's streams can be directly mapped to AXI-4 and adapted easily to AvalonST with: https://github.com/enjoy-digital/litex/blob/master/litex/soc/interconnect/avalon.py.
A basic real world example is provided by litex.soc.cores.uart
.
It has a StreamEndpoint
called sink
, which
enables the user of the module to stream data into the module as follows:
#!/usr/bin/env python3
from migen import *
from litex.soc.cores.uart import RS232PHYTX
from litex.build.generic_platform import *
baudrate = 115200
clk_freq = 50e6
tuning = int((baudrate/clk_freq)*2**32)
pads = Record([
("tx", 1),
("rx", 1)
])
dut = RS232PHYTX(pads, tuning)
def write(value: int):
yield dut.sink.payload.data.eq(value)
yield dut.sink.valid.eq(1)
yield
yield dut.sink.payload.data.eq(0)
yield
yield dut.sink.valid.eq(0)
while (yield dut.sink.ready != 1):
yield
def testbench():
yield from write(0)
yield from write(0xaa)
yield from write(0x55)
yield from write(0xff)
run_simulation(dut, testbench(), vcd_name="rs232-tx.vcd")
When the sink becomes ready (ie the UART is ready to transmit another byte), the ready
signal is asserted, and data
can be written by setting up the payload data as above and asserting the valid
signal.
When the valid
signal is asserted, the data is read by the module. In the example above, you can see that it is clocked into the transmit register of the UART.
The whole trace of the above example then looks like this:
Note that in this example we had only a single input signal (payload.data
). This is because the Endpoint definition for the UART
was defined as a record with a single member (data
):
self.sink = stream.Endpoint([("data", 8)])
This means that streams can carry bundles of related signals (nmigen Record
type).
Click here for a more in-depth example of using Record
.
Have a question or want to get in touch? Our IRC channel is #litex at irc.libera.chat.
- Welcome to LiteX
- LiteX's internals
- How to
- Create a minimal SoC-TODO
- Add a new Board-TODO
- Add a new Core-WIP
- Add a new CPU-WIP
- Reuse-a-(System)Verilog,-VHDL,-Amaranth,-Spinal-HDL,-Chisel-core
- Use LiteX on the Acorn CLE 215+
- Load application code the CPU(s)
- Use Host Bridges to control/debug a SoC
- Use LiteScope to debug a SoC
- JTAG/GDB Debugging with VexRiscv CPU
- JTAG/GDB Debugging with VexRiscv-SMP, NaxRiscv and VexiiRiscv CPUs
- Document a SoC
- How to (Advanced)