Tutorial

Building a Multi-Master System with Axion Bridge & Cocotb

By Axion Team • 15 min read

Complex FPGA designs often require multiple distinct register spaces. In this tutorial, we'll generate two separate register modules using Axion-HDL, connect them using the axion-common bridge, and verify everything with Cocotb.

1. Define Register Spaces

We'll define two separate modules in YAML: master_ctrl (Base: 0x1000) and peripheral_status (Base: 0x2000).

master_ctrl.yaml

module: master_ctrl
base_addr: "0x1000"
registers:
  - name: bridge_enable
    addr: "0x00"

peripheral_status.yaml

module: peripheral_status
base_addr: "0x2000"
registers:
  - name: device_id
    addr: "0x00"
    access: RO

2. Generate Everything

$ axion-hdl -s src/ -o output/ --all

Found 2 modules: master_ctrl, peripheral_status
 master_ctrl_axion_reg.vhd
 peripheral_status_axion_reg.vhd

3. System Integration

We use the axi_lite_crossbar from the axion-common library to route traffic to the correct slave based on the address.

library axion_common;
use axion_common.axion_common_pkg.all;

-- ... Architecture ...

    -- Instantiate Axion Common Bridge
    inst_bridge : entity work.axion_axi_lite_bridge
        generic map (
            G_NUM_SLAVES => 2
            -- Address decoding handled by slave modules
        )
        port map (
            i_clk     => clk,
            i_rst_n   => rst_n,
            
            -- Upstream (Host)
            M_AXI_M2S => upstream_m2s,
            M_AXI_S2M => upstream_s2m,
            
            -- Downstream (Slaves)
            S_AXI_ARR_M2S => downstream_m2s,
            S_AXI_ARR_S2M => downstream_s2m
        );

4. Verification with Cocotb

We write a Python testbench to verify we can access both address spaces through the single slave interface.

@cocotb.test()
async def test_bridge_access(dut):
    # 1. Enable Bridge (0x1000)
    await axi_write(dut, 0x1000, 0x1)
    
    # 2. Read Device ID from Peripheral (0x2000)
    val = await axi_read(dut, 0x2000)
    assert val == 0xDEADBEEF
$ make simulation

     0.00ns INFO     Starting Bridge Test...
   150.00ns INFO     Writing to Bridge Enable (0x1000)...
   350.00ns INFO     Reading Device ID (0x2000)...
   650.00ns INFO     Device ID Verified: 0xdeadbeef
  1050.00ns INFO     test_bridge_access passed
Try it Now