Framer 16 (framer16)

Converts a single-channel complex IQ sample stream into 16-sample positional frames, mimicking the channelizer output expected by the folded demod chain.

Tested platforms include xsim.

Design

The folded demod front-end (cr_x16, ted_x16, dsd_x16, fs_x16) expects its input as a stream of 16-sample complex_short_timed_sample messages — one message per channelizer output cycle — where each sample slot corresponds to one of the 16 frequency bins assigned to that port. framer16 generates this framing from a single-channel stream so that the folded chain can be exercised in pure simulation, without a real channelizer or AD9361 hardware.

For each input sample the worker emits a 16-beat output message. The sample is placed in beat position (a writable property); all other beats carry zero. som is asserted on beat 0 and eom on beat 15. The output opcode is always complex_short_timed_sample_sample_op_e.

The worker accepts one input sample per emitted frame. While it is serialising the 16-beat output burst (busy = '1'), the input port is back-pressured (take is deasserted). At the nominal OPV waveform rate of 216.8 kHz (after 1/15 decimation, SPS = 4), the output burst runs at 3.47 MHz — well below the fabric clock — so the input effectively never stalls.

The swap_iq property swaps the two 16-bit halves of each input sample word before latching. This accommodates the cr_x16 I/Q word convention (I/real in bits 31:16, Q/imag in bits 15:0) when the upstream decimator or file source uses the opposite packing (real in bits 15:0).

Input samples with any opcode other than complex_short_timed_sample_sample are silently discarded; only sample-opcode beats are latched and framed.

EOF from the input is latched and propagated to the output after the current frame (if any) has been fully emitted and the worker has returned to the idle state.

Interface

<?xml version='1.0' encoding='utf-8'?>
<!-- framer16: wrap a single-channel IQ stream into the 16-channel POSITIONAL
     frame format the folded demod chain (cr_x16 ...) expects, exactly mimicking
     the channelizer's output.  For each input sample it emits one 16-sample
     complex_short_timed_sample message (SOM on position 0, EOM on position 15)
     with the sample placed in `position` and zeros in the other 15 positions.

     Use in pure-sim validation (no channelizer / no AD9361):
        file_read(frame_bits) -> msk_mod -> polyphase_decimator(/15) -> framer16
        -> cr_x16 -> ted_x16 -> dsd_x16 -> fs_x16 -> msk_decode_x16 -> file_write
     The decimator sets the rate (216.8 kHz, SPS=4); framer16 sets the framing.

     I/Q convention: cr_x16 reads I/real = data[31:16] (high 16).  If the upstream
     decimator puts real in the low 16, set swap_iq=true. -->
<ComponentSpec>

  <property name='init' type='bool' writable='true' default='false'
            description="Pulse high to reset the framer"/>

  <property name='position' type='uchar' writable='true' default='0'
            description="Which of the 16 frame positions (0..15) carries the signal; others are zero"/>

  <property name='swap_iq' type='bool' writable='true' default='false'
            description="Swap the I/Q 16-bit halves of each sample (set if upstream uses real=low 16 but cr_x16 expects real=high 16)"/>

  <port name="input"  producer="false" protocol="complex_short_timed_sample-prot"/>
  <port name="output" producer="true"  protocol="complex_short_timed_sample-prot"/>

</ComponentSpec>

Ports

Inputs:

  • input: Single-channel complex_short_timed_sample stream to be framed.

    • Protocol: complex_short_timed_sample-prot

    • Optional: False

Outputs:

  • output: 16-sample positional frame stream compatible with the folded demod chain input.

    • Protocol: complex_short_timed_sample-prot

    • Optional: False

Opcode Handling

Only sample opcodes on the input are processed. Any other opcode is consumed (taken from the input) but does not trigger a framing cycle and produces no output. The output always carries the sample opcode.

Properties

  • init: Pulse high to reset the framer.

    • Type: bool

    • Access:

      • Parameter: False

      • Writable: True

      • Initial: False

      • Volatile: False

    • Default value: false

  • position: Which of the 16 frame positions (0..15) carries the signal; others are zero.

    • Type: uchar

    • Access:

      • Parameter: False

      • Writable: True

      • Initial: False

      • Volatile: False

    • Default value: 0

  • swap_iq: Swap the I/Q 16-bit halves of each sample (set if upstream uses real=low 16 but cr_x16 expects real=high 16).

    • Type: bool

    • Access:

      • Parameter: False

      • Writable: True

      • Initial: False

      • Volatile: False

    • Default value: false

Implementations

  • framer16 (HDL)

    Wraps a single-channel IQ sample stream into 16-sample positional frames for simulation testing of the folded demod chain.

Dependencies

The framer16 HDL worker depends on:

  • ieee.std_logic_1164

  • ieee.numeric_std

  • ocpi.types (for complex_short_timed_sample opcode constants)

Limitations

Limitations of framer16 are:

  • Designed for simulation use only. The 16x output expansion is not suitable for production placement ahead of a real channelizer.

  • position must be in the range 0 to 15. Values of 15 or higher are accepted but values of 16 or above exceed the 4-bit pos_cnt counter range and will never match, producing a frame of all zeros.

  • Only the sample opcode is forwarded. Metadata or time-tag opcodes from an upstream worker are silently dropped.

Testing

The unit test drives the input with a sequence of complex_short_timed_sample messages at position = 0. The verify script checks that each output message is exactly 16 samples long, that beat 0 carries the expected I/Q value, that all other beats are zero, and that som/eom framing is correct.

Tested platforms: None

Component testing not completed.