t27.aiEnglish

Дешифрация адреса

Вы узнаете

Сколько адресных бит стоит количество периферии и что проверяет стенд моста.

Адресация на APB — вопрос бит: сколько слуг сидит за мостом, столько бит дешифрация тратит. Спека отвечает по счёту — addr_bits_for_1_peripheral, addr_bits_for_4_peripherals, addr_bits_for_8_peripherals — а её тестбенч гоняет результат: test_reset_state, test_apb_write, test_apb_read, test_write_read_roundtrip, test_multiple_apb_writes, восемь тестов. Запись опускает тестбенч-спеку моста APB в Verilog.

Попробовать

В записи найдите тесты стенда; затем в спеке вычислите, сколько адресных бит спека тратит на 8 периферий.

Открыть интерактивный урок →

t27c gen-verilog on apb_bridge_tb.t27 -- the testbench as RTL
t27c gen-verilog on apb_bridge_tb.t27 -- the testbench as RTL ↗

The APB bridge testbench spec lowered to Verilog: what a bench looks like when the compiler emits it.

specs/fpga/testbench/apb_bridge_tb.t27

// SPDX-License-Identifier: Apache-2.0
// t27/specs/fpga/testbench/apb_bridge_tb.t27
// APB Bridge Testbench
// Tests APB bus protocol: setup, access, wait states
// phi^2 + 1/phi^2 = 3 | TRINITY

module APB_Bridge_Testbench {
    use fpga::apb_bridge::ApbBridge;

    const CLK_PERIOD : u32 = 20;
    const SIM_TIMEOUT : u32 = 5_000_000;
    const APB_ADDR_WIDTH : u32 = 12;
    const APB_DATA_WIDTH : u32 = 32;

    var clk : bool = false;
    var rst_n : bool = false;
    var psel : bool = false;
    var penable : bool = false;
    var pwrite : bool = false;
    var paddr : u32 = 0;
    var pwdata : u32 = 0;
    var prdata : u32 = 0;
    var pready : bool = false;
    var pslverr : bool = false;

    var test_passed : u32 = 0;
    var test_failed : u32 = 0;

    fn tick() {
        clk = false;
        clk = true;
    }

    fn reset() {
        rst_n = false;
        tick();
        tick();
        rst_n = true;
        tick();
    }

    fn apb_write(addr : u32, data : u32) -> bool {
        paddr = addr;
        pwdata = data;
        pwrite = true;
        psel = true;
        penable = false;
        tick();
        penable = true;
        tick();
        while !pready { tick(); }
        psel = false;
        penable = false;
        pwrite = false;
        return !pslverr;
    }

    fn apb_read(addr : u32) -> u32 {
        paddr = addr;
        pwrite = false;
        psel = true;
        penable = false;
        tick();
        penable = true;
        tick();
        while !pready { tick(); }
        var data : u32 = prdata;
        psel = false;
        penable = false;
        return data;
    }

    test test_reset_state {
        reset();
        invariant pready == true || pready == false;
        invariant pslverr == false;
    }

    test test_apb_write {
        reset();
        var ok : bool = apb_write(0x100, 0xDEAD);
        invariant ok == true;
        invariant pslverr == false;
    }

    test test_apb_read {
        reset();
        var val : u32 = apb_read(0x100);
        invariant pslverr == false;
    }

    test test_write_read_roundtrip {
        reset();
        apb_write(0x200, 0xCAFEBABE);
        var val : u32 = apb_read(0x200);
        invariant val == 0xCAFEBABE;
    }

    test test_multiple_apb_writes {
        reset();
        var i : u32 = 0;
        while i < 8 {
            apb_write(0x000 + i * 4, i * 0x10);
            i = i + 1;
        }
        i = 0;
        while i < 8 {
            var val : u32 = apb_read(0x000 + i * 4);
            invariant val == i * 0x10;
            i = i + 1;
        }
    }

    test test_protocol_phases {
        reset();
        psel = true;
        penable = false;
        tick();
        invariant psel == true;
        penable = true;
        tick();
        invariant penable == true;
        psel = false;
        penable = false;
    }

    invariant addr_width_valid : APB_ADDR_WIDTH > 0;
    invariant data_width_valid : APB_DATA_WIDTH == 32;

    test test_tick_functionality {
        reset();
        var initial_clk : bool = clk;
        tick();
        var after_tick_clk : bool = clk;
        invariant after_tick_clk != initial_clk;
    }

    bench bench_apb_throughput {
        reset();
        var i : u32 = 0;
        while i < 64 {
            apb_write(i * 4, i);
            i = i + 1;
        }
        i = 0;
        while i < 64 {
            apb_read(i * 4);
            i = i + 1;
        }
    }

    test "tick_function" {
        reset();
        var initial_clk : bool = clk;
        tick();
        invariant initial_clk != clk;
    }
}

Открыть спеку урока в плеере ↗

Все уроки