A real AHB system has more than one slave: on-chip RAM, flash, an APB bridge, perhaps a memory controller. The decoder and the multiplexor connect them, and getting their timing right is the main design problem. The decoder works in the address phase, the multiplexor in the data phase, and an unmapped address needs a default slave. With more than one master, a multi-layer interconnect gives each master its own path. This article builds a single-master system with two RAMs and a default slave, then looks at multi-layer AHB.
9 min read | Intermediate
What You'll Learn
- Write an AHB address decoder and a data-phase multiplexor
- Explain why the multiplexor select must be registered
- Add a default slave for unmapped addresses
- Describe how a multi-layer interconnect supports several masters
The System
The fabric below connects one master to three slaves:
| Address range | Slave | Behaviour |
|---|---|---|
| 0x0000 - 0x03FF | RAM 0 | No wait states |
| 0x1000 - 0x13FF | RAM 1 | One wait state on the first beat of a burst |
| Everything else | Default slave | ERROR for NONSEQ and SEQ, OKAY for IDLE and BUSY |
The Decoder
The decoder is a combinational decode of the high address bits. Each slave owns at least 1 KB starting on a 1 KB boundary, so bits 31:10 are enough:
wire hsel_ram0 = (HADDR[31:10] == 22'h0); // 0x0000 - 0x03FF
wire hsel_ram1 = (HADDR[31:10] == 22'h4); // 0x1000 - 0x13FF
wire hsel_def = !hsel_ram0 && !hsel_ram1; // everything else
The 1 KB rule is what makes this simple. Because an incrementing burst never crosses a 1 KB boundary, all beats of a burst decode to the same slave, and no slave ever sees half a burst. The specification encourages simple decoding like this to keep it fast.
The Multiplexor and Its Select
The multiplexor returns HRDATA, HRESP and HREADYOUT of one slave to the master. Which slave? The one in the data phase. But HSEL follows HADDR, which already shows the next transfer. The decoder output must therefore be registered at the end of each address phase, which is every edge where HREADY is high:
reg [2:0] dsel; // which slave owns the data phase
always @(posedge HCLK) begin
if (!HRESETn)
dsel <= 3'b000;
else if (HREADY)
dsel <= {hsel_def, hsel_ram1, hsel_ram0};
end
assign HREADY = dsel[0] ? ready0 :
dsel[1] ? ready1 :
dsel[2] ? ready_d : 1'b1;
assign HRESP = dsel[0] ? resp0 :
dsel[1] ? resp1 :
dsel[2] ? resp_d : 1'b0;
assign HRDATA = dsel[0] ? rdata0 :
dsel[1] ? rdata1 : 32'h0;
Note that the multiplexor output HREADY feeds back into its own select register and into every slave. When no slave owns a data phase, such as after reset, HREADY is high so that the first transfer can start.
Quick Check
Q: What goes wrong if the multiplexor uses HSEL directly instead of the registered dsel?
Show Answer
In back-to-back transfers to different slaves, the master gets the response and read data of the slave in the address phase instead of the one in the data phase. A read from RAM 0 followed by an access to RAM 1 would return RAM 1's data, and RAM 1's HREADYOUT would decide whether the RAM 0 read is finished.
The Default Slave
If the memory map has gaps, the specification requires a default slave. Without one, an access to a gap selects nobody, and nobody drives HREADYOUT. The bus hangs or completes with garbage. The default slave answers NONSEQ and SEQ transfers with a two-cycle ERROR, and IDLE and BUSY with a zero-wait OKAY:
module ahb_default_slave (
input HCLK,
input HRESETn,
input HSEL,
input [1:0] HTRANS,
input HREADY,
output HREADYOUT,
output HRESP
);
reg err1;
reg err2;
always @(posedge HCLK) begin
if (!HRESETn) begin
err1 <= 1'b0;
err2 <= 1'b0;
end
else begin
err1 <= HREADY && HSEL && HTRANS[1];
err2 <= err1;
end
end
assign HREADYOUT = !err1;
assign HRESP = err1 || err2;
endmodule
The Simulation
The master writes and reads both RAMs, then reads 0x2000, which belongs to nobody, and finally reads RAM 0 again:
burst(1, SINGLE, 32'h0004, WORD, 1, 32'hD0); // RAM 0
burst(1, SINGLE, 32'h1004, WORD, 1, 32'hD1); // RAM 1: one wait state
burst(0, SINGLE, 32'h0004, WORD, 1, 0);
burst(0, SINGLE, 32'h1004, WORD, 1, 0);
burst(0, SINGLE, 32'h2000, WORD, 1, 0); // nothing here: default slave
burst(0, SINGLE, 32'h0004, WORD, 1, 0);
35 write 0x0004 = 0x000000d0 OKAY 55 write 0x1004 = 0x000000d1 OKAY 65 read 0x0004 = 0x000000d0 OKAY 85 read 0x1004 = 0x000000d1 OKAY 105 read 0x2000 = 0x00000000 ERROR 115 read 0x0004 = 0x000000d0 OKAY
In the waveform, each HSEL line rises together with the address it decodes. The multiplexor select follows one cycle later, when that transfer is in its data phase, and it does not move while RAM 1 holds HREADY low. The read of 0x2000 reaches the default slave and fails with a two-cycle ERROR; the master then carries on with the next transfer.
More Than One Master: Multi-Layer AHB
AHB-Lite has one master per bus. To connect a processor and a DMA engine, you use a multi-layer interconnect. Each master gets its own AHB-Lite layer into an interconnect matrix, and each slave port of the matrix has its own arbiter:
Two masters that want different slaves proceed at the same time, which a single shared bus could never do. Two masters that want the same slave are arbitrated at that slave's port, and the loser sees wait states on its own layer. From each slave's point of view nothing changed: it still sees one AHB-Lite transfer at a time.
A multi-layer interconnect may also end a burst early to let another master reach the slave, which is why a slave must work correctly when a burst is not completed. And when a slave can be reached by several masters, locked transfers matter: HMASTLOCK tells the interconnect not to let another master in between, for example during the read and write of a semaphore.
Quick Check
Q: In a multi-layer system, the processor reads flash while the DMA engine writes RAM. How many transfers can complete in one cycle?
Show Answer
Two, one on each layer, because they go to different slaves with different arbiters. On a single shared bus only one could complete.
Running It in ChipVerify Lab
The example contains the fabric with both RAMs and the default slave. Compare the HSEL lines with the multiplexor select in the waveform.
Common Mistakes
Mistake #1: Selecting the multiplexor with HSEL
The response must come from the slave in the data phase. Register the decoder output when HREADY is high and use that for the multiplexor.
Mistake #2: No default slave
A gap in the memory map with no default slave leaves the master waiting for an HREADYOUT that nobody drives. Always cover the whole address space.
Mistake #3: Slave regions smaller than 1 KB
A slave region smaller than 1 KB, or one that does not start on a 1 KB boundary, lets a legal burst run from one slave into the next. Keep regions at least 1 KB and 1 KB aligned.
Practice Exercise
Challenge: Just Past the End
Change the read of 0x2000 to a read of 0x1400. Which slave answers, and what is the result?
Hint
RAM 1 owns 0x1000 to 0x13FF. Work out HADDR[31:10] for 0x1400.
Solution
35 write 0x0004 = 0x000000d0 OKAY 55 write 0x1004 = 0x000000d1 OKAY 65 read 0x0004 = 0x000000d0 OKAY 85 read 0x1004 = 0x000000d1 OKAY 105 read 0x1400 = 0x00000000 ERROR 115 read 0x0004 = 0x000000d0 OKAY
HADDR[31:10] for 0x1400 is 5, not 4, so neither RAM is selected and the default slave answers with ERROR. The result is identical to the read of 0x2000: one address past the end of a region is just as unmapped as one far away.
Open the ready-made example in the lab and run the simulation.
Summary
- The decoder raises one
HSELper slave from the high address bits, in the address phase. - The multiplexor returns the response of the slave in the data phase, using a select registered when
HREADYis high. - A default slave answers unmapped addresses: ERROR for NONSEQ and SEQ, OKAY for IDLE and BUSY.
- Slave regions of at least 1 KB on 1 KB boundaries keep every burst inside one slave.
- Multi-layer AHB gives each master its own layer and each slave its own arbiter, so masters reach different slaves in parallel.