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
| Port | Direction | Type | Description |
|---|---|---|---|
clk_i | in | 1 bit | Clock |
rst_i | in | 1 bit | Synchronous reset (active high) |
a_i | in | 1 bit | Encoder channel A, synchronous |
b_i | in | 1 bit | Encoder channel B, synchronous |
pos_o | out | 8-bit vector | Position count, wraps mod 256, registered |
dir_o | out | 1 bit | 1 toward the far dock, 0 toward the near dock, registered |
fault_o | out | 1 bit | Sticky 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_oandfault_oall 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_owraps mod 256 in both directions dir_oupdates 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_obut leavesdir_oalone - Both bits changed at once: no count change, no direction change;
fault_ogoes 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 = 1at 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_oandfault_oon 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.
Click Run to execute your code. Output will appear here.