top of page

 APB protocol Test bench

In the last tutorial we learnt how to write a verilog code for APB protocol. 

Today we will write a testbench code to verify it. 

This testbench instantiates an APB interface module called "apb_interface", which is the design under test. It sets the inputs to the DUT, toggles the clock, generates test vectors, and verifies the expected outputs.

In the test vectors, the testbench writes to the APB slave by setting the APB address and data, and then reads from the APB slave by setting the APB address and setting the write signal to 0. It then waits for the APB to complete the transaction and verifies that the output matches the expected output.

​

Testbench Code for APB protocol:

​

`timescale 1ns / 1ps // Set the timescale for simulation

module apb_testbench;

// Inputs and outputs to the testbench
reg clk;
reg reset;
reg apb_psel;
reg apb_penable;
reg apb_pwrite;
reg [31:0] apb_paddr;
reg [31:0] apb_pwdata;
wire [31:0] apb_prdata;
wire apb_pready;
wire apb_pslverr;

// Instantiate the DUT module
apb_interface DUT (
  .clk(clk),
  .reset(reset),
  .apb_psel(apb_psel),
  .apb_penable(apb_penable),
  .apb_pwrite(apb_pwrite),
  .apb_paddr(apb_paddr),
  .apb_pwdata(apb_pwdata),
  .apb_prdata(apb_prdata),
  .apb_pready(apb_pready),
  .apb_pslverr(apb_pslverr)
);

// Initialize inputs to the DUT
initial begin
  clk = 0;
  reset = 0;
  apb_psel = 0;
  apb_penable = 0;
  apb_pwrite = 0;
  apb_paddr = 0;
  apb_pwdata = 0;
end

// Toggle the clock
always #10 clk = ~clk;

// Write test vectors
initial begin
  // Reset the DUT
  reset = 1;
  #10 reset = 0;

  // Write to the APB slave
  apb_psel = 1;
  apb_penable = 1;
  apb_pwrite = 1;
  apb_paddr = 32'h1000;
  apb_pwdata = 32'hABCD1234;
  #10;
  apb_penable = 0;
  #10;
  apb_psel = 0;

  // Read from the APB slave
  apb_psel = 1;
  apb_penable = 1;
  apb_pwrite = 0;
  apb_paddr = 32'h1000;
  #10;
  apb_penable = 0;
  #10;
  apb_psel = 0;

  // Wait for APB to complete transaction
  repeat (10) @(posedge clk);

  // Verify output
  if (apb_prdata !== 32'hABCD1234) $display("ERROR: Expected 32'hABCD1234, but got %h", apb_prdata);
end

endmodule
 

In addition to the basic write and read test vectors in the example code, here are some additional test vectors that you can add to further test the APB protocol:

  1. Multiple writes and reads: Instead of a single write and read, you can write multiple times to the APB slave, followed by multiple reads to verify the data. This will test the APB slave's ability to handle multiple transactions.

  2. Address and data boundary testing: Test the APB slave's ability to handle address and data boundaries by writing and reading at different address offsets and with different data sizes.

  3. Error testing: You can add test vectors that intentionally cause errors in the APB protocol, such as sending an invalid address or data, or toggling the enable signal too quickly. This will test the APB slave's ability to detect and handle errors.

  4. Stress testing: Test the APB slave's ability to handle high frequency transactions by generating a large number of transactions with different addresses and data. This will test the APB slave's performance and ability to handle a high load.

  5. Combination testing: Combine multiple test vectors to create complex test scenarios. For example, you can test a scenario where multiple transactions are happening simultaneously or where a read transaction is initiated before a write transaction is completed.

By adding these test vectors, you can thoroughly test the APB protocol and ensure that the design under test is robust and reliable.

​

For now we will try to cover different types of protocol and restrict ourselves from doing more robust testing. 

We will use System Verilog and UVM in the later tutorials to cover all the scenarios, write coverage, assertions and lot more. 

​

Keep Following this space for more updates. 

bottom of page