Skip to content

owr_pkg: Architecture and Design Description

1. Contents

File Content
src/owr_pkg.vhd Character kinds Kind*_c, control types Ctrl*_c, N-Char format NChar_t, link states State*_c, error causes Cause*_c, credit limits, broadcast code fields BcType*_c and BcKind*_c, nominal times of ECSS 5.4.8, 5.4.10 and 5.5.7, functions timeCycles, initDivider, parityBit, xorReduce
src/owr_regs_pkg.vhd Register map (generated by tools/regmap.py)
src/owr_cc_pulse.vhd Pulse crossing without latch: two-phase handshake over olo_ft_cc_bits, one output pulse of one cycle per input pulse (section 4)

2. Character encoding

Kind Bits on the line (first bit left) Length
Data character P 0 D0 D1 D2 D3 D4 D5 D6 D7 10
FCT P 1 0 0 4
EOP P 1 0 1 4
EEP P 1 1 0 4
ESC P 1 1 1 4
Null ESC FCT: P 1 1 1 0 1 0 0 8
Broadcast code ESC data character: P 1 1 1 1 0 B0 .. B7 14

The control type constants hold the type bits with bit 0 as the first bit sent: CtrlEop_c = "10" is sent as 0, 1. parityBit(prev, flag) returns the parity bit P that makes prev XOR P XOR flag = '1'.

3. Data-Strobe far-end model (tb/)

owr_tb_ds_pkg defines the character encoding and the protected type of the control object; owr_tb_farend_pkg holds the object FarEnd_v with, per model instance, a transmit queue, the bit period, the transmit mode (off with controlled reset, Nulls when idle, silent when idle), the fault injection requests, a receive log of characters with their start time, a log of edges and error counters. owr_tb_ds_bfm is the model: its transmitter encodes the queued characters with its own implementation of ECSS 5.4.3 and 5.4.4 and waits the bit period between bits; its receiver wakes on every edge of data or strobe, recovers a bit on every change of data XOR strobe, searches the first Null and decodes the characters. Both work in continuous time and do not use the clock of the port.

4. Pulse crossing owr_cc_pulse

Per pulse bit a two-phase handshake (no latch, every path between the clock domains starts at a register):

            In_Clk                          |              Out_Clk
                                            |
 In_Pulse -> Want = In_Pulse or Pend        |
             Fire = Want and (Req = Ack)    |
             Req  <= Req xor Fire  (TMR) ---+-> olo_ft_cc_bits -> ReqOut -+-> Out_Pulse = ReqOut xor Last
             Pend <= Want and not Fire (TMR)|                            |   Last <= ReqOut (TMR)
             Ack  <- olo_ft_cc_bits <-------+----------------------------+
  • A pulse toggles the request level when no transfer is in progress (request equal to acknowledge), otherwise it is stored as pending (Pend) and toggles the request once the acknowledge returns. Further pulses during the same transfer merge with the pending one.
  • The output side emits one pulse per change of the synchronised request level and returns the level as acknowledge.
  • Round trip: at most 5 input and 4 output clock cycles (request register and the input register of olo_ft_cc_bits, two synchronising stages per direction, alignment to the other clock), so pulses 5 input plus 5 output clock cycles apart are never pending. Latency of an output pulse: at most 3 input plus 4 output clock cycles.
  • Req, Pend and Last are triplicated; every copy loads the voted value, so a flipped copy is corrected in the next cycle. Synthesis attributes of the Open Logic attribute packages (dont_touch, dont_merge, preserve, syn_preserve, syn_keep) prevent merging of the copies, syn_radhardlevel = none prevents vendor TMR insertion.
  • olo_ft_cc_reset couples the resets: a reset of either side resets both; request, acknowledge and Last restart from 0, so a reset creates no output pulse.

olo_ft_cc_pulse of Open Logic is not used: it is built from a set/reset latch per copy, which the FPGA tools map to a transparent latch whose gate and data both follow the input pulse, so the end of the pulse races the closing of the latch, and the path through the latch is not timed.