While working on a multiple CAN transceiver project for a test automation suite, I decided the most cost effective architecture for a single interface with lots of CAN nodes was to use multiple super-cheap MCUs with one CAN interface each and a shared bus.  Since the most ubiquitous communication interface on inexpensive MCUs happened to be a UART, I decided to build a shared UART bus with a FTDI USB/UART bridge at the head end.

The downstream host-to-many direction was implemented by tying the FTDI’s UART transmit line to all the MCU’s receive line through a single buffer/driver to eliminate fan-out concerns. ¬†Arbitration is not needed here as an address scheme in the protocol defines which MCU is being addressed by the host. ¬†All MCUs see the same broadcast data from the host, but act only on packets with their node id.

The upstream many-to-host direction needs more control. ¬†Each MCU’s UART transmit line is tied to a common net through a tri-stateable buffer – again for fan-out concerns with so many capacitive loads on the same wire. ¬†An arbitration mechanism is needed to keep each node from talking over the other. ¬†This could be solved by having the host schedule a time window where each node could relay back a frame (or nothing) – eg a polling scheme. ¬†However this is a bit inefficient. ¬†It occurred to me a simple fixed priority arbiter could be made out of a SPLD like a 22v10.


My requirement was to create a cascade-able fixed priority arbiter out of a common logic device.  Most logic devices are either combinatoric or registered logic but not both.  The most common devices that include both are V series SPLDs like 16v8s and 22v10s.  I chose the later due to a higher pin count Рmeaning more nodes could be supported w/o cascading.

The design has specific 10 outputs Р9 grant lines to slave nodes and 1 request line to an upstream master arbiter.  The design has 10 specific inputs Р9 request lines from slave nodes and 1 grant line from an upstream master arbiter.  If cascade support is not needed, the upstream request line can be tied to the upstream grant line.  This design, implemented on a 22v10, can act as all arbitration nodes at each level in a multi-tier scheme.  The design has 2 common inputs Рan asynchronous reset to ensure all flip-flops are in a deterministic state at the start of operation and a clock input to pace grant evaluation and prevent racing.  The clock input can be any frequency and determines the minimum grant response to any request.

In a cascading system, all arbiters can use the same clock.  The cascade chain can be infinitely long, but the minimum grant time is 1 clock for a single device, 2 clocks for a two tier cascade, 3 clocks for a three tier cascade, and so on.  All resets should be tied together for a multiple device cascade.


The following CUPL code is the complete implementation of the arbiter:

Pin  1 = CLK;
Pin  2 = !R0;
Pin  3 = !R1;
Pin  4 = !R2;
Pin  5 = !R3;
Pin  6 = !R4;
Pin  7 = !R5;
Pin  8 = !R6;
Pin  9 = !R7;
Pin 10 = !R8;
Pin 11 = !GE;
Pin 13 = !RESET;

Pin 14 = !RE;
Pin 15 = !G8;
Pin 16 = !G7;
Pin 17 = !G6;
Pin 18 = !G5;
Pin 19 = !G4;
Pin 20 = !G3;
Pin 21 = !G2;
Pin 22 = !G1;
Pin 23 = !G0;

G0.d = GE & R0 & (G0 # (!G1 & !G2 & !G3 & !G4 & !G5 & !G6 & !G7 & !G8));
G1.d = GE & R1 & (G1 # (!G0 & !G2 & !G3 & !G4 & !G5 & !G6 & !G7 & !G8 & !R0));
G2.d = GE & R2 & (G2 # (!G0 & !G1 & !G3 & !G4 & !G5 & !G6 & !G7 & !G8 & !R0 & !R1));
G3.d = GE & R3 & (G3 # (!G0 & !G1 & !G2 & !G4 & !G5 & !G6 & !G7 & !G8 & !R0 & !R1 & !R2));
G4.d = GE & R4 & (G4 # (!G0 & !G1 & !G2 & !G3 & !G5 & !G6 & !G7 & !G8 & !R0 & !R1 & !R2 & !R3));
G5.d = GE & R5 & (G5 # (!G0 & !G1 & !G2 & !G3 & !G4 & !G6 & !G7 & !G8 & !R0 & !R1 & !R2 & !R3 & !R4));
G6.d = GE & R6 & (G6 # (!G0 & !G1 & !G2 & !G3 & !G4 & !G5 & !G7 & !G8 & !R0 & !R1 & !R2 & !R3 & !R4 & !R5));
G7.d = GE & R7 & (G7 # (!G0 & !G1 & !G2 & !G3 & !G4 & !G5 & !G6 & !G8 & !R0 & !R1 & !R2 & !R3 & !R4 & !R5 & !R6));
G8.d = GE & R8 & (G8 # (!G0 & !G1 & !G2 & !G3 & !G4 & !G5 & !G6 & !G7 & !R0 & !R1 & !R2 & !R3 & !R4 & !R5 & !R6 & !R7));

RE = R0 # R1 # R2 # R3 # R4 # R5 # R6 # R7 # R8;

[G8..0].ar = RESET;
[G8..0].sp = 'b'0;
[G8..0].ck = CLK; = RESET;
GA.sp = 'b'0; = CLK;


Each slave must assert it’s request signal (active low) and then monitor for it’s grant signal to indicate active (low) before communicating on the bus. ¬†While granted, no other slave can interrupt a current grant so long as the slave holding the grant maintains it’s request signal. ¬†Once a slave releases it’s request signal, it must wait at least one arbitration clock pulse duration before attempting to re-assert the request signal as the grant may still reflect the previous state evaluation until the next arbitration clock. ¬†For cascaded systems, it is advisable slaves wait <n> arbitration clock periods between requests where <n> is the tier count.

A system master must ensure a reset assertion on power up to prevent in-deterministic transients.  This can be done by a designated reset master or a power supervision reset chip like a MCP130.


This code is (c) Alan Hightower Р and release under the GPLv2 license.  Please be respectful and carry it forward.