Lab 5.9 — BPSK framed TX/RX loopback top-level¶
Goal¶
Promote the separate TX and RX anchors into one deterministic framed HDL chain:
framed bits -> symbol mapper -> 8x upsampler -> RRC TX FIR -> RRC RX FIR -> fixed-phase timing -> hard decision
This is the first Zynq-oriented top-level integration step in Block 5. It adds two things that the earlier labs intentionally avoided:
- framed source control with
valid/ready/last; - deterministic zero-symbol flushing after the last bit so the FIR tails are fully observable in loopback.
Executable HDL package¶
| File | Purpose |
|---|---|
blocks/block_05_fpga_hdl_flow/rtl/bpsk_framed_tx_chain.v |
framed BPSK TX chain with automatic flush tail |
blocks/block_05_fpga_hdl_flow/rtl/bpsk_rx_bit_recovery_chain.v |
RX matched filter, timing sampler and hard decision wrapper |
blocks/block_05_fpga_hdl_flow/python/generate_bpsk_framed_loopback_vectors.py |
generates framed input bits and loopback metadata |
blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_framed_loopback.v |
self-checking integrated TX/RX loopback testbench |
Run from the repository root:
python blocks/block_05_fpga_hdl_flow/python/generate_bpsk_framed_loopback_vectors.py
iverilog -g2012 \
-o blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_framed_loopback.out \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_symbol_mapper.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_upsampler_8x.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_rrc_tx_fir.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_rrc_rx_fir.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_symbol_timing_sampler.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_hard_decision.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_framed_tx_chain.v \
blocks/block_05_fpga_hdl_flow/rtl/bpsk_rx_bit_recovery_chain.v \
blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_framed_loopback.v
vvp blocks/block_05_fpga_hdl_flow/tb/tb_bpsk_framed_loopback.out
Expected result:
PASS: bpsk_framed_loopback completed without errors
What changed compared to Labs 5.6-5.8¶
The earlier labs proved each bridge separately:
- bit-to-symbol mapping;
- symbol-rate to sample-rate expansion;
- TX pulse shaping;
- RX matched filtering and deterministic bit recovery.
This lab proves that those stages can now run as one framed burst rather than as isolated static checks.
Framing contract¶
The TX wrapper accepts:
| Signal | Meaning |
|---|---|
s_valid |
one source bit is available |
s_ready |
the chain can accept the next framed bit |
s_last |
marks the last payload bit of the frame |
After s_last, the wrapper injects a deterministic zero-symbol flush tail. In the current BPSK setup the loopback metadata resolves this to 16 zero symbols, which is enough to expose the combined TX and RX FIR tails.
Shared metadata from Block 11¶
The loopback generator reuses:
| Shared file | Role |
|---|---|
tx_bits.txt |
framed bit payload and expected BER reference |
rrc_taps_q15.txt |
shared TX/RX pulse-shaping coefficients |
config.json |
samples_per_symbol = 8 and frame context |
The generator searches for the deterministic matched-filter sampling point of the fully integrated HDL-equivalent loopback and stores it in bpsk_framed_loopback_meta.txt.
Why this stage matters¶
This is the missing bridge between unit-style HDL checks and an actual board-level modem path:
- there is now a framed entry point instead of loose standalone vectors;
- the TX chain has explicit burst termination behavior;
- the RX chain is wired to the same timing and BER contract;
- the end-to-end HDL route can now be promoted to a Zynq top-level with DMA or RF I/O.
What to expect¶
PASS: bpsk_framed_loopback completed without errors (281 bits, payload errors 0)
tb/bpsk_framed_loopback_meta.txt: start_offset = 62, sps = 8, 281 bits, 25 preamble bits, flush_symbols = 16. Here the TX chain inside the same top-level produces the samples, so the offset is set by the internal pipeline, not by the stored input vectors of Lab 5.8.
The course runner generates the vectors, compiles, simulates and turns any FAIL line or non-zero simulator exit into an error:
python tools/run_block5_hdl_smoke.py --test tb_bpsk_framed_loopback
Exercises¶
Each exercise below is a deliberate one-line RTL mutation. Make it, run the bench, read the messages, then restore the file (git checkout -- <file>). The quoted outputs were observed with Icarus Verilog 12.0.
- Apply the polarity flip from Lab 5.8 (
out_bit <= (in_i >= 0);). This bench fails the same way:total/payload errors = 281 / 256. Nothing in this top-level knows what the preamble should look like. - Why must the TX keep sending
flush_symbols = 16zero symbols after the last frame bit? Relate the number to the group delay of the TX and RX RRC filters (65 taps each, 8 samples per symbol). - Which single signal in the waveform would you watch first to find the frame start, and why is
start_offseta fragile way to find it on real hardware?
Answers (checked against the RTL and the bench)
- The observed output is in the exercise: this top level has no reference to detect the inversion.
- Each 65-tap RRC filter delays the signal by 32 samples, 4 symbols at 8 samples per symbol; TX and RX together delay it by 8 symbols, plus the register latency of the pipeline. Without flush symbols the last frame bits would still be inside the filters when the input stops; 16 zero symbols push them through with margin.
- The matched-filter output (or the preamble correlation/lock signal, where there is one): the frame starts where the known preamble pattern appears.
start_offsethard-codes the total latency in samples, which on hardware depends on the converter FIFOs, the AD936x path and when each block was enabled; it can differ between builds and between boots, as the Block 11 case studies show.
Report checklist¶
- Show that
s_readythrottles the framed source to the 8x upsampler rate. - State the flush-symbol count and why it is needed.
- Include the deterministic
start_offsetused by the loopback receiver. - Show the final pass log with zero total and payload errors.
- State the next hardware step: routed top-level integration or board-level TX/RX validation.
Engineering conclusion template¶
The framed BPSK HDL loopback connected the mapper, 8x upsampler, TX RRC FIR and deterministic RX recovery chain into one self-checking burst path.
The TX side now exposes a framed ready/valid interface and appends a deterministic flush tail after the last bit.
This is the first integrated HDL top-level anchor that can be promoted to a routed Zynq design and later to measured BER experiments.