An SPI bus usually has one master and several slaves: a flash, a sensor, a display controller. They share the clock and data lines, and the master picks one at a time with its chip select. This article designs an SPI slave, connects two of them to one master, and covers the alternative wiring, the daisy chain.
9 min read | Intermediate
What You'll Learn
- Design an SPI slave that works in any mode
- Share MISO between slaves with high-impedance outputs
- Address several slaves with independent chip selects
- Understand daisy-chained SPI devices
Sharing the Bus
With independent chip selects, SCLK and MOSI go to every slave, and every slave's MISO connects to the master's MISO. Only the selected slave may drive MISO; every other slave leaves it in high impedance. A slave also ignores SCLK and MOSI while its chip select is high. The cost is one chip select pin per slave.
The Slave
This slave runs on its own system clock and oversamples SCLK through a synchronizer, which is common in FPGAs and in chips whose SPI port is slow compared with their clock. Its protocol is two bytes per transaction: a command byte (bit 7 = 1 for a write, bits 1:0 the register), answered with the slave's ID, and a data byte.
// SPI slave with four 8-bit registers, oversampling SCLK with its own clock.
// A transaction is two bytes with chip select held low:
// byte 1 from the master: command {rw, 5'b0, addr[1:0]}, rw = 1 for a write
// byte 1 to the master: the slave's ID
// byte 2: write data from the master, or the register value to the master for a read
// MISO is high impedance while the slave is not selected, so several slaves can share it.
module spi_slave #(
parameter CPOL = 0,
parameter CPHA = 0,
parameter ID = 8'hA5
) (
input clk,
input rst,
input sclk,
input mosi,
output miso,
input cs_n,
output [7:0] reg0,
output [7:0] reg1
);
reg [7:0] regs [0:3];
reg [2:0] sclk_s; // synchronizer plus previous value
reg [1:0] cs_s;
reg [1:0] mosi_s;
reg [2:0] bitc;
reg second; // receiving the second byte
reg [7:0] cmd;
reg [7:0] rx_sh;
reg [7:0] tx_sh;
reg miso_r;
integer i;
assign reg0 = regs[0];
assign reg1 = regs[1];
assign miso = cs_s[1] ? 1'bz : miso_r;
wire rise = sclk_s[1] && !sclk_s[2];
wire fall = !sclk_s[1] && sclk_s[2];
wire leading = CPOL ? fall : rise;
wire trailing = CPOL ? rise : fall;
wire sample = CPHA ? trailing : leading;
wire change = CPHA ? leading : trailing;
wire selected = !cs_s[1];
wire cs_fall = cs_s[1] && !cs_n; // chip select is about to become active
always @(posedge clk) begin
sclk_s <= {sclk_s[1:0], sclk};
cs_s <= {cs_s[0], cs_n};
mosi_s <= {mosi_s[0], mosi};
end
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < 4; i = i + 1)
regs[i] <= 8'h00;
miso_r <= 1'b0;
end
else if (cs_fall) begin
bitc <= 3'd0;
second <= 1'b0;
if (CPHA == 0) begin
miso_r <= ID[7]; // the first bit is on MISO before the first edge
tx_sh <= {ID[6:0], 1'b0};
end
else begin
tx_sh <= ID;
end
end
else if (selected) begin
if (sample) begin
rx_sh <= {rx_sh[6:0], mosi_s[1]};
bitc <= bitc + 3'd1;
if (bitc == 3'd7) begin // a whole byte has arrived
if (!second) begin
cmd <= {rx_sh[6:0], mosi_s[1]};
second <= 1'b1;
tx_sh <= regs[{rx_sh[0], mosi_s[1]}]; // the reply for a read
end
else if (cmd[7]) begin
regs[cmd[1:0]] <= {rx_sh[6:0], mosi_s[1]};
end
end
end
if (change) begin
miso_r <= tx_sh[7];
tx_sh <= {tx_sh[6:0], 1'b0};
end
end
end
endmodule
The edge detection is done in the system clock domain: rise and fall compare the synchronized SCLK with its previous value, and CPOL and CPHA turn them into sample and change, the mirror image of the master. On the falling edge of chip select the slave restarts: it loads its ID, and for CPHA = 0 puts the first bit on MISO immediately. When the eighth bit of the command arrives, it loads the reply for the second byte, which for a read is the addressed register.
Quick Check
Q: Why must the slave load its reply as soon as the last bit of the command arrives, rather than at the start of the second byte?
Show Answer
Because the first bit of the reply goes out on the very next change edge, half an SCLK period later. There is no gap between bytes in which the slave could prepare it.
Two Slaves
The testbench decodes one chip select per slave and gives the slaves different IDs. miso is declared as a tri-state net shared by both:
reg sel = 0; // which slave the next transaction is for
wire cs0_n = cs_n || sel != 0;
wire cs1_n = cs_n || sel != 1;
tri miso; // shared: only the selected slave drives it
SPI mode 0 (CPOL=0, CPHA=0) 1535 slave 0: write reg1 = 0x11 (ID 0xa5) 3055 slave 1: write reg1 = 0x22 (ID 0x5a) 4575 slave 0: read reg1 = 0x11 (ID 0xa5) 6095 slave 1: read reg1 = 0x22 (ID 0x5a)
Each slave answers with its own ID and keeps its own register value, although both saw every clock on SCLK and MOSI. Their chip selects kept them apart.
Daisy Chains
Some devices, such as LED drivers and shift-register-style DACs, are designed to be chained: the MISO of one feeds the MOSI of the next, all share one chip select, and the MISO of the last returns to the master. The whole chain is one long shift register. To update three 8-bit devices, the master clocks 24 bits with chip select low; the bits for the last device go first. Chip select rising then latches every device's byte at once. Daisy chains save pins but every access touches every device.
Quick Check
Q: In a daisy chain of four 16-bit devices, how many clocks does the master need to update all of them?
Show Answer
64: the chain is one 64-bit shift register, and every device's data must be shifted all the way to its position.
Running It in ChipVerify Lab
The example contains the master, two slaves and the testbench with two chip selects. Change sel and watch MISO switch between the slaves.
Common Mistakes
Mistake #1: A slave that always drives MISO
A slave that drives MISO while not selected fights the selected slave. MISO must be high impedance when CS_n is high.
Mistake #2: Two chip selects active at once
A decode bug that selects two slaves makes both drive MISO, and the master reads garbage.
Mistake #3: A slave that reacts to SCLK while not selected
Traffic to another slave would shift into its register. Every slave must ignore the bus while its chip select is high.
Practice Exercise
Challenge: A Decode Bug
Break the chip select decode so that slave 1 is also selected whenever slave 0 is. Predict what the master reads from slave 0, then run it.
Hint
Two outputs driving opposite values on the same net give X in simulation.
Solution
wire cs1_n = cs_n || (sel != 1 && sel != 0); // BUG: slave 1 also selected for slave 0
1535 slave 0: write reg1 = 0x11 (ID 0xxx) 3055 slave 1: write reg1 = 0x22 (ID 0x5a) 4575 slave 0: read reg1 = 0xXX (ID 0xxx) 6095 slave 1: read reg1 = 0x22 (ID 0x5a)
While "slave 0" is addressed, both slaves drive MISO with their different IDs and data, and every bit where they disagree becomes X. On a real board the two outputs fight, drawing current, and the master reads whichever wins. Slave 1 also received slave 0's write, which a later read of slave 1 would reveal if the second write had not overwritten it.
Open the ready-made example in the lab and run the simulation.
Summary
- Slaves share SCLK, MOSI and MISO; each has its own chip select.
- A slave drives MISO only while selected and ignores the bus otherwise.
- An oversampling slave detects SCLK edges in its own clock domain and mirrors the master's leading/trailing logic.
- The reply byte must be ready immediately after the last bit of the command.
- A daisy chain turns several devices into one long shift register with a shared chip select.