Practice

Ferry Chain Count

A chain ferry crosses the river at Aldermere by pulling itself along a 140 m chain. The new dock controller needs to know where the ferry is and which way it is moving. The chain turns a pulley with a 2-bit position sensor called a quadrature encoder, which sends signals on channels a_i and b_i. Each step of the chain flips exactly 1 of the 2 bits. The order of the flips tells you the direction.

The commissioning log shows two problems. First, at the docks, waves from passing boats rock the ferry, and the pulley jitters: 1 step forward, 1 step back. The old decoder reported a direction change on every jitter step. Each report re-arms the boarding barrier, so the barrier lights blinked all afternoon. Second, a greasy sensor sometimes misses one change, and then the next sample shows both bits changed at once. After such a jump, the sample cannot show whether the chain moved 2 steps forward or back, so the position is unknown and the count must not guess.

Your task: build the decoder. It keeps a wrapping position count on pos_o and a direction output dir_o that dock jitter cannot flip. It also raises a sticky fault flag fault_o (it stays set until reset) for the both-bits jumps.

Interface

PortDirectionTypeDescription
clk_iin1 bitClock
rst_iin1 bitSynchronous reset (active high)
a_iin1 bitEncoder channel A, synchronous
b_iin1 bitEncoder channel B, synchronous
pos_oout8-bit vectorPosition count, wraps mod 256, registered
dir_oout1 bit1 toward the far dock, 0 toward the near dock, registered
fault_oout1 bitSticky double-transition flag, cleared by reset

Behavior

  • The pair (a_i, b_i) is sampled at every rising edge and compared with the previous sample
  • No change: pos_o, dir_o and fault_o all hold
  • Exactly one bit changed: a step. Forward order 00, 01, 11, 10, 00 adds 1 to pos_o, and the reverse order subtracts 1. pos_o wraps mod 256 in both directions
  • dir_o updates only when a step goes the same way as the step before it
  • A single step against the current run (the dock jitter) moves pos_o but leaves dir_o alone
  • Both bits changed at once: no count change, no direction change; fault_o goes high and stays high until reset
  • After a double change, decoding re-anchors on the new pair; later valid steps keep counting while the flag stays up
  • rst_i = 1 at a rising edge: pos_o = 0, dir_o = 1, fault_o = 0, and the previous-step memory is set to forward
  • Reset also latches the current line pair as the new baseline, so an unmoving chain produces no phantom step on release

What the bench checks

  • The testbench checks pos_o, dir_o and fault_o on every cycle
  • Forward and reverse runs cover steady parking and position wrap in both directions
  • Direction must change only after two consecutive contrary steps, while alternating jitter must leave it unchanged
  • Both illegal double transitions must set the sticky fault without changing position, and valid counting must continue afterward
  • Reset on nonzero encoder lines must clear every output and re-anchor there without a phantom step

Constraints

TIMING: everything is synchronous to clk_i; all three outputs are registers.

SCOPE: this models the step decoder alone; the lines arrive clean and synchronous. The pulley, the chain, the barrier, and the sensor's electrical side are out of scope.

The encoder lines are already clean and synchronous. There is nothing to debounce (the lines never glitch). Do not add ports.

Loading editor...

Click Run to execute your code. Output will appear here.