AHB Protocol - Complete Guide

The Advanced High-performance Bus (AHB) is a high-speed bus protocol designed for connecting high-bandwidth components like processors, memory controllers, and DMA controllers. This guide covers everything you need to know about AHB.

What is AHB?

AHB (Advanced High-performance Bus) is part of the AMBA (Advanced Microcontroller Bus Architecture) family developed by ARM. It's designed for high-bandwidth, high-clock frequency system buses in SoC designs.

Key Features of AHB

  • Pipelined operation - Address and data phases are separated, enabling higher throughput
  • Burst transfers - Multiple data transfers with single address phase
  • Split transactions - Allows slaves to free the bus during long operations
  • Single clock edge - All operations synchronized to rising edge
  • Multiplexed architecture - Shared address and data buses

Where is AHB Used?

AHB is commonly used to connect:

  • Processor cores (like ARM Cortex-M)
  • On-chip memory (SRAM, ROM)
  • DMA controllers
  • External memory interfaces
  • High-bandwidth peripherals

AHB Signals

Understanding AHB signals is fundamental to working with the protocol. Here's a complete list:

Global Signals

Signal Width Description
HCLK 1 System clock - all transfers sampled on rising edge
HRESETn 1 Active-low reset signal

Master Signals (Outputs from Master)

Signal Width Description
HADDR 32 Transfer address
HTRANS 2 Transfer type: IDLE(00), BUSY(01), NONSEQ(10), SEQ(11)
HWRITE 1 Write (1) or Read (0) transfer
HSIZE 3 Transfer size: 8/16/32/64/128/256/512/1024 bits
HBURST 3 Burst type: SINGLE, INCR, WRAP4, INCR4, etc.
HPROT 4 Protection control (opcode/data, privileged, bufferable, cacheable)
HWDATA 32/64 Write data bus

Slave Signals (Outputs from Slave)

Signal Width Description
HRDATA 32/64 Read data bus
HREADY 1 Transfer complete indicator
HRESP 2 Response: OKAY(00), ERROR(01), RETRY(10), SPLIT(11)

Transfer Types (HTRANS)

The HTRANS signal indicates the type of each transfer:

IDLE (2'b00)

No transfer required. Master uses this when it has nothing to transfer. Slave must respond with zero wait-state OKAY.

BUSY (2'b01)

Insert idle cycles in a burst. Master is not ready to continue the burst yet. Address/control must remain same as previous transfer.

NONSEQ (2'b10)

Non-sequential transfer - first transfer of a burst or single transfer. Address and control signals are unrelated to previous transfer.

SEQ (2'b11)

Sequential transfer - continuation of a burst. Address is related to previous transfer based on burst type.

HTRANS Encoding
// HTRANS encoding
typedef enum logic [1:0] {
    IDLE   = 2'b00,  // No transfer
    BUSY   = 2'b01,  // Burst pause
    NONSEQ = 2'b10,  // First/Single transfer
    SEQ    = 2'b11   // Burst continuation
} htrans_t;

Burst Types (HBURST)

AHB supports various burst types for efficient data transfer:

HBURST Type Beats Description
3'b000 SINGLE 1 Single transfer
3'b001 INCR Undefined Incrementing burst of unspecified length
3'b010 WRAP4 4 4-beat wrapping burst
3'b011 INCR4 4 4-beat incrementing burst
3'b100 WRAP8 8 8-beat wrapping burst
3'b101 INCR8 8 8-beat incrementing burst
3'b110 WRAP16 16 16-beat wrapping burst
3'b111 INCR16 16 16-beat incrementing burst

Incrementing vs Wrapping Bursts

Incrementing (INCR): Address increases by transfer size for each beat. For example, with HSIZE=2 (4 bytes): 0x100, 0x104, 0x108, 0x10C...

Wrapping (WRAP): Address wraps at a boundary. Useful for cache line fills. For WRAP4 with 4-byte transfers starting at 0x104: 0x104, 0x108, 0x10C, 0x100 (wraps back!).

Address Calculation for Bursts
// Calculate next address for burst
function automatic [31:0] next_burst_addr(
    input [31:0] current_addr,
    input [2:0]  hsize,
    input [2:0]  hburst
);
    int transfer_size = 2 ** hsize;  // Bytes per transfer
    int burst_length;
    int wrap_boundary;
    logic [31:0] next_addr;
    
    case (hburst)
        3'b010, 3'b011: burst_length = 4;
        3'b100, 3'b101: burst_length = 8;
        3'b110, 3'b111: burst_length = 16;
        default:        burst_length = 1;
    endcase
    
    next_addr = current_addr + transfer_size;
    
    // Check if wrapping burst
    if (hburst inside {3'b010, 3'b100, 3'b110}) begin
        wrap_boundary = burst_length * transfer_size;
        if ((next_addr % wrap_boundary) == 0)
            next_addr = current_addr - (burst_length - 1) * transfer_size;
    end
    
    return next_addr;
endfunction

Basic AHB Transfer

AHB uses a pipelined architecture with two phases:

  • Address Phase: Master drives address and control (HADDR, HTRANS, HWRITE, HSIZE, HBURST)
  • Data Phase: Data is transferred (HWDATA for write, HRDATA for read)
Simple AHB Write Transfer
// Simple AHB write - single cycle each phase
// Cycle 1: Address Phase
//   Master: HADDR=0x1000, HTRANS=NONSEQ, HWRITE=1
//   (Data phase of previous transfer, if any)

// Cycle 2: Data Phase of write
//   Master: HWDATA=0xDEADBEEF
//   Master: Next address (or HTRANS=IDLE)
//   Slave: HREADY=1 (transfer complete), HRESP=OKAY

// Timeline:
// CLK    : ____/‾‾‾‾\____/‾‾‾‾\____/‾‾‾‾\____
// HADDR  : --------------
// HTRANS : --------------
// HWRITE : ----<1       >----------
// HWDATA : --------------
// HREADY : ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

Complete AHB Master Example

Simple AHB Master Module
module ahb_master (
    input  logic        HCLK,
    input  logic        HRESETn,
    // AHB Master Interface
    output logic [31:0] HADDR,
    output logic [1:0]  HTRANS,
    output logic        HWRITE,
    output logic [2:0]  HSIZE,
    output logic [2:0]  HBURST,
    output logic [31:0] HWDATA,
    input  logic [31:0] HRDATA,
    input  logic        HREADY,
    input  logic [1:0]  HRESP,
    // Control Interface
    input  logic        start,
    input  logic [31:0] addr,
    input  logic [31:0] wdata,
    input  logic        write,
    output logic [31:0] rdata,
    output logic        done,
    output logic        error
);

    // FSM states
    typedef enum logic [1:0] {
        ST_IDLE   = 2'b00,
        ST_ADDR   = 2'b01,
        ST_DATA   = 2'b10
    } state_t;
    
    state_t state, next_state;
    logic [31:0] addr_reg, wdata_reg, rdata_reg;
    logic write_reg;
    
    // FSM
    always_ff @(posedge HCLK or negedge HRESETn) begin
        if (!HRESETn)
            state <= ST_IDLE;
        else
            state <= next_state;
    end
    
    // Next state logic
    always_comb begin
        next_state = state;
        case (state)
            ST_IDLE: if (start) next_state = ST_ADDR;
            ST_ADDR: if (HREADY) next_state = ST_DATA;
            ST_DATA: if (HREADY) next_state = ST_IDLE;
        endcase
    end
    
    // Register inputs
    always_ff @(posedge HCLK) begin
        if (start && state == ST_IDLE) begin
            addr_reg  <= addr;
            wdata_reg <= wdata;
            write_reg <= write;
        end
    end
    
    // AHB outputs
    always_comb begin
        HADDR  = addr_reg;
        HTRANS = (state == ST_ADDR) ? 2'b10 : 2'b00;  // NONSEQ or IDLE
        HWRITE = write_reg;
        HSIZE  = 3'b010;  // 32-bit
        HBURST = 3'b000;  // SINGLE
        HWDATA = wdata_reg;
    end
    
    // Capture read data
    always_ff @(posedge HCLK) begin
        if (state == ST_DATA && HREADY && !write_reg)
            rdata_reg <= HRDATA;
    end
    
    // Outputs
    assign rdata = rdata_reg;
    assign done  = (state == ST_DATA) && HREADY;
    assign error = (state == ST_DATA) && HREADY && (HRESP == 2'b01);
    
endmodule

Topics in This Section

Browse the sidebar to learn more about each AHB topic:

  • Basics - Signals, components, and fundamentals
  • Transfers - Basic, burst, pipelined, and wait-state transfers
  • Arbitration - Multi-master handling, locked and split transfers
  • Verification - Assertions, coverage, and VIP architecture

Common Interview Questions

  1. What is the difference between INCR and WRAP bursts?

    INCR bursts continuously increment the address. WRAP bursts wrap around at a boundary determined by the burst length and transfer size. WRAP is used for cache line fills where you want to fetch the critical word first.

  2. What are the four possible HRESP values and their meanings?

    OKAY (00) - Transfer successful. ERROR (01) - Transfer failed. RETRY (10) - Retry the transfer. SPLIT (11) - Split transfer, master should try other transfers.

  3. Why is AHB pipelined?

    Pipelining allows the address phase of the next transfer to overlap with the data phase of the current transfer, achieving higher throughput without increasing clock frequency.

  4. What happens when HREADY is low?

    The slave is inserting wait states. The master must maintain all control signals, and the transfer is extended until HREADY goes high.