Altera® AXI4 Bus Functional Model User Guides

ID 838773
Date 5/19/2025
Public
Document Table of Contents

1.4.4. Altera® AXI4 Memory-Mapped Manager RTL Implementation Example

The following top_tb.sv testbench example uses axi_mgr_bfm and axi_sub_bfm IP-generated BFMs. You can generate simulation models and setup scripts by following the guidelines in Quartus® Prime Pro Edition User Guide: Third-party Simulation.

// top_tb.sv
`timescale 1 ns / 10 ps

module top_tb();
localparam real CLK_PERIOD = 10;

localparam ADDR_WIDTH = 64;
localparam DATA_WIDTH = 64;
localparam ID_WIDTH   = 8;
localparam USER_WIDTH = 32;

import altera_axi_bfm_pkg::*;
import host_memory_class_pkg::*;

// For simplicity, defining hierarchical names of manager and subordinate BFMs
// <bfm inst>.<inst> 
`define  mgr_bfm test_intf_m.axi4_mm_manager_intf_0 
`define  sub_bfm test_intf_s.axi4_mm_subordinate_intf_0 
// For simplicity, defining hierarchical names of subordinate host memory
// <bfm inst>.<inst>.host_memory
`define  sub_mem test_intf_s.axi4_mm_subordinate_intf_0.host_memory

bit clk, rstn;

wire [ID_WIDTH-1:0] awid;   
wire [ADDR_WIDTH-1:0] awaddr; 
wire [ 7:0] awlen;
wire [ 2:0] awsize;
wire [ 1:0] awburst;
wire [ 0:0] awvalid;
wire [ 0:0] awready;
wire [ 0:0] awlock;
//wire [ 3:0] awcache; 
wire [ 2:0] awprot;
//wire [ 3:0] awqos; 
wire [ 3:0] awregion;
wire [USER_WIDTH-1:0] awuser;
wire [DATA_WIDTH-1:0] wdata; 
wire [DATA_WIDTH/8-1:0] wstrb;	
wire [ 0:0] wlast;	
wire [USER_WIDTH-1:0] wuser; 
wire [ 0:0] wvalid;
wire [ 0:0] wready;
wire [ID_WIDTH-1:0] bid;	  
wire [ 1:0] bresp; 
wire [USER_WIDTH-1:0] buser; 
wire [ 0:0] bvalid;
wire [ 0:0] bready;	
wire [ID_WIDTH-1:0] arid;		
wire [ADDR_WIDTH-1:0] araddr; 	
wire [ 7:0] arlen; 	
wire [ 2:0] arsize; 	
wire [ 1:0] arburst; 	
wire [ 0:0] arlock;	
//wire [ 3:0] arcache; 	
wire [ 2:0] arprot;	
//wire [ 3:0] arqos;   	
wire [ 3:0] arregion;	
wire [USER_WIDTH-1:0] aruser;  	
wire [ 0:0] arvalid;	
wire [ 0:0] arready; 	
wire [ID_WIDTH-1:0] rid;		
wire [DATA_WIDTH-1:0] rdata; 	
wire [ 1:0] rresp; 	
wire [ 0:0] rlast; 	
wire [USER_WIDTH-1:0] ruser; 	
wire [ 0:0] rvalid;	
wire [ 0:0] rready;

// start toggling clock
always begin
	#(CLK_PERIOD/2) clk = ~clk;
end

initial begin
	rstn = 0;
	#10;
	repeat (1) @(posedge clk);
	rstn = 1;

end

axi_mgr_bfm test_intf_m(  // MAN instance interface
         .clk(clk),
			.rstn(rstn),		
			.awid(awid),
            .awaddr(awaddr),
            .awlen(awlen),
			.awsize(awsize),   
			.awburst(awburst),  
			.awlock(awlock),   
			//.awcache(awcache),  
			.awprot(awprot),   
			//.awqos(awqos),    
			.awregion(awregion), 
			.awuser(awuser),   
			.awvalid(awvalid),  
			.awready(awready),
			.wdata(wdata), 	
			.wstrb(wstrb),	
			.wlast(wlast),		
			.wuser(wuser), 	
			.wvalid(wvalid),	
			.wready(wready),	
			.bid(bid),		
			.bresp(bresp),		
			.buser(buser),		
			.bvalid(bvalid),	
			.bready(bready),	
			.arid(arid),		
			.araddr(araddr), 	
			.arlen(arlen), 	
			.arsize(arsize),
            .arburst(arburst), 	
			.arlock(arlock),	
			//.arcache(arcache), 	
			.arprot(arprot),	
			//.arqos(arqos),   	
			.arregion(arregion),	
			.aruser(aruser),  	
			.arvalid(arvalid),	
			.arready(arready), 	
			.rid(rid),		
			.rdata(rdata), 	
			.rresp(rresp), 	
			.rlast(rlast), 	
			.ruser(ruser), 	
			.rvalid(rvalid),	
			.rready(rready)	
); 
axi_sub_bfm test_intf_s(  //SUB instance interface
         .clk(clk),
			.rstn(rstn),		
			.awid(awid),
            .awaddr(awaddr),
            .awlen(awlen),
			.awsize(awsize),   
			.awburst(awburst),  
			.awlock(awlock),   
			//.awcache(awcache),  
			.awprot(awprot),   
			//.awqos(awqos),    
			.awregion(awregion), 
			.awuser(awuser),   
			.awvalid(awvalid),  
			.awready(awready),
			.wdata(wdata), 	
			.wstrb(wstrb),		
			.wlast(wlast),		
			.wuser(wuser), 	
			.wvalid(wvalid),	
			.wready(wready),	
			.bid(bid),		
			.bresp(bresp),		
			.buser(buser),		
			.bvalid(bvalid),	
			.bready(bready),	
			.arid(arid),		
			.araddr(araddr), 	
			.arlen(arlen), 	
			.arsize(arsize), 	
			.arburst(arburst), 
			.arlock(arlock),	
			//.arcache(arcache), 	
			.arprot(arprot),	
			//.arqos(arqos),   	
			.arregion(arregion),	
			.aruser(aruser),  	
			.arvalid(arvalid),	
			.arready(arready), 	
			.rid(rid),		
			.rdata(rdata), 	
			.rresp(rresp), 	
			.rlast(rlast), 	
			.ruser(ruser), 	
			.rvalid(rvalid),	
			.rready(rready)	
); 

// BFM Manager	 
initial begin 

// AXI Transactions 
AlteraAxiTransaction wr_tr, rd_tr;  

// Manager BFM 
BaseAxiBfm#(ADDR_WIDTH, DATA_WIDTH, ID_WIDTH, USER_WIDTH) axi_mgr_bfm; 
axi_mgr_bfm = `mgr_bfm.AXI4MAN.bfm; 

// Reset BFM  
axi_mgr_bfm.m_reset(); 

// Create Read Transaction and configure 
rd_tr = axi_mgr_bfm.manager_bfm_rd_tx(1, 0, 3, AXI4_BYTES_8, BURST_TYPE_INCR);

// id,  addr, burst_len, burst_size, burst_type

// Execute Read Transaction 
axi_mgr_bfm.put_transaction(rd_tr);  
axi_mgr_bfm.drive_transaction(); 

// Create Write Transaction 
wr_tr = axi_mgr_bfm.manager_bfm_wr_tx();    

// Configure Write Transaction 
wr_tr.set_id(1); 
wr_tr.set_awaddr(0); 
wr_tr.set_burst_length(3); 
wr_tr.set_size(AXI4_BYTES_8); 
wr_tr.set_burst_type(BURST_TYPE_INCR); 

wr_tr.set_data_words('haaaaaaaa_11111111, 0); // data, index 
wr_tr.set_data_words('hbbbbbbbb_22222222, 1);  
wr_tr.set_data_words('hcccccccc_33333333, 2);  
wr_tr.set_data_words('hdddddddd_44444444, 3); 
wr_tr.set_write_strobes(8'hff, 0); 		 //strobe, index 
wr_tr.set_write_strobes(8'hff, 1); 
wr_tr.set_write_strobes(8'hff, 2); 
wr_tr.set_write_strobes(8'hff, 3);  

// Execute Write Transaction 
axi_mgr_bfm.put_transaction(wr_tr);  
axi_mgr_bfm.drive_transaction(); 

// Execute Read Transaction 
rd_tr.set_id(2); 
axi_mgr_bfm.put_transaction(rd_tr);  
axi_mgr_bfm.drive_transaction(); 

$display("\n@ *************** END OF Write/Read TEST ***************\n"); 
end // Manager BFM 


// Subordinate BFM 
initial begin 
AlteraAxiTransaction wr_resp_tr, rd_resp_tr;  
byte_t init_buf[];  

// Subordinate BFM 
BaseAxiBfm#(ADDR_WIDTH, DATA_WIDTH, ID_WIDTH, USER_WIDTH) axi_sub_bfm; 
axi_sub_bfm = `sub_bfm.AXI4SUB.bfm; 

// Reset BFM 
axi_sub_bfm.s_reset();  

// Create response transactions 
wr_resp_tr = axi_sub_bfm.subordinate_bfm_wr_resp_tx();  
rd_resp_tr = axi_sub_bfm.subordinate_bfm_rd_resp_tx();  

fork  

   //Initialise the memory  

   init_buf = new[8];  
   init_buf = {<<byte_t{64'h0000_ffff_0000_ffff}}; 
   `sub_mem.initialize_data(0, init_buf);  
   init_buf = {<<byte_t{64'hffff_1111_ffff_1111}};  
   `sub_mem.initialize_data(8, init_buf);  
   init_buf = {<<byte_t{64'h2222_ffff_2222_ffff}};  
   `sub_mem.initialize_data(16, init_buf);  
   init_buf = {<<byte_t{64'h1111_2222_3333_4444}};  
   `sub_mem.initialize_data(24, init_buf); 

join  

fork  
   forever begin	 
   axi_sub_bfm.put_transaction(rd_resp_tr);  		    
   axi_sub_bfm.drive_transaction();    
   end 

   forever begin 
   axi_sub_bfm.put_transaction(wr_resp_tr); 	 		    
   axi_sub_bfm.drive_transaction();    
   end 

join  

end // Subordinate BFM 

endmodule: top_tb 

The following shows the simulation output from this example:

Figure 2. RTL Example Simulation Output