Initial commit
* Bare skeleton implementation of everything * Testbench builds with Verilator * Test runs
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | obj_dir | ||||||
|  | runs | ||||||
|  | logs | ||||||
							
								
								
									
										117
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | |||||||
|  | # Logging control | ||||||
|  | LOG_REDIR = >& | ||||||
|  | TIME=/usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]" | ||||||
|  |  | ||||||
|  | # Makefile variables | ||||||
|  | NUM_PROCS=$(shell nproc --all) | ||||||
|  | PROJ_BASE=$(shell pwd) | ||||||
|  |  | ||||||
|  | # Make and run project | ||||||
|  | UVM_HOME=$(HOME)/git/uvm-verilator | ||||||
|  | PROJ=axi | ||||||
|  |  | ||||||
|  | SV_OUT=obj_dir/Vuvm_pkg__verFiles.dat | ||||||
|  | SV_BUILD_LOG=logs/$(PROJ)_build_sv.log | ||||||
|  |  | ||||||
|  | CPP_OUT=$(PROJ).sim | ||||||
|  | CPP_BUILD_LOG=logs/$(PROJ)_build_cpp.log | ||||||
|  |  | ||||||
|  | SIM_LOG=$(PROJ)_sim.log | ||||||
|  |  | ||||||
|  | SV_FILES=$(shell ls common/* src/*.sv tb/*.sv) | ||||||
|  | SV_SRC=$(UVM_HOME)/src/uvm_pkg.sv common/common_pkg.sv src/design_pkg.sv tb/tb_types.sv tb/tb_pkg.sv | ||||||
|  | DPI_SRC=$(UVM_HOME)/src/dpi/uvm_dpi.cc | ||||||
|  | DPI_INC=-I/usr/share/verilator/include | ||||||
|  | SV_DEPS=$(SV_FILES) | ||||||
|  |  | ||||||
|  | CPP_SRC=sim_$(PROJ).cpp | ||||||
|  |  | ||||||
|  | TIMESCALE= --timescale '1ns/1ns' | ||||||
|  |  | ||||||
|  | UVM_DEFINES=+define+UVM_NO_DPI \ | ||||||
|  |             +define+UVM_REPORT_DISABLE_FILE_LINE | ||||||
|  | DISABLED_WARNINGS=-Wno-WIDTHTRUNC  -Wno-WIDTHEXPAND \ | ||||||
|  |                   -Wno-CASTCONST   -Wno-CONSTRAINTIGN \ | ||||||
|  |                   -Wno-MISINDENT   -Wno-REALCVT \ | ||||||
|  |                   -Wno-SYMRSVDWORD -Wno-CASEINCOMPLETE | ||||||
|  |  | ||||||
|  | BUILD_ARGS=-I$(UVM_HOME)/src -I. \ | ||||||
|  |         -o $(PROJ).sim \ | ||||||
|  |         -j $(NUM_PROCS) \ | ||||||
|  |         --error-limit 10 \ | ||||||
|  |         --timing $(TIMESCALE) \ | ||||||
|  |         --trace \ | ||||||
|  |         +define+SVA_ON \ | ||||||
|  |         $(UVM_DEFINES) \ | ||||||
|  |         $(DISABLED_WARNINGS) \ | ||||||
|  |         +incdir+common +incdir+src +incdir+tb \ | ||||||
|  |         $(SV_SRC) | ||||||
|  |  | ||||||
|  | ifndef TEST_NAME | ||||||
|  |     TEST_NAME=test_basic | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Full build to generate testbench executable (Default target) | ||||||
|  | # | ||||||
|  | build: build_cpp | ||||||
|  | 	@echo "Build done" | ||||||
|  |  | ||||||
|  | prepare_area: | ||||||
|  | 	$(info #----------------) | ||||||
|  | 	$(info # Preparing area) | ||||||
|  | 	$(info #----------------) | ||||||
|  | 	@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # C code generation from SystemVerilog | ||||||
|  | # | ||||||
|  | build_sv: prepare_area $(SV_OUT) | ||||||
|  |  | ||||||
|  | $(PROJ_BASE)/logs: | ||||||
|  | 	@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi | ||||||
|  |  | ||||||
|  | $(SV_OUT): $(PROJ_BASE)/logs $(SV_DEPS) | ||||||
|  | 	$(info #------------) | ||||||
|  | 	$(info # Building SV) | ||||||
|  | 	$(info #------------) | ||||||
|  | 	@verilator --cc $(BUILD_ARGS) | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # C code build to generate testbench executable | ||||||
|  | # | ||||||
|  | build_cpp: build_sv $(CPP_OUT) | ||||||
|  |  | ||||||
|  | $(CPP_OUT): $(SV_OUT) | ||||||
|  | 	$(info #-------------) | ||||||
|  | 	$(info # Building CPP) | ||||||
|  | 	$(info #-------------) | ||||||
|  | 	@verilator --binary $(BUILD_ARGS) | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Run just lint to detect syntax errors during development | ||||||
|  | # | ||||||
|  | lint: | ||||||
|  | 	$(info #--------) | ||||||
|  | 	$(info # Linting) | ||||||
|  | 	$(info #--------) | ||||||
|  | 	@verilator --lint-only $(BUILD_ARGS) | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Run test. Use TEST_NAME=<test name> on make line to pick the test | ||||||
|  | # | ||||||
|  | run: $(CPP_OUT) | ||||||
|  | 	$(info #---------------------) | ||||||
|  | 	$(info # Running $(TEST_NAME)) | ||||||
|  | 	$(info #---------------------) | ||||||
|  | 	@if [ ! -d runs/$(TEST_NAME) ]; then mkdir -p runs/$(TEST_NAME); fi | ||||||
|  | 	@cd runs/$(TEST_NAME) && \ | ||||||
|  |         $(PROJ_BASE)/obj_dir/$(PROJ).sim +UVM_TESTNAME=$(TEST_NAME) +UVM_CONFIG_DB_TRACE |& tee $(SIM_LOG) | ||||||
|  | 	notify-send "[$(PROJ)] Test run done" | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Remove generated files | ||||||
|  | # - This will not remove 'runs' directory that contains simulation run logs | ||||||
|  | # | ||||||
|  | clean: | ||||||
|  | 	rm -rf obj_dir logs $(PROJ)*.log | ||||||
							
								
								
									
										122
									
								
								Makefile.details
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								Makefile.details
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | |||||||
|  | # Logging control | ||||||
|  | ifdef VERBOSE | ||||||
|  | 	LOG_REDIR = |tee -a | ||||||
|  | 	TIME=stdbuf -o 0 /usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]" | ||||||
|  | else | ||||||
|  | 	LOG_REDIR = >& | ||||||
|  | 	TIME=/usr/bin/time --format "Elapsed: %E, Memory: %M KB [Swaps %W]" | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | # Makefile variables | ||||||
|  | NUM_PROCS=$(shell nproc --all) | ||||||
|  | PROJ_BASE=$(shell pwd) | ||||||
|  |  | ||||||
|  | # Make and run project | ||||||
|  | UVM_HOME=$(HOME)/git/uvm-verilator | ||||||
|  | PROJ=axi | ||||||
|  |  | ||||||
|  | SV_OUT=obj_dir/Vuvm_pkg__verFiles.dat | ||||||
|  | SV_BUILD_LOG=logs/$(PROJ)_build_sv.log | ||||||
|  |  | ||||||
|  | CPP_OUT=$(PROJ).sim | ||||||
|  | CPP_BUILD_LOG=logs/$(PROJ)_build_cpp.log | ||||||
|  |  | ||||||
|  | SIM_LOG=$(PROJ)_sim.log | ||||||
|  |  | ||||||
|  | SV_FILES=$(shell ls common/* src/*.sv tb/*.sv) | ||||||
|  | SV_SRC=$(UVM_HOME)/src/uvm_pkg.sv common/common_pkg.sv src/design_pkg.sv tb/tb_types.sv tb/tb_pkg.sv | ||||||
|  | DPI_SRC=$(UVM_HOME)/src/dpi/uvm_dpi.cc | ||||||
|  | DPI_INC=-I/usr/share/verilator/include | ||||||
|  | SV_DEPS=$(SV_FILES) | ||||||
|  |  | ||||||
|  | CPP_SRC=sim_$(PROJ).cpp | ||||||
|  |  | ||||||
|  | TIMESCALE= --timescale '1ns/1ns' | ||||||
|  |  | ||||||
|  | UVM_DEFINES=+define+UVM_NO_DPI \ | ||||||
|  |             +define+UVM_REPORT_DISABLE_FILE_LINE | ||||||
|  | DISABLED_WARNINGS=-Wno-WIDTHTRUNC  -Wno-WIDTHEXPAND \ | ||||||
|  |                   -Wno-CASTCONST   -Wno-CONSTRAINTIGN \ | ||||||
|  |                   -Wno-MISINDENT   -Wno-REALCVT \ | ||||||
|  |                   -Wno-SYMRSVDWORD -Wno-CASEINCOMPLETE | ||||||
|  |  | ||||||
|  | BUILD_ARGS=-I$(UVM_HOME)/src -I. \ | ||||||
|  |         -o $(PROJ).sim \ | ||||||
|  |         -j $(NUM_PROCS) \ | ||||||
|  |         --error-limit 10 \ | ||||||
|  |         --timing $(TIMESCALE) \ | ||||||
|  |         --trace \ | ||||||
|  |         +define+SVA_ON \ | ||||||
|  |         $(UVM_DEFINES) \ | ||||||
|  |         $(DISABLED_WARNINGS) \ | ||||||
|  |         +incdir+common +incdir+src +incdir+tb \ | ||||||
|  |         $(SV_SRC) | ||||||
|  |  | ||||||
|  | ifndef TEST_NAME | ||||||
|  |     TEST_NAME=test_basic | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Full build to generate testbench executable (Default target) | ||||||
|  | # | ||||||
|  | build: build_cpp | ||||||
|  | 	@echo "Build done" | ||||||
|  |  | ||||||
|  | prepare_area: | ||||||
|  | 	$(info #----------------) | ||||||
|  | 	$(info # Preparing area) | ||||||
|  | 	$(info #----------------) | ||||||
|  | 	@if [ ! -d $(PROJ_BASE)/logs ]; then mkdir -p $(PROJ_BASE)/logs; fi | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # C code generation from SystemVerilog | ||||||
|  | # | ||||||
|  | build_sv: prepare_area $(SV_OUT) | ||||||
|  |  | ||||||
|  | $(SV_OUT): $(PROJ_BASE)/logs $(SV_DEPS) | ||||||
|  | 	$(info #------------) | ||||||
|  | 	$(info # Building SV) | ||||||
|  | 	$(info #------------) | ||||||
|  | 	@$(TIME) verilator --cc $(BUILD_ARGS) $(LOG_REDIR) $(SV_BUILD_LOG) && \ | ||||||
|  | 		tail -1 $(SV_BUILD_LOG) | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # C code build to generate testbench executable | ||||||
|  | # | ||||||
|  | build_cpp: build_sv $(CPP_OUT) | ||||||
|  |  | ||||||
|  | $(CPP_OUT): $(SV_OUT) | ||||||
|  | 	$(info #-------------) | ||||||
|  | 	$(info # Building CPP) | ||||||
|  | 	$(info #-------------) | ||||||
|  | 	@$(TIME) verilator --binary $(BUILD_ARGS) $(LOG_REDIR) $(CPP_BUILD_LOG) && \ | ||||||
|  | 		tail -1 $(CPP_BUILD_LOG) && \ | ||||||
|  | 		notify-send "[$(PROJ)] Build done" | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Run just lint to detect syntax errors during development | ||||||
|  | # | ||||||
|  | lint: | ||||||
|  | 	$(info #--------) | ||||||
|  | 	$(info # Linting) | ||||||
|  | 	$(info #--------) | ||||||
|  | 	@$(TIME) verilator --lint-only $(BUILD_ARGS) | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Run test. Use TEST_NAME=<test name> on make line to pick the test | ||||||
|  | # | ||||||
|  | run: $(CPP_OUT) | ||||||
|  | 	$(info #---------------------) | ||||||
|  | 	$(info # Running $(TEST_NAME)) | ||||||
|  | 	$(info #---------------------) | ||||||
|  | 	@if [ ! -d runs/$(TEST_NAME) ]; then mkdir -p runs/$(TEST_NAME); fi | ||||||
|  | 	@cd runs/$(TEST_NAME) && \ | ||||||
|  |         $(TIME) $(PROJ_BASE)/obj_dir/$(PROJ).sim +UVM_TESTNAME=$(TEST_NAME) |& tee $(SIM_LOG) | ||||||
|  | 	@notify-send "[$(PROJ)] Test run done" | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # Remove generated files | ||||||
|  | # - This will not remove 'runs' directory that contains simulation run logs | ||||||
|  | # | ||||||
|  | clean: | ||||||
|  | 	rm -rf obj_dir logs $(PROJ)*.log | ||||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | # AXI Protocol Playground | ||||||
|  |  | ||||||
|  | ## Introduction | ||||||
|  |  | ||||||
|  | * There is no RTL design here. Just validation components working as both | ||||||
|  |   MANAGER and SUBORDINATE parts | ||||||
|  |  | ||||||
|  | ## Dependencies | ||||||
|  |  | ||||||
|  | * Verilator simulator | ||||||
|  | * UVM that works with Verilator | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | $ cd $UVM_HOME | ||||||
|  | $ git remote -v | ||||||
|  | origin  https://github.com/antmicro/uvm-verilator.git (fetch) | ||||||
|  | origin  https://github.com/antmicro/uvm-verilator.git (push) | ||||||
|  | $ git branch | ||||||
|  |   current-patches | ||||||
|  | * current-patches-2 | ||||||
|  | ``` | ||||||
							
								
								
									
										414
									
								
								common/axi.intf.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										414
									
								
								common/axi.intf.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,414 @@ | |||||||
|  | // Generated AXI Interface | ||||||
|  | // This file is automatically generated by scripts/gen_axi_intf.pl | ||||||
|  | // Do not edit this file directly. | ||||||
|  | // | ||||||
|  | // Interface Name: AXI Signal List | ||||||
|  | interface axi_intf #( | ||||||
|  |     parameter                          ADDR_WIDTH = 1, | ||||||
|  |     parameter                       ARSNOOP_WIDTH = 1, | ||||||
|  |     parameter                         AWCMO_WIDTH = 1, | ||||||
|  |     parameter                       AWSNOOP_WIDTH = 1, | ||||||
|  |     parameter                         BRESP_WIDTH = 1, | ||||||
|  |     parameter             CEIL_DATA_WIDTH_DIV_128 = 1, | ||||||
|  |     parameter       CEIL_DATA_WIDTH_DIV_128_TMS_4 = 1, | ||||||
|  |     parameter              CEIL_DATA_WIDTH_DIV_64 = 1, | ||||||
|  |     parameter                          DATA_WIDTH = 1, | ||||||
|  |     parameter                    DATA_WIDTH_DIV_8 = 1, | ||||||
|  |     parameter                          ID_R_WIDTH = 1, | ||||||
|  |     parameter                          ID_W_WIDTH = 1, | ||||||
|  |     parameter                        LOOP_R_WIDTH = 1, | ||||||
|  |     parameter                        LOOP_W_WIDTH = 1, | ||||||
|  |     parameter                         MECID_WIDTH = 1, | ||||||
|  |     parameter                          MPAM_WIDTH = 1, | ||||||
|  |     parameter                     RCHUNKNUM_WIDTH = 1, | ||||||
|  |     parameter                    RCHUNKSTRB_WIDTH = 1, | ||||||
|  |     parameter                         RRESP_WIDTH = 1, | ||||||
|  |     parameter                        SECSID_WIDTH = 1, | ||||||
|  |     parameter                           SID_WIDTH = 1, | ||||||
|  |     parameter                          SSID_WIDTH = 1, | ||||||
|  |     parameter                      SUBSYSID_WIDTH = 1, | ||||||
|  |     parameter SUM_USER_DATA_WIDTH_USER_RESP_WIDTH = 1, | ||||||
|  |     parameter                     USER_DATA_WIDTH = 1, | ||||||
|  |     parameter                      USER_REQ_WIDTH = 1, | ||||||
|  |     parameter                     USER_RESP_WIDTH = 1 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | ( | ||||||
|  |     input ACLK, | ||||||
|  |     input ARESETn | ||||||
|  | ); | ||||||
|  |  | ||||||
|  |     // A2.4.1 Clock and reset signals | ||||||
|  |     // External signal: ACLK;              // External Global clock signal [External] | ||||||
|  |     // External signal: ARESETn;           // External Global reset signal [External] | ||||||
|  |  | ||||||
|  |     // A2.1.1 Write request channel | ||||||
|  |     logic                                           AWVALID;           // Valid indicator [Manager] | ||||||
|  |     logic                                           AWREADY;           // Ready indicator [Subordinate] | ||||||
|  |     logic                          [ID_W_WIDTH-1:0] AWID;              // Transaction identifier for the write channels [Manager] | ||||||
|  |     logic                          [ADDR_WIDTH-1:0] AWADDR;            // Transaction address [Manager] | ||||||
|  |     logic                                     [3:0] AWREGION;          // Region identifier [Manager] | ||||||
|  |     logic                                     [7:0] AWLEN;             // Transaction length [Manager] | ||||||
|  |     logic                                     [2:0] AWSIZE;            // Transaction size [Manager] | ||||||
|  |     logic                                     [1:0] AWBURST;           // Burst attribute [Manager] | ||||||
|  |     logic                                           AWLOCK;            // Exclusive access indicator [Manager] | ||||||
|  |     logic                                     [3:0] AWCACHE;           // Memory attributes [Manager] | ||||||
|  |     logic                                     [2:0] AWPROT;            // Access attributes [Manager] | ||||||
|  |     logic                                           AWNSE;             // Non-secure extension bit for RME [Manager] | ||||||
|  |     logic                                     [3:0] AWQOS;             // QoS identifier [Manager] | ||||||
|  |     logic                      [USER_REQ_WIDTH-1:0] AWUSER;            // User-defined extension to a request [Manager] | ||||||
|  |     logic                                     [1:0] AWDOMAIN;          // Shareability domain of a request [Manager] | ||||||
|  |     logic                       [AWSNOOP_WIDTH-1:0] AWSNOOP;           // Write request opcode [Manager] | ||||||
|  |     logic                                    [10:0] AWSTASHNID;        // Stash Node ID [Manager] | ||||||
|  |     logic                                           AWSTASHNIDEN;      // Stash Node ID enable [Manager] | ||||||
|  |     logic                                     [4:0] AWSTASHLPID;       // Stash Logical Processor ID [Manager] | ||||||
|  |     logic                                           AWSTASHLPIDEN;     // Stash Logical Processor ID enable [Manager] | ||||||
|  |     logic                                           AWTRACE;           // Trace signal [Manager] | ||||||
|  |     logic                        [LOOP_W_WIDTH-1:0] AWLOOP;            // Loopback signals on the write channels [Manager] | ||||||
|  |     logic                                           AWMMUVALID;        // MMU signal qualifier [Manager] | ||||||
|  |     logic                        [SECSID_WIDTH-1:0] AWMMUSECSID;       // Secure Stream ID [Manager] | ||||||
|  |     logic                           [SID_WIDTH-1:0] AWMMUSID;          // StreamID [Manager] | ||||||
|  |     logic                                           AWMMUSSIDV;        // SubstreamID valid [Manager] | ||||||
|  |     logic                          [SSID_WIDTH-1:0] AWMMUSSID;         // SubstreamID [Manager] | ||||||
|  |     logic                                           AWMMUATST;         // Address translated indicator [Manager] | ||||||
|  |     logic                                     [1:0] AWMMUFLOW;         // SMMU flow type [Manager] | ||||||
|  |     logic                                     [3:0] AWPBHA;            // Page-based Hardware Attributes [Manager] | ||||||
|  |     logic                                     [3:0] AWNSAID;           // Non-secure Access ID [Manager] | ||||||
|  |     logic                      [SUBSYSID_WIDTH-1:0] AWSUBSYSID;        // Subsystem ID [Manager] | ||||||
|  |     logic                                     [5:0] AWATOP;            // Atomic transaction opcode [Manager] | ||||||
|  |     logic                          [MPAM_WIDTH-1:0] AWMPAM;            // MPAM information with a request [Manager] | ||||||
|  |     logic                                           AWIDUNQ;           // Unique ID indicator [Manager] | ||||||
|  |     logic                         [AWCMO_WIDTH-1:0] AWCMO;             // CMO type [Manager] | ||||||
|  |     logic                                     [1:0] AWTAGOP;           // Memory Tag operation for write requests [Manager] | ||||||
|  |     logic                         [MECID_WIDTH-1:0] AWMECID;           // Memory Encryption Context identifier [Manager] | ||||||
|  |  | ||||||
|  |     // A2.1.1 Write request channel | ||||||
|  |     logic                                           WVALID;            // Valid indicator [Manager] | ||||||
|  |     logic                                           WREADY;            // Ready indicator [Subordinate] | ||||||
|  |     logic                          [DATA_WIDTH-1:0] WDATA;             // Write data [Manager] | ||||||
|  |     logic                    [DATA_WIDTH_DIV_8-1:0] WSTRB;             // Write data strobes [Manager] | ||||||
|  |     logic       [CEIL_DATA_WIDTH_DIV_128_TMS_4-1:0] WTAG;              // Memory Tag [Manager] | ||||||
|  |     logic             [CEIL_DATA_WIDTH_DIV_128-1:0] WTAGUPDATE;        // Memory Tag update [Manager] | ||||||
|  |     logic                                           WLAST;             // Last write data [Manager] | ||||||
|  |     logic                     [USER_DATA_WIDTH-1:0] WUSER;             // User-defined extension to write data [Manager] | ||||||
|  |     logic              [CEIL_DATA_WIDTH_DIV_64-1:0] WPOISON;           // Poison indicator [Manager] | ||||||
|  |     logic                                           WTRACE;            // Trace signal [Manager] | ||||||
|  |  | ||||||
|  |     // A2.1.3 Write response channel | ||||||
|  |     logic                                           BVALID;            // Valid indicator [Subordinate] | ||||||
|  |     logic                                           BREADY;            // Ready indicator [Manager] | ||||||
|  |     logic                          [ID_W_WIDTH-1:0] BID;               // Transaction identifier for the write channels [Subordinate] | ||||||
|  |     logic                                           BIDUNQ;            // Unique ID indicator [Subordinate] | ||||||
|  |     logic                         [BRESP_WIDTH-1:0] BRESP;             // Write response code [Subordinate] | ||||||
|  |     logic                                           BCOMP;             // Completion response indicator [Subordinate] | ||||||
|  |     logic                                           BPERSIST;          // Persist response [Subordinate] | ||||||
|  |     logic                                     [1:0] BTAGMATCH;         // Memory Tag Match response [Subordinate] | ||||||
|  |     logic                     [USER_RESP_WIDTH-1:0] BUSER;             // User-defined extension to a write response [Subordinate] | ||||||
|  |     logic                                           BTRACE;            // Trace signal [Subordinate] | ||||||
|  |     logic                        [LOOP_W_WIDTH-1:0] BLOOP;             // Loopback signals on the write channels [Subordinate] | ||||||
|  |     logic                                     [1:0] BBUSY;             // Busy indicator [Subordinate] | ||||||
|  |  | ||||||
|  |     // A2.2.1 Read request channel | ||||||
|  |     logic                                           ARVALID;           // Valid indicator [Manager] | ||||||
|  |     logic                                           ARREADY;           // Ready indicator [Subordinate] | ||||||
|  |     logic                          [ID_R_WIDTH-1:0] ARID;              // Transaction identifier for the read channels [Manager] | ||||||
|  |     logic                          [ADDR_WIDTH-1:0] ARADDR;            // Transaction address [Manager] | ||||||
|  |     logic                                     [3:0] ARREGION;          // Region identifier [Manager] | ||||||
|  |     logic                                     [7:0] ARLEN;             // Transaction length [Manager] | ||||||
|  |     logic                                     [2:0] ARSIZE;            // Transaction size [Manager] | ||||||
|  |     logic                                     [1:0] ARBURST;           // Burst attribute [Manager] | ||||||
|  |     logic                                           ARLOCK;            // Exclusive access indicator [Manager] | ||||||
|  |     logic                                     [3:0] ARCACHE;           // Memory attributes [Manager] | ||||||
|  |     logic                                     [2:0] ARPROT;            // Access attributes [Manager] | ||||||
|  |     logic                                           ARNSE;             // Non-secure extension bit for RME [Manager] | ||||||
|  |     logic                                     [3:0] ARQOS;             // QoS identifier [Manager] | ||||||
|  |     logic                      [USER_REQ_WIDTH-1:0] ARUSER;            // User-defined extension to a request [Manager] | ||||||
|  |     logic                                     [1:0] ARDOMAIN;          // Shareability domain of a request [Manager] | ||||||
|  |     logic                       [ARSNOOP_WIDTH-1:0] ARSNOOP;           // Read request opcode [Manager] | ||||||
|  |     logic                                           ARTRACE;           // Trace signal [Manager] | ||||||
|  |     logic                        [LOOP_R_WIDTH-1:0] ARLOOP;            // Loopback signals on the read channels [Manager] | ||||||
|  |     logic                                           ARMMUVALID;        // MMU signal qualifier [Manager] | ||||||
|  |     logic                        [SECSID_WIDTH-1:0] ARMMUSECSID;       // Secure Stream ID [Manager] | ||||||
|  |     logic                           [SID_WIDTH-1:0] ARMMUSID;          // StreamID [Manager] | ||||||
|  |     logic                                           ARMMUSSIDV;        // SubstreamID valid [Manager] | ||||||
|  |     logic                          [SSID_WIDTH-1:0] ARMMUSSID;         // SubstreamID [Manager] | ||||||
|  |     logic                                           ARMMUATST;         // Address translated indicator [Manager] | ||||||
|  |     logic                                     [1:0] ARMMUFLOW;         // SMMU flow type [Manager] | ||||||
|  |     logic                                     [3:0] ARPBHA;            // Page-based Hardware Attributes [Manager] | ||||||
|  |     logic                                     [3:0] ARNSAID;           // Non-secure Access ID [Manager] | ||||||
|  |     logic                      [SUBSYSID_WIDTH-1:0] ARSUBSYSID;        // Subsystem ID [Manager] | ||||||
|  |     logic                                           ARCHUNKEN;         // Read data chunking enable [Manager] | ||||||
|  |     logic                                           ARIDUNQ;           // Unique ID indicator [Manager] | ||||||
|  |     logic                                     [1:0] ARTAGOP;           // Memory Tag operation for read requests [Manager] | ||||||
|  |     logic                         [MECID_WIDTH-1:0] ARMECID;           // Memory Encryption Context identifier [Manager] | ||||||
|  |  | ||||||
|  |     // A2.2.2 Read data channel | ||||||
|  |     logic                                           RVALID;            // Valid indicator [Subordinate] | ||||||
|  |     logic                                           RREADY;            // Ready indicator [Manager] | ||||||
|  |     logic                          [ID_R_WIDTH-1:0] RID;               // Transaction identifier for the read channels [Subordinate] | ||||||
|  |     logic                                           RIDUNQ;            // Unique ID indicator [Subordinate] | ||||||
|  |     logic                          [DATA_WIDTH-1:0] RDATA;             // Read data [Subordinate] | ||||||
|  |     logic       [CEIL_DATA_WIDTH_DIV_128_TMS_4-1:0] RTAG;              // Memory Tag [Subordinate] | ||||||
|  |     logic                         [RRESP_WIDTH-1:0] RRESP;             // Read response [Subordinate] | ||||||
|  |     logic                                           RLAST;             // Last read data [Subordinate] | ||||||
|  |     logic [SUM_USER_DATA_WIDTH_USER_RESP_WIDTH-1:0] RUSER;             // User-defined extension to read data and response [Subordinate] | ||||||
|  |     logic              [CEIL_DATA_WIDTH_DIV_64-1:0] RPOISON;           // Poison indicator [Subordinate] | ||||||
|  |     logic                                           RTRACE;            // Trace signal [Subordinate] | ||||||
|  |     logic                        [LOOP_R_WIDTH-1:0] RLOOP;             // Loopback signals on the read channels [Subordinate] | ||||||
|  |     logic                                           RCHUNKV;           // Read data chunking valid [Subordinate] | ||||||
|  |     logic                     [RCHUNKNUM_WIDTH-1:0] RCHUNKNUM;         // Read data chunk number [Subordinate] | ||||||
|  |     logic                    [RCHUNKSTRB_WIDTH-1:0] RCHUNKSTRB;        // Read data chunk strobe [Subordinate] | ||||||
|  |     logic                                     [1:0] RBUSY;             // Busy indicator [Subordinate] | ||||||
|  |  | ||||||
|  |     // Modport for Manager role | ||||||
|  |     modport MANAGER ( | ||||||
|  |  | ||||||
|  |         // A2.4.1 Clock and reset signals | ||||||
|  |         input    ACLK, | ||||||
|  |         input    ARESETn, | ||||||
|  |  | ||||||
|  |         // A2.1.1 Write request channel | ||||||
|  |         output   AWVALID, | ||||||
|  |         input    AWREADY, | ||||||
|  |         output   AWID, | ||||||
|  |         output   AWADDR, | ||||||
|  |         output   AWREGION, | ||||||
|  |         output   AWLEN, | ||||||
|  |         output   AWSIZE, | ||||||
|  |         output   AWBURST, | ||||||
|  |         output   AWLOCK, | ||||||
|  |         output   AWCACHE, | ||||||
|  |         output   AWPROT, | ||||||
|  |         output   AWNSE, | ||||||
|  |         output   AWQOS, | ||||||
|  |         output   AWUSER, | ||||||
|  |         output   AWDOMAIN, | ||||||
|  |         output   AWSNOOP, | ||||||
|  |         output   AWSTASHNID, | ||||||
|  |         output   AWSTASHNIDEN, | ||||||
|  |         output   AWSTASHLPID, | ||||||
|  |         output   AWSTASHLPIDEN, | ||||||
|  |         output   AWTRACE, | ||||||
|  |         output   AWLOOP, | ||||||
|  |         output   AWMMUVALID, | ||||||
|  |         output   AWMMUSECSID, | ||||||
|  |         output   AWMMUSID, | ||||||
|  |         output   AWMMUSSIDV, | ||||||
|  |         output   AWMMUSSID, | ||||||
|  |         output   AWMMUATST, | ||||||
|  |         output   AWMMUFLOW, | ||||||
|  |         output   AWPBHA, | ||||||
|  |         output   AWNSAID, | ||||||
|  |         output   AWSUBSYSID, | ||||||
|  |         output   AWATOP, | ||||||
|  |         output   AWMPAM, | ||||||
|  |         output   AWIDUNQ, | ||||||
|  |         output   AWCMO, | ||||||
|  |         output   AWTAGOP, | ||||||
|  |         output   AWMECID, | ||||||
|  |  | ||||||
|  |         // A2.1.1 Write request channel | ||||||
|  |         output   WVALID, | ||||||
|  |         input    WREADY, | ||||||
|  |         output   WDATA, | ||||||
|  |         output   WSTRB, | ||||||
|  |         output   WTAG, | ||||||
|  |         output   WTAGUPDATE, | ||||||
|  |         output   WLAST, | ||||||
|  |         output   WUSER, | ||||||
|  |         output   WPOISON, | ||||||
|  |         output   WTRACE, | ||||||
|  |  | ||||||
|  |         // A2.1.3 Write response channel | ||||||
|  |         input    BVALID, | ||||||
|  |         output   BREADY, | ||||||
|  |         input    BID, | ||||||
|  |         input    BIDUNQ, | ||||||
|  |         input    BRESP, | ||||||
|  |         input    BCOMP, | ||||||
|  |         input    BPERSIST, | ||||||
|  |         input    BTAGMATCH, | ||||||
|  |         input    BUSER, | ||||||
|  |         input    BTRACE, | ||||||
|  |         input    BLOOP, | ||||||
|  |         input    BBUSY, | ||||||
|  |  | ||||||
|  |         // A2.2.1 Read request channel | ||||||
|  |         output   ARVALID, | ||||||
|  |         input    ARREADY, | ||||||
|  |         output   ARID, | ||||||
|  |         output   ARADDR, | ||||||
|  |         output   ARREGION, | ||||||
|  |         output   ARLEN, | ||||||
|  |         output   ARSIZE, | ||||||
|  |         output   ARBURST, | ||||||
|  |         output   ARLOCK, | ||||||
|  |         output   ARCACHE, | ||||||
|  |         output   ARPROT, | ||||||
|  |         output   ARNSE, | ||||||
|  |         output   ARQOS, | ||||||
|  |         output   ARUSER, | ||||||
|  |         output   ARDOMAIN, | ||||||
|  |         output   ARSNOOP, | ||||||
|  |         output   ARTRACE, | ||||||
|  |         output   ARLOOP, | ||||||
|  |         output   ARMMUVALID, | ||||||
|  |         output   ARMMUSECSID, | ||||||
|  |         output   ARMMUSID, | ||||||
|  |         output   ARMMUSSIDV, | ||||||
|  |         output   ARMMUSSID, | ||||||
|  |         output   ARMMUATST, | ||||||
|  |         output   ARMMUFLOW, | ||||||
|  |         output   ARPBHA, | ||||||
|  |         output   ARNSAID, | ||||||
|  |         output   ARSUBSYSID, | ||||||
|  |         output   ARCHUNKEN, | ||||||
|  |         output   ARIDUNQ, | ||||||
|  |         output   ARTAGOP, | ||||||
|  |         output   ARMECID, | ||||||
|  |  | ||||||
|  |         // A2.2.2 Read data channel | ||||||
|  |         input    RVALID, | ||||||
|  |         output   RREADY, | ||||||
|  |         input    RID, | ||||||
|  |         input    RIDUNQ, | ||||||
|  |         input    RDATA, | ||||||
|  |         input    RTAG, | ||||||
|  |         input    RRESP, | ||||||
|  |         input    RLAST, | ||||||
|  |         input    RUSER, | ||||||
|  |         input    RPOISON, | ||||||
|  |         input    RTRACE, | ||||||
|  |         input    RLOOP, | ||||||
|  |         input    RCHUNKV, | ||||||
|  |         input    RCHUNKNUM, | ||||||
|  |         input    RCHUNKSTRB, | ||||||
|  |         input    RBUSY | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // Modport for Subordinate role | ||||||
|  |     modport SUBORDINATE ( | ||||||
|  |  | ||||||
|  |         // A2.4.1 Clock and reset signals | ||||||
|  |         input    ACLK, | ||||||
|  |         input    ARESETn, | ||||||
|  |  | ||||||
|  |         // A2.1.1 Write request channel | ||||||
|  |         input    AWVALID, | ||||||
|  |         output   AWREADY, | ||||||
|  |         input    AWID, | ||||||
|  |         input    AWADDR, | ||||||
|  |         input    AWREGION, | ||||||
|  |         input    AWLEN, | ||||||
|  |         input    AWSIZE, | ||||||
|  |         input    AWBURST, | ||||||
|  |         input    AWLOCK, | ||||||
|  |         input    AWCACHE, | ||||||
|  |         input    AWPROT, | ||||||
|  |         input    AWNSE, | ||||||
|  |         input    AWQOS, | ||||||
|  |         input    AWUSER, | ||||||
|  |         input    AWDOMAIN, | ||||||
|  |         input    AWSNOOP, | ||||||
|  |         input    AWSTASHNID, | ||||||
|  |         input    AWSTASHNIDEN, | ||||||
|  |         input    AWSTASHLPID, | ||||||
|  |         input    AWSTASHLPIDEN, | ||||||
|  |         input    AWTRACE, | ||||||
|  |         input    AWLOOP, | ||||||
|  |         input    AWMMUVALID, | ||||||
|  |         input    AWMMUSECSID, | ||||||
|  |         input    AWMMUSID, | ||||||
|  |         input    AWMMUSSIDV, | ||||||
|  |         input    AWMMUSSID, | ||||||
|  |         input    AWMMUATST, | ||||||
|  |         input    AWMMUFLOW, | ||||||
|  |         input    AWPBHA, | ||||||
|  |         input    AWNSAID, | ||||||
|  |         input    AWSUBSYSID, | ||||||
|  |         input    AWATOP, | ||||||
|  |         input    AWMPAM, | ||||||
|  |         input    AWIDUNQ, | ||||||
|  |         input    AWCMO, | ||||||
|  |         input    AWTAGOP, | ||||||
|  |         input    AWMECID, | ||||||
|  |  | ||||||
|  |         // A2.1.1 Write request channel | ||||||
|  |         input    WVALID, | ||||||
|  |         output   WREADY, | ||||||
|  |         input    WDATA, | ||||||
|  |         input    WSTRB, | ||||||
|  |         input    WTAG, | ||||||
|  |         input    WTAGUPDATE, | ||||||
|  |         input    WLAST, | ||||||
|  |         input    WUSER, | ||||||
|  |         input    WPOISON, | ||||||
|  |         input    WTRACE, | ||||||
|  |  | ||||||
|  |         // A2.1.3 Write response channel | ||||||
|  |         output   BVALID, | ||||||
|  |         input    BREADY, | ||||||
|  |         output   BID, | ||||||
|  |         output   BIDUNQ, | ||||||
|  |         output   BRESP, | ||||||
|  |         output   BCOMP, | ||||||
|  |         output   BPERSIST, | ||||||
|  |         output   BTAGMATCH, | ||||||
|  |         output   BUSER, | ||||||
|  |         output   BTRACE, | ||||||
|  |         output   BLOOP, | ||||||
|  |         output   BBUSY, | ||||||
|  |  | ||||||
|  |         // A2.2.1 Read request channel | ||||||
|  |         input    ARVALID, | ||||||
|  |         output   ARREADY, | ||||||
|  |         input    ARID, | ||||||
|  |         input    ARADDR, | ||||||
|  |         input    ARREGION, | ||||||
|  |         input    ARLEN, | ||||||
|  |         input    ARSIZE, | ||||||
|  |         input    ARBURST, | ||||||
|  |         input    ARLOCK, | ||||||
|  |         input    ARCACHE, | ||||||
|  |         input    ARPROT, | ||||||
|  |         input    ARNSE, | ||||||
|  |         input    ARQOS, | ||||||
|  |         input    ARUSER, | ||||||
|  |         input    ARDOMAIN, | ||||||
|  |         input    ARSNOOP, | ||||||
|  |         input    ARTRACE, | ||||||
|  |         input    ARLOOP, | ||||||
|  |         input    ARMMUVALID, | ||||||
|  |         input    ARMMUSECSID, | ||||||
|  |         input    ARMMUSID, | ||||||
|  |         input    ARMMUSSIDV, | ||||||
|  |         input    ARMMUSSID, | ||||||
|  |         input    ARMMUATST, | ||||||
|  |         input    ARMMUFLOW, | ||||||
|  |         input    ARPBHA, | ||||||
|  |         input    ARNSAID, | ||||||
|  |         input    ARSUBSYSID, | ||||||
|  |         input    ARCHUNKEN, | ||||||
|  |         input    ARIDUNQ, | ||||||
|  |         input    ARTAGOP, | ||||||
|  |         input    ARMECID, | ||||||
|  |  | ||||||
|  |         // A2.2.2 Read data channel | ||||||
|  |         output   RVALID, | ||||||
|  |         input    RREADY, | ||||||
|  |         output   RID, | ||||||
|  |         output   RIDUNQ, | ||||||
|  |         output   RDATA, | ||||||
|  |         output   RTAG, | ||||||
|  |         output   RRESP, | ||||||
|  |         output   RLAST, | ||||||
|  |         output   RUSER, | ||||||
|  |         output   RPOISON, | ||||||
|  |         output   RTRACE, | ||||||
|  |         output   RLOOP, | ||||||
|  |         output   RCHUNKV, | ||||||
|  |         output   RCHUNKNUM, | ||||||
|  |         output   RCHUNKSTRB, | ||||||
|  |         output   RBUSY | ||||||
|  |     ); | ||||||
|  | endinterface // axi_intf | ||||||
							
								
								
									
										3
									
								
								common/common_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								common/common_pkg.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | `include "axi.intf.sv" | ||||||
|  | package common_pkg; | ||||||
|  | endpackage | ||||||
							
								
								
									
										336
									
								
								scripts/gen_axi_intf.pl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										336
									
								
								scripts/gen_axi_intf.pl
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,336 @@ | |||||||
|  | #!/usr/bin/env perl | ||||||
|  | use strict; | ||||||
|  | use warnings; | ||||||
|  | use Data::Dumper; | ||||||
|  |  | ||||||
|  | my $app = {}; | ||||||
|  |  | ||||||
|  | get_axi_intf_data($app); | ||||||
|  | augment_intf_data($app); | ||||||
|  | #print Dumper($app->{'intf_data'}); # Debugging output | ||||||
|  |  | ||||||
|  | gen_intf($app); | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | # Subroutines | ||||||
|  | # ----------------- | ||||||
|  | sub gen_intf { | ||||||
|  |     my ($app) = @_; | ||||||
|  |  | ||||||
|  |     print "// Generated AXI Interface\n"; | ||||||
|  |     print "// This file is automatically generated by $0\n"; | ||||||
|  |     print "// Do not edit this file directly.\n"; | ||||||
|  |     print "//\n"; | ||||||
|  |     print "// Interface Name: $app->{'intf_data'}->{'name'}\n"; | ||||||
|  |     print "interface axi_intf #(\n"; | ||||||
|  |  | ||||||
|  |     my @plines = get_param_lines($app); | ||||||
|  |     print join(",\n", @plines); | ||||||
|  |     print "\n)\n"; | ||||||
|  |     my @eplines = get_ext_ports_lines($app); | ||||||
|  |     print "\n(\n"; | ||||||
|  |     print join(",\n", @eplines); | ||||||
|  |     print "\n);\n"; | ||||||
|  |  | ||||||
|  |     show_interface($app); | ||||||
|  |  | ||||||
|  |     show_modport($app, 'Manager'); | ||||||
|  |     show_modport($app, 'Subordinate'); | ||||||
|  |  | ||||||
|  |     print "endinterface // axi_intf\n"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub get_param_lines { | ||||||
|  |     my ($app) = @_; | ||||||
|  |     my @plines; | ||||||
|  |  | ||||||
|  |     foreach my $p (sort { $a cmp $b  } keys %{$app->{'intf_data'}->{'params'}}) { | ||||||
|  |         my $param_value = $app->{'intf_data'}->{'params'}->{$p}->{'d'}; | ||||||
|  |         push(@plines, sprintf("    parameter %$app->{'intf_data'}->{'info'}->{'param_width'}s = %d", | ||||||
|  |             $p, $param_value)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return @plines; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub get_ext_ports_lines { | ||||||
|  |     my ($app) = @_; | ||||||
|  |     my @eplines; | ||||||
|  |  | ||||||
|  |     foreach my $p (sort { $a cmp $b  } @{$app->{'intf_data'}->{'ext_sigs'}}) { | ||||||
|  |         push(@eplines, sprintf("    input %s", | ||||||
|  |             $p->{'n'})); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return @eplines; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub show_interface { | ||||||
|  |     my ($app) = @_; | ||||||
|  |  | ||||||
|  |     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||||
|  |         print "\n"; | ||||||
|  |         print "    // $section->{'name'}\n"; | ||||||
|  |  | ||||||
|  |         # Display signals | ||||||
|  |         foreach my $signal (@{$section->{'signals'}}) { | ||||||
|  |             if ($signal->{'s'} eq 'External') { | ||||||
|  |                 printf "    // External signal: %-$app->{'intf_data'}->{'info'}->{'sig_width'}s // $signal->{'d'} [$signal->{'s'}]\n", | ||||||
|  |                     "$signal->{'n'};"; | ||||||
|  |             } else { | ||||||
|  |                 printf "    logic %$app->{'intf_data'}->{'info'}->{'dim_width'}s %-$app->{'intf_data'}->{'info'}->{'sig_width'}s // $signal->{'d'} [$signal->{'s'}]\n", | ||||||
|  |                     get_dimension($app, $signal->{'w'}), "$signal->{'n'};"; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub show_modport{ | ||||||
|  |     my ($app, $role) = @_; | ||||||
|  |     my $last = 0; | ||||||
|  |  | ||||||
|  |     print "\n"; | ||||||
|  |     print "    // Modport for $role role\n"; | ||||||
|  |     print "    modport " . uc($role) . " (\n"; | ||||||
|  |  | ||||||
|  |     my $num_sections = scalar @{$app->{'intf_data'}->{'sections'}}; | ||||||
|  |     my $section_count = 0; | ||||||
|  |     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||||
|  |         print "\n"; | ||||||
|  |         print "        // $section->{'name'}\n"; | ||||||
|  |  | ||||||
|  |         $section_count++; | ||||||
|  |  | ||||||
|  |         # Display signals | ||||||
|  |         my $num_signals = scalar @{$section->{'signals'}}; | ||||||
|  |         my $signal_count = 0; | ||||||
|  |         foreach my $signal (@{$section->{'signals'}}) { | ||||||
|  |             # When role is Manager, signals with 'Manager' source are output, others are input | ||||||
|  |             # When role is Subordinate, signals with 'Subordinate' source are output, others are input | ||||||
|  |             my $direction = ($role eq 'Global') ? 'input' : ($role eq $signal->{'s'}) ? 'output' : 'input'; | ||||||
|  |  | ||||||
|  |             $signal_count++; | ||||||
|  |  | ||||||
|  |             $last = 1 if ($num_signals == $signal_count && $num_sections == $section_count); | ||||||
|  |  | ||||||
|  |             printf "        %-8s $signal->{'n'}" . (($last == 1) ? "" : ","). "\n", $direction; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     print "    );\n"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub augment_intf_data { | ||||||
|  |     my ($app) = @_; | ||||||
|  |  | ||||||
|  |     # Pretty print widths | ||||||
|  |     $app->{'intf_data'}->{'info'}->{'param_width'} = 0; | ||||||
|  |     $app->{'intf_data'}->{'info'}->{'dim_width'} = 0; | ||||||
|  |     $app->{'intf_data'}->{'info'}->{'sig_width'} = 0; | ||||||
|  |  | ||||||
|  |     # Capture parameters from signals | ||||||
|  |     $app->{'intf_data'}->{'params'} = {}; | ||||||
|  |     # Capture external signals | ||||||
|  |     $app->{'intf_data'}->{'ext_sigs'} = []; | ||||||
|  |     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||||
|  |         foreach my $signal (@{$section->{'signals'}}) { | ||||||
|  |             my $width = $signal->{'w'}; | ||||||
|  |             if ($width !~ /^\d+$/) { | ||||||
|  |                 unless (exists $app->{'intf_data'}->{'params'}->{$width}) { | ||||||
|  |                     $app->{'intf_data'}->{'params'}->{$width} = { | ||||||
|  |                         'd' => 1, # Default value for the parameter | ||||||
|  |                     }; | ||||||
|  |                     $app->{'intf_data'}->{'info'}->{'param_width'} = length($width) | ||||||
|  |                         if (length($width) > $app->{'intf_data'}->{'info'}->{'param_width'}); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if ($signal->{'s'} eq 'External') { | ||||||
|  |                 push(@{$app->{'intf_data'}->{'ext_sigs'}}, $signal); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     # Find the maximum width of the parameters | ||||||
|  |     foreach my $section (@{$app->{'intf_data'}->{'sections'}}) { | ||||||
|  |  | ||||||
|  |         foreach my $signal (@{$section->{'signals'}}) { | ||||||
|  |             $app->{'intf_data'}->{'info'}->{'dim_width'} = length(get_dimension($app, $signal->{'w'})) | ||||||
|  |                 if (length(get_dimension($app, $signal->{'w'})) > $app->{'intf_data'}->{'info'}->{'dim_width'}); | ||||||
|  |             $app->{'intf_data'}->{'info'}->{'sig_width'} = length($signal->{'n'}) | ||||||
|  |                 if (length($signal->{'n'}) > $app->{'intf_data'}->{'info'}->{'sig_width'}); | ||||||
|  |         } | ||||||
|  |         $app->{'intf_data'}->{'info'}->{'sig_width'} += 1; # Account for the semi-colon | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub get_dimension { | ||||||
|  |     my ($app, $width) = @_; | ||||||
|  |  | ||||||
|  |     if ($width =~ /^\d+$/) { | ||||||
|  |         if ($width == 1) { | ||||||
|  |             return ""; # Single bit width | ||||||
|  |         } else { | ||||||
|  |             return "[" . ($width-1) . ":0]"; # Specific width | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         return "[$width-1:0]"; # Width parameter | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # ----------------- | ||||||
|  | sub get_axi_intf_data { | ||||||
|  |     my ($app) = @_; | ||||||
|  |  | ||||||
|  |     $app->{'intf_data'} = { | ||||||
|  |         'name' => "AXI Signal List", | ||||||
|  |         'sections' => | ||||||
|  |         [ | ||||||
|  |             { | ||||||
|  |                 'name' => 'A2.4.1 Clock and reset signals', | ||||||
|  |                 'signals' => [ | ||||||
|  |                     { 'n' => 'ACLK',    'w' => '1', 's' => 'External', 'd' => 'External Global clock signal'}, | ||||||
|  |                     { 'n' => 'ARESETn', 'w' => '1', 's' => 'External', 'd' => 'External Global reset signal'} | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 'name' => 'A2.1.1 Write request channel', | ||||||
|  |                 'signals' => [ | ||||||
|  |                     # n: name, w: width, s: source, d: description | ||||||
|  |                     {'n' =>'AWVALID','w' =>'1','s' =>'Manager','d' =>'Valid indicator' }, | ||||||
|  |                     {'n' =>'AWREADY','w' =>'1','s' =>'Subordinate','d' =>'Ready indicator' }, | ||||||
|  |                     {'n' =>'AWID','w' =>'ID_W_WIDTH','s' =>'Manager','d' =>'Transaction identifier for the write channels' }, | ||||||
|  |                     {'n' =>'AWADDR','w' =>'ADDR_WIDTH','s' =>'Manager','d' =>'Transaction address' }, | ||||||
|  |                     {'n' =>'AWREGION','w' =>'4','s' =>'Manager','d' =>'Region identifier' }, | ||||||
|  |                     {'n' =>'AWLEN','w' =>'8','s' =>'Manager','d' =>'Transaction length' }, | ||||||
|  |                     {'n' =>'AWSIZE','w' =>'3','s' =>'Manager','d' =>'Transaction size' }, | ||||||
|  |                     {'n' =>'AWBURST','w' =>'2','s' =>'Manager','d' =>'Burst attribute' }, | ||||||
|  |                     {'n' =>'AWLOCK','w' =>'1','s' =>'Manager','d' =>'Exclusive access indicator' }, | ||||||
|  |                     {'n' =>'AWCACHE','w' =>'4','s' =>'Manager','d' =>'Memory attributes' }, | ||||||
|  |                     {'n' =>'AWPROT','w' =>'3','s' =>'Manager','d' =>'Access attributes' }, | ||||||
|  |                     {'n' =>'AWNSE','w' =>'1','s' =>'Manager','d' =>'Non-secure extension bit for RME' }, | ||||||
|  |                     {'n' =>'AWQOS','w' =>'4','s' =>'Manager','d' =>'QoS identifier' }, | ||||||
|  |                     {'n' =>'AWUSER','w' =>'USER_REQ_WIDTH','s' =>'Manager','d' =>'User-defined extension to a request' }, | ||||||
|  |                     {'n' =>'AWDOMAIN','w' =>'2','s' =>'Manager','d' =>'Shareability domain of a request' }, | ||||||
|  |                     {'n' =>'AWSNOOP','w' =>'AWSNOOP_WIDTH','s' =>'Manager','d' =>'Write request opcode' }, | ||||||
|  |                     {'n' =>'AWSTASHNID','w' =>'11','s' =>'Manager','d' =>'Stash Node ID' }, | ||||||
|  |                     {'n' =>'AWSTASHNIDEN','w' =>'1','s' =>'Manager','d' =>'Stash Node ID enable' }, | ||||||
|  |                     {'n' =>'AWSTASHLPID','w' =>'5','s' =>'Manager','d' =>'Stash Logical Processor ID' }, | ||||||
|  |                     {'n' =>'AWSTASHLPIDEN','w' =>'1','s' =>'Manager','d' =>'Stash Logical Processor ID enable' }, | ||||||
|  |                     {'n' =>'AWTRACE','w' =>'1','s' =>'Manager','d' =>'Trace signal' }, | ||||||
|  |                     {'n' =>'AWLOOP','w' =>'LOOP_W_WIDTH','s' =>'Manager','d' =>'Loopback signals on the write channels' }, | ||||||
|  |                     {'n' =>'AWMMUVALID','w' =>'1','s' =>'Manager','d' =>'MMU signal qualifier' }, | ||||||
|  |                     {'n' =>'AWMMUSECSID','w' =>'SECSID_WIDTH','s' =>'Manager','d' =>'Secure Stream ID' }, | ||||||
|  |                     {'n' =>'AWMMUSID','w' =>'SID_WIDTH','s' =>'Manager','d' =>'StreamID' }, | ||||||
|  |                     {'n' =>'AWMMUSSIDV','w' =>'1','s' =>'Manager','d' =>'SubstreamID valid' }, | ||||||
|  |                     {'n' =>'AWMMUSSID','w' =>'SSID_WIDTH','s' =>'Manager','d' =>'SubstreamID' }, | ||||||
|  |                     {'n' =>'AWMMUATST','w' =>'1','s' =>'Manager','d' =>'Address translated indicator' }, | ||||||
|  |                     {'n' =>'AWMMUFLOW','w' =>'2','s' =>'Manager','d' =>'SMMU flow type' }, | ||||||
|  |                     {'n' =>'AWPBHA','w' =>'4','s' =>'Manager','d' =>'Page-based Hardware Attributes' }, | ||||||
|  |                     {'n' =>'AWNSAID','w' =>'4','s' =>'Manager','d' =>'Non-secure Access ID' }, | ||||||
|  |                     {'n' =>'AWSUBSYSID','w' =>'SUBSYSID_WIDTH','s' =>'Manager','d' =>'Subsystem ID' }, | ||||||
|  |                     {'n' =>'AWATOP','w' =>'6','s' =>'Manager','d' =>'Atomic transaction opcode' }, | ||||||
|  |                     {'n' =>'AWMPAM','w' =>'MPAM_WIDTH','s' =>'Manager','d' =>'MPAM information with a request' }, | ||||||
|  |                     {'n' =>'AWIDUNQ','w' =>'1','s' =>'Manager','d' =>'Unique ID indicator' }, | ||||||
|  |                     {'n' =>'AWCMO','w' =>'AWCMO_WIDTH','s' =>'Manager','d' =>'CMO type' }, | ||||||
|  |                     {'n' =>'AWTAGOP','w' =>'2','s' =>'Manager','d' =>'Memory Tag operation for write requests' }, | ||||||
|  |                     {'n' =>'AWMECID','w' =>'MECID_WIDTH','s' =>'Manager','d' =>'Memory Encryption Context identifier' }, | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 'name' => 'A2.1.1 Write request channel', | ||||||
|  |                 'signals' => [ | ||||||
|  |                     { 'n' => 'WVALID', 'w' => '1', 's' => 'Manager', 'd' => 'Valid indicator' }, | ||||||
|  |                     { 'n' => 'WREADY', 'w' => '1', 's' => 'Subordinate', 'd' => 'Ready indicator' }, | ||||||
|  |                     { 'n' => 'WDATA', 'w' => 'DATA_WIDTH', 's' => 'Manager', 'd' => 'Write data' }, | ||||||
|  |                     { 'n' => 'WSTRB', 'w' => 'DATA_WIDTH_DIV_8', 's' => 'Manager', 'd' => 'Write data strobes' }, | ||||||
|  |                     { 'n' => 'WTAG', 'w' => 'CEIL_DATA_WIDTH_DIV_128_TMS_4', 's' => 'Manager', 'd' => 'Memory Tag' }, | ||||||
|  |                     { 'n' => 'WTAGUPDATE', 'w' => 'CEIL_DATA_WIDTH_DIV_128', 's' => 'Manager', 'd' => 'Memory Tag update' }, | ||||||
|  |                     { 'n' => 'WLAST', 'w' => '1', 's' => 'Manager', 'd' => 'Last write data' }, | ||||||
|  |                     { 'n' => 'WUSER', 'w' => 'USER_DATA_WIDTH', 's' => 'Manager', 'd' => 'User-defined extension to write data' }, | ||||||
|  |                     { 'n' => 'WPOISON', 'w' => 'CEIL_DATA_WIDTH_DIV_64', 's' => 'Manager', 'd' => 'Poison indicator' }, | ||||||
|  |                     { 'n' => 'WTRACE', 'w' => '1', 's' => 'Manager', 'd' => 'Trace signal' }, | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 'name' => 'A2.1.3 Write response channel', | ||||||
|  |                 'signals' => [ | ||||||
|  |                     { 'n' => 'BVALID', 'w' => '1', 's' => 'Subordinate', 'd' => 'Valid indicator' }, | ||||||
|  |                     { 'n' => 'BREADY', 'w' => '1', 's' => 'Manager', 'd' => 'Ready indicator' }, | ||||||
|  |                     { 'n' => 'BID', 'w' => 'ID_W_WIDTH', 's' => 'Subordinate', 'd' => 'Transaction identifier for the write channels' }, | ||||||
|  |                     { 'n' => 'BIDUNQ', 'w' => '1', 's' => 'Subordinate', 'd' => 'Unique ID indicator' }, | ||||||
|  |                     { 'n' => 'BRESP', 'w' => 'BRESP_WIDTH', 's' => 'Subordinate', 'd' => 'Write response code' }, | ||||||
|  |                     { 'n' => 'BCOMP', 'w' => '1', 's' => 'Subordinate', 'd' => 'Completion response indicator' }, | ||||||
|  |                     { 'n' => 'BPERSIST', 'w' => '1', 's' => 'Subordinate', 'd' => "Persist response" }, | ||||||
|  |                     { 'n' => 'BTAGMATCH', 'w' => '2', 's' => 'Subordinate', 'd' => 'Memory Tag Match response' }, | ||||||
|  |                     { 'n' => 'BUSER', 'w' => 'USER_RESP_WIDTH', 's' => 'Subordinate', 'd' => 'User-defined extension to a write response' }, | ||||||
|  |                     { 'n' => 'BTRACE', 'w' => '1', 's' => 'Subordinate', 'd' => 'Trace signal' }, | ||||||
|  |                     { 'n' => 'BLOOP', 'w' => 'LOOP_W_WIDTH', 's' => 'Subordinate', 'd' => 'Loopback signals on the write channels' }, | ||||||
|  |                     { 'n' => 'BBUSY', 'w' => '2', 's' => 'Subordinate', 'd' => "Busy indicator" }, | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 'name' => 'A2.2.1 Read request channel', | ||||||
|  |                 'signals' => [ | ||||||
|  |                     { 'n' => 'ARVALID', 'w' => '1', 's' => 'Manager', 'd' => 'Valid indicator' }, | ||||||
|  |                     { 'n' => 'ARREADY', 'w' => '1', 's' => 'Subordinate', 'd' => 'Ready indicator' }, | ||||||
|  |                     { 'n' => 'ARID', 'w' => 'ID_R_WIDTH', 's' => 'Manager', 'd' => 'Transaction identifier for the read channels' }, | ||||||
|  |                     { 'n' => 'ARADDR', 'w' => 'ADDR_WIDTH', 's' => 'Manager', 'd' => 'Transaction address' }, | ||||||
|  |                     { 'n' => 'ARREGION', 'w' => '4', 's' => 'Manager', 'd' => 'Region identifier' }, | ||||||
|  |                     { 'n' => 'ARLEN',  'w' => '8',  's' => 'Manager',  'd'=> "Transaction length" }, | ||||||
|  |                     { 'n' => 'ARSIZE',  'w' => '3',  's' => 'Manager',  'd' => 'Transaction size' }, | ||||||
|  |                     { 'n' => 'ARBURST', 'w' => '2', 's' => 'Manager', 'd' => 'Burst attribute' }, | ||||||
|  |                     { 'n' => 'ARLOCK', 'w' => '1', 's' => 'Manager', 'd' => 'Exclusive access indicator' }, | ||||||
|  |                     { 'n' => 'ARCACHE', 'w' => '4', 's' => 'Manager', 'd' => 'Memory attributes' }, | ||||||
|  |                     { 'n' => 'ARPROT', 'w' => '3', 's' => 'Manager', 'd' => 'Access attributes' }, | ||||||
|  |                     { 'n' => 'ARNSE', 'w' => '1', 's' => 'Manager', 'd' => 'Non-secure extension bit for RME' }, | ||||||
|  |                     { 'n' => 'ARQOS', 'w' => '4', 's' => 'Manager', 'd' => 'QoS identifier' }, | ||||||
|  |                     { 'n' => 'ARUSER', 'w' => 'USER_REQ_WIDTH', 's' => 'Manager', 'd' => 'User-defined extension to a request' }, | ||||||
|  |                     { 'n' => 'ARDOMAIN', 'w' => '2', 's' => 'Manager', 'd' => 'Shareability domain of a request' }, | ||||||
|  |                     { 'n' => 'ARSNOOP', 'w' => 'ARSNOOP_WIDTH', 's' => 'Manager', 'd' => 'Read request opcode' }, | ||||||
|  |                     { 'n' => 'ARTRACE', 'w' => '1', 's' => 'Manager', 'd' => 'Trace signal' }, | ||||||
|  |                     { 'n' => 'ARLOOP', 'w' => 'LOOP_R_WIDTH', 's' => 'Manager', 'd' => 'Loopback signals on the read channels' }, | ||||||
|  |                     { 'n' => 'ARMMUVALID', 'w' => '1', 's' => 'Manager', 'd' => 'MMU signal qualifier' }, | ||||||
|  |                     { 'n' => 'ARMMUSECSID', 'w' => 'SECSID_WIDTH', 's' => 'Manager', 'd' => 'Secure Stream ID' }, | ||||||
|  |                     { 'n' => 'ARMMUSID', 'w' => 'SID_WIDTH', 's' => 'Manager', 'd' => 'StreamID' }, | ||||||
|  |                     { 'n' => 'ARMMUSSIDV', 'w' => '1', 's' => 'Manager', 'd' => 'SubstreamID valid' }, | ||||||
|  |                     { 'n' => 'ARMMUSSID', 'w' => 'SSID_WIDTH', 's' => 'Manager', 'd' => 'SubstreamID' }, | ||||||
|  |                     { 'n' => 'ARMMUATST', 'w' => '1', 's' => 'Manager', 'd' => 'Address translated indicator' }, | ||||||
|  |                     { 'n' => 'ARMMUFLOW', 'w' => '2', 's' => 'Manager', 'd' => 'SMMU flow type' }, | ||||||
|  |                     { 'n' => 'ARPBHA', 'w' => '4', 's' => 'Manager', 'd' => 'Page-based Hardware Attributes' }, | ||||||
|  |                     { 'n' => 'ARNSAID', 'w' => '4', 's' => 'Manager', 'd' => 'Non-secure Access ID' }, | ||||||
|  |                     { 'n' => 'ARSUBSYSID', 'w' => 'SUBSYSID_WIDTH', 's' => 'Manager', 'd' => 'Subsystem ID' }, | ||||||
|  |                     { 'n' => 'ARCHUNKEN','w' => '1','s' => 'Manager','d' => 'Read data chunking enable'}, | ||||||
|  |                     { 'n' => 'ARIDUNQ','w' => '1','s' => 'Manager','d' => 'Unique ID indicator'}, | ||||||
|  |                     { 'n' => 'ARTAGOP','w' => '2','s' => 'Manager','d' => 'Memory Tag operation for read requests'}, | ||||||
|  |                     { 'n' => 'ARMECID','w' => 'MECID_WIDTH','s' => 'Manager','d' => 'Memory Encryption Context identifier'}, | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 'name' => 'A2.2.2 Read data channel', | ||||||
|  |                 'signals' => [ | ||||||
|  |                     { 'n' => 'RVALID', 'w' => '1', 's' => 'Subordinate', 'd' => 'Valid indicator' }, | ||||||
|  |                     { 'n' => 'RREADY', 'w' => '1', 's' => 'Manager', 'd' => 'Ready indicator' }, | ||||||
|  |                     { 'n' => 'RID', 'w' => 'ID_R_WIDTH', 's' => 'Subordinate', 'd' => 'Transaction identifier for the read channels' }, | ||||||
|  |                     { 'n' => 'RIDUNQ', 'w' => '1', 's' => 'Subordinate', 'd' => 'Unique ID indicator' }, | ||||||
|  |                     { 'n' => 'RDATA', 'w' => 'DATA_WIDTH', 's' => 'Subordinate', 'd' => 'Read data' }, | ||||||
|  |                     { 'n' => 'RTAG', 'w' => 'CEIL_DATA_WIDTH_DIV_128_TMS_4', 's' => 'Subordinate', 'd' => 'Memory Tag' }, | ||||||
|  |                     { 'n' => 'RRESP', 'w' => 'RRESP_WIDTH', 's' => 'Subordinate', 'd' => 'Read response' }, | ||||||
|  |                     { 'n' => 'RLAST', 'w' => '1', 's' => 'Subordinate', 'd' => 'Last read data' }, | ||||||
|  |                     { 'n' => 'RUSER', 'w' => 'SUM_USER_DATA_WIDTH_USER_RESP_WIDTH', 's' => 'Subordinate', 'd' => 'User-defined extension to read data and response' }, | ||||||
|  |                     { 'n' => 'RPOISON', 'w' => 'CEIL_DATA_WIDTH_DIV_64', 's' => 'Subordinate', 'd' => 'Poison indicator' }, | ||||||
|  |                     { 'n' => 'RTRACE', 'w' => '1', 's' => 'Subordinate', 'd' => 'Trace signal' }, | ||||||
|  |                     { 'n' => 'RLOOP', 'w' => 'LOOP_R_WIDTH', 's' => 'Subordinate', 'd' => 'Loopback signals on the read channels' }, | ||||||
|  |                     { 'n' => 'RCHUNKV','w' => '1', 's' => 'Subordinate', 'd' => 'Read data chunking valid' }, | ||||||
|  |                     { 'n' => 'RCHUNKNUM', 'w' => 'RCHUNKNUM_WIDTH', 's' => 'Subordinate', 'd' => 'Read data chunk number' }, | ||||||
|  |                     { 'n' => 'RCHUNKSTRB', 'w' => 'RCHUNKSTRB_WIDTH', 's' => 'Subordinate', 'd' => 'Read data chunk strobe' }, | ||||||
|  |                     { 'n' => 'RBUSY', 'w' => '2', 's' => 'Subordinate', 'd' => 'Busy indicator' }, | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								src/design_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/design_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										88
									
								
								tb/axi_agent.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								tb/axi_agent.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | |||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | // Agent to operate AXI transactions | ||||||
|  | // This agent includes a driver, monitor, and sequencer for AXI transactions | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | typedef axi_sequencer; | ||||||
|  |  | ||||||
|  | class axi_agent extends uvm_agent; | ||||||
|  |     agent_type_t agent_type; | ||||||
|  |     virtual `AXI_INTF.MANAGER m_if; | ||||||
|  |     virtual `AXI_INTF.SUBORDINATE s_if; | ||||||
|  |  | ||||||
|  |     // Declare the sequencer and driver | ||||||
|  |     axi_sequencer sequencer; | ||||||
|  |     axi_driver driver; | ||||||
|  |     axi_monitor monitor; | ||||||
|  |  | ||||||
|  |     `uvm_component_utils_begin(axi_agent) | ||||||
|  |         `uvm_field_enum(agent_type_t, agent_type, UVM_DEFAULT) | ||||||
|  |     `uvm_component_utils_end | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "axi_agent", uvm_component parent = null); | ||||||
|  |         super.new(name, parent); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Set agent type | ||||||
|  |     function void set_agent_type(agent_type_t atype); | ||||||
|  |         agent_type = atype; | ||||||
|  |         `uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW) | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Build phase | ||||||
|  |     virtual function void build_phase(uvm_phase phase); | ||||||
|  |         sequencer   = axi_sequencer::type_id::create("sequencer", this); | ||||||
|  |         driver      = axi_driver::type_id::create("driver", this); | ||||||
|  |         monitor     = axi_monitor::type_id::create("monitor", this); | ||||||
|  |  | ||||||
|  |         // Propagete the agent type to driver and monitor | ||||||
|  |         driver.set_agent_type(agent_type); | ||||||
|  |         monitor.set_agent_type(agent_type); | ||||||
|  |  | ||||||
|  |         if (agent_type == MANAGER) begin | ||||||
|  |             if (!uvm_config_db#(virtual `AXI_INTF.MANAGER)::get(this, "", "axi_dvr_vif", m_if)) begin | ||||||
|  |                 `uvm_fatal("axi_agent", "AXI agent MANAGER interface not configured") | ||||||
|  |             end | ||||||
|  |             `uvm_info("axi_agent", $sformatf("Using AXI agent MANAGER interface: axi_dvr_vif"), UVM_LOW) | ||||||
|  |         end else begin // if (agent_type == SUBORDINATE) begin | ||||||
|  |             if (!uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::get(this, "", "axi_dvr_vif", s_if)) begin | ||||||
|  |                 `uvm_fatal("axi_agent", "AXI agent SUBORDINATE interface not configured") | ||||||
|  |             end | ||||||
|  |             `uvm_info("axi_agent", $sformatf("Using AXI agent SUBORDINATE interface: axi_dvr_vif"), UVM_LOW) | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         driver.set_virtual_intefaces(m_if, s_if); | ||||||
|  |         monitor.set_virtual_intefaces(m_if, s_if); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Connect phase | ||||||
|  |     virtual function void connect_phase(uvm_phase phase); | ||||||
|  |         // Connect the driver to the sequencer | ||||||
|  |         driver.seq_item_port.connect(sequencer.seq_item_export); | ||||||
|  |         driver.rsp_port.connect(sequencer.rsp_export); | ||||||
|  |         // Connect the monitor to the sequencer | ||||||
|  |         // driver.rsp_port.connect(monitor.rsp_export); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Run phase | ||||||
|  |     virtual function void run_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("axi_agent", $sformatf("Running AXI agent: %s as %s", | ||||||
|  |             get_full_name(), agent_type.name()), UVM_LOW) | ||||||
|  |     endfunction | ||||||
|  | endclass : axi_agent | ||||||
|  |  | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class axi_sequencer extends uvm_sequencer; | ||||||
|  |  | ||||||
|  |     `uvm_component_utils(axi_sequencer) | ||||||
|  |  | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name, uvm_component parent); | ||||||
|  |         super.new(name, parent); | ||||||
|  |     endfunction | ||||||
|  | endclass : axi_sequencer | ||||||
							
								
								
									
										119
									
								
								tb/axi_driver.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								tb/axi_driver.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | // Driver for AXI transactions | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class axi_driver extends uvm_driver; // #(axi_transaction); | ||||||
|  |     virtual `AXI_INTF.MANAGER m_if; | ||||||
|  |     virtual `AXI_INTF.SUBORDINATE s_if; | ||||||
|  |     agent_type_t agent_type; | ||||||
|  |  | ||||||
|  |     `uvm_component_utils(axi_driver) | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "axi_driver", uvm_component parent = null); | ||||||
|  |         super.new(name, parent); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Set agent type | ||||||
|  |     function void set_agent_type(agent_type_t atype); | ||||||
|  |         agent_type = atype; | ||||||
|  |         `uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW) | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Set virtual interfaces | ||||||
|  |     function void set_virtual_intefaces(virtual `AXI_INTF.MANAGER m_if_p, | ||||||
|  |                                         virtual `AXI_INTF.SUBORDINATE s_if_p); | ||||||
|  |         `uvm_info("set_virtual_intefaces", $sformatf("Setting virtual interfaces"), UVM_LOW) | ||||||
|  |  | ||||||
|  |         m_if = m_if_p; | ||||||
|  |         s_if = s_if_p; | ||||||
|  |  | ||||||
|  |         // if (m_if == null && s_if == null) begin | ||||||
|  |         //     `uvm_fatal("AXI_DRIVER", "Both MANAGER and SUBORDINATE interfaces are null") | ||||||
|  |         // end else if ((agent_type == MANAGER) && (m_if == null)) begin | ||||||
|  |         //     `uvm_error("AXI_DRIVER", $sformatf("MANAGER interface is null")) | ||||||
|  |         // end else if ((agent_type == SUBORDINATE) && (s_if == null)) begin | ||||||
|  |         //     `uvm_error("AXI_DRIVER", $sformatf("SUBORDINATE interface is null")) | ||||||
|  |         // end | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Run phase | ||||||
|  |     virtual task run_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("axi_driver", $sformatf("Running AXI driver: %s as %s", | ||||||
|  |             get_full_name(), agent_type.name()), UVM_LOW) | ||||||
|  |  | ||||||
|  |         if (agent_type == MANAGER) begin | ||||||
|  |             `uvm_info("axi_driver", $sformatf("Manager agent detected, driving transactions"), UVM_LOW) | ||||||
|  |             drive_transactions(); | ||||||
|  |         end else if (agent_type == SUBORDINATE) begin | ||||||
|  |             `uvm_info("axi_driver", $sformatf("Subordinate agent detected, responding to transactions"), UVM_LOW) | ||||||
|  |             respond_to_transactions(); | ||||||
|  |         end else begin | ||||||
|  |             `uvm_fatal("AXI_DRIVER", "Unknown agent type") | ||||||
|  |         end | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     task drive_transactions(); | ||||||
|  |         if (m_if == null) begin | ||||||
|  |             `uvm_error("AXI_DRIVER", "MANAGER interface is null, cannot drive transactions") | ||||||
|  |         end | ||||||
|  |         forever begin | ||||||
|  |             `uvm_info("axi_driver", $sformatf("Starting to drive transactions for %s (rst_n = %0b)", | ||||||
|  |                 get_full_name(), m_if.ARESETn), UVM_LOW) | ||||||
|  |  | ||||||
|  |             if (m_if.ARESETn == 0) begin | ||||||
|  |                 `uvm_info("axi_driver", $sformatf("Waiting for reset to be released (rst_n = %0b)", | ||||||
|  |                     m_if.ARESETn), UVM_LOW) | ||||||
|  |                 @(posedge m_if.ARESETn); | ||||||
|  |             end | ||||||
|  |  | ||||||
|  |             `uvm_info("axi_driver", $sformatf("Starting to drive transactions for %s (rst_n = %0b)", | ||||||
|  |                 get_full_name(), m_if.ARESETn), UVM_LOW) | ||||||
|  |  | ||||||
|  |             while (m_if.ARESETn != 0) begin | ||||||
|  |                 uvm_sequence_item txn; | ||||||
|  |  | ||||||
|  |                 `uvm_info("axi_driver", $sformatf("Waiting for next transaction"), UVM_LOW) | ||||||
|  |  | ||||||
|  |                 seq_item_port.get_next_item(txn); | ||||||
|  |                 drive_item(txn); | ||||||
|  |                 seq_item_port.item_done(); | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     task drive_item(uvm_sequence_item txn); | ||||||
|  |         axi_transaction req; | ||||||
|  |  | ||||||
|  |         if (!$cast(req, txn)) begin | ||||||
|  |             `uvm_fatal("AXI_DRIVER", "Invalid transaction type") | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         `uvm_info("drive_item", $sformatf("Driving AXI transaction:\n%s", req.sprint()), UVM_LOW) | ||||||
|  |         @(posedge m_if.ACLK); | ||||||
|  |         m_if.AWVALID = 1; | ||||||
|  |         m_if.AWADDR  = req.addr; | ||||||
|  |         @(posedge m_if.ACLK); | ||||||
|  |         m_if.WDATA  = req.data; | ||||||
|  |         m_if.WSTRB  = req.strb; | ||||||
|  |         `uvm_info("drive_item", $sformatf("Driving AXI transaction done."), UVM_LOW) | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     task respond_to_transactions(); | ||||||
|  |         forever begin | ||||||
|  |             @(posedge s_if.ARESETn); | ||||||
|  |  | ||||||
|  |             while (s_if.ARESETn != 0) begin | ||||||
|  |                 @(posedge s_if.ACLK); | ||||||
|  |  | ||||||
|  |                 @(negedge s_if.ACLK); | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     endtask | ||||||
|  | endclass : axi_driver | ||||||
							
								
								
									
										117
									
								
								tb/axi_monitor.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								tb/axi_monitor.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | |||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | // Monitor for AXI transactions | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class axi_monitor extends uvm_monitor; // #(axi_transaction); | ||||||
|  |     virtual `AXI_INTF.MANAGER m_if; | ||||||
|  |     virtual `AXI_INTF.SUBORDINATE s_if; | ||||||
|  |     agent_type_t agent_type; | ||||||
|  |  | ||||||
|  |     // Declare the analysis export | ||||||
|  |     uvm_analysis_port ap; | ||||||
|  |  | ||||||
|  |     // Filehandle for transaction tracker file | ||||||
|  |     int trk_file; | ||||||
|  |  | ||||||
|  |     `uvm_component_utils(axi_monitor) | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "axi_monitor", uvm_component parent = null); | ||||||
|  |         super.new(name, parent); | ||||||
|  |         ap = new("analysis_export", this); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Set agent type | ||||||
|  |     function void set_agent_type(agent_type_t atype); | ||||||
|  |         agent_type = atype; | ||||||
|  |         `uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW) | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Set virtual interfaces | ||||||
|  |     function void set_virtual_intefaces(virtual `AXI_INTF.MANAGER m_if_p, | ||||||
|  |                                         virtual `AXI_INTF.SUBORDINATE s_if_p); | ||||||
|  |         `uvm_info("set_virtual_intefaces", $sformatf("Setting virtual interfaces"), UVM_LOW) | ||||||
|  |  | ||||||
|  |         m_if = m_if_p; | ||||||
|  |         s_if = s_if_p; | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Run phase | ||||||
|  |     virtual function void run_phase(uvm_phase phase); | ||||||
|  |         // Open transaction log file | ||||||
|  |         trk_file = $fopen($sformatf("axi_transactions.%s.log", agent_type.name()), "w"); | ||||||
|  |         if (trk_file == 0) begin | ||||||
|  |             `uvm_error("AXI_MONITOR", "Failed to open transaction log file") | ||||||
|  |         end else begin | ||||||
|  |             `uvm_info("AXI_MONITOR", "Transaction log file opened successfully", UVM_LOW) | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         // Start monitoring | ||||||
|  |         do_monitor(); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Monitor logic to capture transactions | ||||||
|  |     virtual task do_monitor(); | ||||||
|  |         if (agent_type == MANAGER) begin | ||||||
|  |             do_manager_monitor(); | ||||||
|  |         end else if (agent_type == SUBORDINATE) begin | ||||||
|  |             do_subordinate_monitor(); | ||||||
|  |         end else begin | ||||||
|  |             `uvm_fatal("AXI_MONITOR", "Unknown agent type") | ||||||
|  |         end | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Monitor logic for MANAGER agent | ||||||
|  |     virtual task do_manager_monitor(); | ||||||
|  |         // Placeholder for actual monitoring logic | ||||||
|  |         // This would typically involve sampling signals and creating transactions | ||||||
|  |         forever begin | ||||||
|  |             axi_transaction txn; | ||||||
|  |             @(posedge m_if.ACLK); | ||||||
|  |  | ||||||
|  |             txn = axi_transaction::type_id::create("txn"); | ||||||
|  |  | ||||||
|  |             // Capture transaction details here | ||||||
|  |  | ||||||
|  |             ap.write(txn); | ||||||
|  |             write_transaction_to_file(txn); | ||||||
|  |         end | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Monitor logic for SUBORDINATE agent | ||||||
|  |     virtual task do_subordinate_monitor(); | ||||||
|  |         // Placeholder for actual monitoring logic | ||||||
|  |         // This would typically involve sampling signals and creating transactions | ||||||
|  |         forever begin | ||||||
|  |             axi_transaction txn; | ||||||
|  |             @(posedge s_if.ACLK); | ||||||
|  |  | ||||||
|  |             txn = axi_transaction::type_id::create("txn"); | ||||||
|  |  | ||||||
|  |             // Capture transaction details here | ||||||
|  |  | ||||||
|  |             ap.write(txn); | ||||||
|  |             write_transaction_to_file(txn); | ||||||
|  |         end | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Report phase | ||||||
|  |     virtual function void report_phase(uvm_phase phase); | ||||||
|  |         // Report any captured transactions or statistics | ||||||
|  |         `uvm_info("axi_monitor", $sformatf("Reporting on %s", | ||||||
|  |             get_full_name()), UVM_LOW) | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Function to write captured transaction into a file | ||||||
|  |     function void write_transaction_to_file(axi_transaction txn); | ||||||
|  |         $fwrite(trk_file, "%s\n", txn.sprint()); | ||||||
|  |     endfunction | ||||||
|  | endclass : axi_monitor | ||||||
							
								
								
									
										43
									
								
								tb/axi_transaction.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								tb/axi_transaction.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class axi_transaction extends uvm_sequence_item; | ||||||
|  |     // Declare AXI transaction fields | ||||||
|  |     rand axi_transaction_type_t txn_type; // Transaction type (read/write) | ||||||
|  |     rand bit [31:0] addr; // Address | ||||||
|  |     rand bit [31:0] data; // Data | ||||||
|  |     rand bit [3:0]  strb; // Byte enable | ||||||
|  |  | ||||||
|  |     `uvm_object_utils_begin(axi_transaction) | ||||||
|  |         `uvm_field_enum(axi_transaction_type_t, txn_type, UVM_DEFAULT) | ||||||
|  |         `uvm_field_int(addr, UVM_DEFAULT) | ||||||
|  |         `uvm_field_int(data, UVM_DEFAULT) | ||||||
|  |         `uvm_field_int(strb, UVM_DEFAULT) | ||||||
|  |     `uvm_object_utils_end | ||||||
|  |  | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "axi_transaction"); | ||||||
|  |         super.new(name); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // Copy method for cloning | ||||||
|  |     virtual function uvm_object clone(); | ||||||
|  |         axi_transaction copy; | ||||||
|  |         copy = axi_transaction::type_id::create(get_name()); | ||||||
|  |         copy.txn_type = this.txn_type; | ||||||
|  |         copy.addr = this.addr; | ||||||
|  |         copy.data = this.data; | ||||||
|  |         copy.strb = this.strb; | ||||||
|  |         return copy; | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // Comparison method for checking equality | ||||||
|  |     virtual function bit compare(uvm_object rhs); | ||||||
|  |         axi_transaction other; | ||||||
|  |         if (!$cast(other, rhs)) return 0; // Ensure type match | ||||||
|  |         return (this.txn_type == other.txn_type) && | ||||||
|  |                (this.addr == other.addr) && | ||||||
|  |                (this.data == other.data) && | ||||||
|  |                (this.strb == other.strb); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  | endclass : axi_transaction | ||||||
|  |  | ||||||
							
								
								
									
										40
									
								
								tb/tb_env.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								tb/tb_env.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | // Testbench environment for UVM-based verification | ||||||
|  | class tb_env extends uvm_env; | ||||||
|  |  | ||||||
|  |     axi_agent axi_m; | ||||||
|  |     axi_agent axi_s; | ||||||
|  |  | ||||||
|  |     `uvm_component_utils(tb_env) | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     function new(string name, uvm_component parent); | ||||||
|  |         super.new(name, parent); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual function void build_phase(uvm_phase phase); | ||||||
|  |         axi_m = axi_agent::type_id::create("axi_m", this); | ||||||
|  |         axi_s = axi_agent::type_id::create("axi_s", this); | ||||||
|  |  | ||||||
|  |         `uvm_info("tb_env", $sformatf("Building testbench environment: %s", get_full_name()), UVM_LOW) | ||||||
|  |         // Set agent types in AXI agents | ||||||
|  |         axi_m.set_agent_type(MANAGER); | ||||||
|  |         axi_s.set_agent_type(SUBORDINATE); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual function void connect_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("tb_env", $sformatf("Connecting testbench environment: %s", get_full_name()), UVM_LOW) | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual function void report_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("tb_env", $sformatf("Reporting for testbench environment: %s", get_full_name()), UVM_LOW) | ||||||
|  |         // Add any specific report phase tasks here | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     function uvm_sequencer_base get_axi_m_sequencer(); | ||||||
|  |         return axi_m.sequencer; | ||||||
|  |     endfunction | ||||||
|  | endclass : tb_env | ||||||
							
								
								
									
										26
									
								
								tb/tb_intf.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tb/tb_intf.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // Testbench interface for UVM-based verification environment | ||||||
|  | interface testbench_if ( | ||||||
|  |     input clk, | ||||||
|  |     virtual axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), | ||||||
|  |                .CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), | ||||||
|  |                .CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), | ||||||
|  |                .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), | ||||||
|  |                .DATA_WIDTH(`DATA_WIDTH), | ||||||
|  |                .DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) m_if, | ||||||
|  |     virtual axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), | ||||||
|  |                .CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), | ||||||
|  |                .CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), | ||||||
|  |                .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), | ||||||
|  |                .DATA_WIDTH(`DATA_WIDTH), | ||||||
|  |                .DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) s_if); | ||||||
|  |  | ||||||
|  |     logic rst_n; | ||||||
|  |  | ||||||
|  |     initial begin | ||||||
|  |         forever begin | ||||||
|  |             @(clk or rst_n); | ||||||
|  |                 $monitor("@%6t: %b %b ", $time, | ||||||
|  |                     rst_n, clk); | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | endinterface | ||||||
							
								
								
									
										39
									
								
								tb/tb_params.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tb/tb_params.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | // Tesbench defines | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | // List of AXI parameters used in this testbench | ||||||
|  | `define                          ADDR_WIDTH 32 | ||||||
|  | // `define                       ARSNOOP_WIDTH 1 | ||||||
|  | // `define                         AWCMO_WIDTH 1 | ||||||
|  | // `define                       AWSNOOP_WIDTH 1 | ||||||
|  | // `define                         BRESP_WIDTH 1 | ||||||
|  | `define             CEIL_DATA_WIDTH_DIV_128 1 | ||||||
|  | `define       CEIL_DATA_WIDTH_DIV_128_TMS_4 4 | ||||||
|  | `define              CEIL_DATA_WIDTH_DIV_64 1 | ||||||
|  | `define                          DATA_WIDTH 64 | ||||||
|  | `define                    DATA_WIDTH_DIV_8 8 | ||||||
|  | // `define                          ID_R_WIDTH 1 | ||||||
|  | // `define                          ID_W_WIDTH 1 | ||||||
|  | // `define                        LOOP_R_WIDTH 1 | ||||||
|  | // `define                        LOOP_W_WIDTH 1 | ||||||
|  | // `define                         MECID_WIDTH 1 | ||||||
|  | // `define                          MPAM_WIDTH 1 | ||||||
|  | // `define                     RCHUNKNUM_WIDTH 1 | ||||||
|  | // `define                    RCHUNKSTRB_WIDTH 1 | ||||||
|  | // `define                         RRESP_WIDTH 1 | ||||||
|  | // `define                        SECSID_WIDTH 1 | ||||||
|  | // `define                           SID_WIDTH 1 | ||||||
|  | // `define                          SSID_WIDTH 1 | ||||||
|  | // `define                      SUBSYSID_WIDTH 1 | ||||||
|  | // `define SUM_USER_DATA_WIDTH_USER_RESP_WIDTH 1 | ||||||
|  | // `define                     USER_DATA_WIDTH 1 | ||||||
|  | // `define                      USER_REQ_WIDTH 1 | ||||||
|  | // `define                     USER_RESP_WIDTH 1 | ||||||
|  |  | ||||||
|  | // Defines | ||||||
|  | `define AXI_INTF axi_intf #(.ADDR_WIDTH(`ADDR_WIDTH), \ | ||||||
|  |                     .CEIL_DATA_WIDTH_DIV_128(`CEIL_DATA_WIDTH_DIV_128), \ | ||||||
|  |                     .CEIL_DATA_WIDTH_DIV_128_TMS_4(`CEIL_DATA_WIDTH_DIV_128_TMS_4), \ | ||||||
|  |                     .CEIL_DATA_WIDTH_DIV_64(`CEIL_DATA_WIDTH_DIV_64), \ | ||||||
|  |                     .DATA_WIDTH(`DATA_WIDTH), \ | ||||||
|  |                     .DATA_WIDTH_DIV_8(`DATA_WIDTH_DIV_8)) | ||||||
							
								
								
									
										25
									
								
								tb/tb_pkg.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tb/tb_pkg.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | `include "tb_params.sv" | ||||||
|  | `include "tb_intf.sv" | ||||||
|  | package tb_pkg; | ||||||
|  |     import uvm_pkg::*; | ||||||
|  |     import tb_types::*; | ||||||
|  |  | ||||||
|  |     `include "uvm_macros.svh" | ||||||
|  |  | ||||||
|  |     // Testbench defines | ||||||
|  |     // UVM data items | ||||||
|  |     `include "axi_transaction.sv" | ||||||
|  |  | ||||||
|  |     // UVM components | ||||||
|  |     `include "axi_driver.sv" | ||||||
|  |     `include "axi_monitor.sv" | ||||||
|  |     `include "axi_agent.sv" | ||||||
|  |     `include "tb_env.sv" | ||||||
|  |  | ||||||
|  |     // UVM sequences | ||||||
|  |     `include "tb_seq_base.sv" | ||||||
|  |  | ||||||
|  |     // Tests | ||||||
|  |     `include "test_base.sv" | ||||||
|  | endpackage | ||||||
|  | `include "tb_top.sv" | ||||||
							
								
								
									
										51
									
								
								tb/tb_seq_base.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tb/tb_seq_base.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | // Base sequence class for testbench sequences | ||||||
|  | class tb_seq_base extends uvm_sequence; | ||||||
|  |     `uvm_object_utils(tb_seq_base) | ||||||
|  |  | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "tb_seq_base"); | ||||||
|  |         super.new(name); | ||||||
|  |     endfunction | ||||||
|  | endclass : tb_seq_base | ||||||
|  |  | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class axi_m_seq_base extends tb_seq_base; | ||||||
|  |     tb_env env; | ||||||
|  |  | ||||||
|  |     `uvm_object_utils(axi_m_seq_base) | ||||||
|  |  | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "axi_m_seq_base"); | ||||||
|  |         super.new(name); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // Task to start the sequence | ||||||
|  |     virtual task body(); | ||||||
|  |         bit ok = uvm_config_db#(tb_env)::get(uvm_root::get(), "*", "env", env); | ||||||
|  |     endtask | ||||||
|  | endclass : axi_m_seq_base | ||||||
|  |  | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class axi_simple_seq extends axi_m_seq_base; | ||||||
|  |     `uvm_object_utils(axi_simple_seq) | ||||||
|  |  | ||||||
|  |     // Constructor | ||||||
|  |     function new(string name = "axi_simple_seq"); | ||||||
|  |         super.new(name); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // Task to start the sequence | ||||||
|  |     virtual task body(); | ||||||
|  |         axi_transaction txn; | ||||||
|  |  | ||||||
|  |         super.body(); | ||||||
|  |  | ||||||
|  |         `uvm_info("axi_simple_seq", "Starting simple AXI sequence", UVM_LOW) | ||||||
|  |  | ||||||
|  |         `uvm_do(txn, env.get_axi_m_sequencer(), -1, { | ||||||
|  |             addr == 32'h0000_0000; // Example address | ||||||
|  |             data == 32'hDEAD_BEEF; // Example data | ||||||
|  |             strb == 'hf; // Example byte enable | ||||||
|  |         }); | ||||||
|  |     endtask | ||||||
|  | endclass : axi_simple_seq | ||||||
							
								
								
									
										49
									
								
								tb/tb_top.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								tb/tb_top.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | // Testbench top module for UVM-based verification environment | ||||||
|  | import uvm_pkg::*; | ||||||
|  |  | ||||||
|  | module tb_top (input logic sys_clk); | ||||||
|  |     logic clk; | ||||||
|  |     logic rst_n; | ||||||
|  |  | ||||||
|  |     // AXI interface for manager and subordinate | ||||||
|  |     `AXI_INTF a_if (.ACLK(clk), .ARESETn(rst_n)); | ||||||
|  |  | ||||||
|  |     // // Instantiate the UVM testbench interface | ||||||
|  |     // testbench_if tb_if ( | ||||||
|  |     //     .clk(clk), | ||||||
|  |     //     .m_if(m_if), | ||||||
|  |     //     .s_if(s_if) | ||||||
|  |     // ); | ||||||
|  |     // assign tb_if.rst_n = rst_n; | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     initial begin | ||||||
|  |         uvm_config_db#(virtual     `AXI_INTF.MANAGER)::set(uvm_root::get(), "uvm_test_top.env.axi_m", "axi_dvr_vif", a_if.MANAGER); | ||||||
|  |         uvm_config_db#(virtual `AXI_INTF.SUBORDINATE)::set(uvm_root::get(), "uvm_test_top.env.axi_s", "axi_dvr_vif", a_if.SUBORDINATE); | ||||||
|  |  | ||||||
|  |         run_test(); | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     initial begin | ||||||
|  |         $dumpfile("wave.vcd"); | ||||||
|  |         $dumpvars(); | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     // Clock generation | ||||||
|  |     // TODO: Move to interface. Parameterize frequency | ||||||
|  |     initial begin | ||||||
|  |         clk = 0; // Initialize clock to 0 at time 0 | ||||||
|  |         forever begin | ||||||
|  |             #5ns clk = ~clk; // Toggle clock every 5 ns | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     // -------------------------------------------------- | ||||||
|  |     initial begin | ||||||
|  |         rst_n = 0; | ||||||
|  |  | ||||||
|  |         #20ns rst_n = 1; // Release reset after 20 ns | ||||||
|  |     end | ||||||
|  | endmodule | ||||||
							
								
								
									
										13
									
								
								tb/tb_types.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tb/tb_types.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | // Types | ||||||
|  | package tb_types; | ||||||
|  |     // Agent type | ||||||
|  |     typedef enum { | ||||||
|  |         MANAGER, | ||||||
|  |         SUBORDINATE | ||||||
|  |     } agent_type_t; | ||||||
|  |  | ||||||
|  |     typedef enum { | ||||||
|  |         AXI_READ, | ||||||
|  |         AXI_WRITE | ||||||
|  |     } axi_transaction_type_t; | ||||||
|  | endpackage | ||||||
							
								
								
									
										129
									
								
								tb/test_base.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								tb/test_base.sv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | |||||||
|  | // Base class for testbench tests | ||||||
|  | class test_base extends uvm_test; | ||||||
|  |     `uvm_component_utils(test_base) | ||||||
|  |  | ||||||
|  |     tb_env env; | ||||||
|  |     uvm_table_printer tb_printer; | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     function new(string name, uvm_component parent); | ||||||
|  |         super.new(name, parent); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     function void build_phase(uvm_phase phase); | ||||||
|  |         super.build_phase(phase); | ||||||
|  |  | ||||||
|  |         env = tb_env::type_id::create("env", this); | ||||||
|  |         tb_printer = new("tb_printer"); | ||||||
|  |  | ||||||
|  |         uvm_config_db#(tb_env)::set(uvm_root::get(), "*", "env", env); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual function void end_of_elaboration_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("end_of_elaboration_phase", $sformatf("Testbench topology:\n%s", this.sprint(tb_printer)), UVM_LOW) | ||||||
|  |         display_uvm_config_db(); | ||||||
|  |         display_uvm_config_db("uvm_test_top.env.axi_m"); | ||||||
|  |         display_uvm_config_db("uvm_test_top.env.axi_s"); | ||||||
|  |         dump_uvm_config_db(); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual task run_phase(uvm_phase phase); | ||||||
|  |         uvm_objection objection; | ||||||
|  |  | ||||||
|  |         objection = phase.get_objection(); | ||||||
|  |  | ||||||
|  |         `uvm_info("run_phase", $sformatf("Raising objection"), UVM_LOW) | ||||||
|  |         phase.raise_objection(this); | ||||||
|  |  | ||||||
|  |         run_reset_phase(phase); | ||||||
|  |  | ||||||
|  |         run_test_phase(phase); | ||||||
|  |  | ||||||
|  |         run_flush_phase(phase); | ||||||
|  |  | ||||||
|  |         objection.set_drain_time(this, 20); | ||||||
|  |         `uvm_info("run_phase", $sformatf("Dropping objection"), UVM_LOW) | ||||||
|  |         phase.drop_objection(this); | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual task run_reset_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("run_reset_phase", $sformatf("Starting reset"), UVM_LOW) | ||||||
|  |         `uvm_info("run_reset_phase", $sformatf("Finishing reset"), UVM_LOW) | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual task run_test_phase(uvm_phase phase); | ||||||
|  |         `uvm_warning("run_test_phase", $sformatf("This content is expected to be implemented in specific tests")) | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual task run_flush_phase(uvm_phase phase); | ||||||
|  |         `uvm_info("run_flush_phase", $sformatf("Finishing test"), UVM_LOW) | ||||||
|  |     endtask | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     // Function to traverse and display all entries in uvm_config_db | ||||||
|  |     function void display_uvm_config_db(string scope = ".*"); | ||||||
|  |         uvm_resource_pool rp = uvm_resource_pool::get(); | ||||||
|  |         uvm_resource_types::rsrc_q_t resources; | ||||||
|  |  | ||||||
|  |         // Get all resources from the resource pool | ||||||
|  |         resources = rp.lookup_regex(scope, get_full_name()); | ||||||
|  |  | ||||||
|  |         rp.print_resources(resources, 1); | ||||||
|  |  | ||||||
|  |         `uvm_info("CONFIG_DB", "Traversing uvm_config_db contents:", UVM_LOW) | ||||||
|  |         if (resources.size() == 0) begin | ||||||
|  |             `uvm_info("CONFIG_DB", "No entries found in uvm_config_db", UVM_LOW) | ||||||
|  |             return; | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         // Iterate through all resources | ||||||
|  |         do begin | ||||||
|  |             uvm_resource_base r = resources.pop_front(); | ||||||
|  |  | ||||||
|  |             if (r == null) begin | ||||||
|  |                 `uvm_info("CONFIG_DB", "No more resources to process", UVM_LOW) | ||||||
|  |                 break; | ||||||
|  |             end | ||||||
|  |  | ||||||
|  |             `uvm_info("CONFIG_DB", $sformatf("Resource: %s", r.get_name()), UVM_LOW) | ||||||
|  |         end while (1); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     // Function to dump all entries in uvm_config_db | ||||||
|  |     function void dump_uvm_config_db(); | ||||||
|  |         uvm_resource_pool rp = uvm_resource_pool::get(); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  | endclass | ||||||
|  |  | ||||||
|  | // ---------------------------------------------------------------------- | ||||||
|  | class test_basic extends test_base; | ||||||
|  |     `uvm_component_utils(test_basic) | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     function new(string name, uvm_component parent); | ||||||
|  |         super.new(name, parent); | ||||||
|  |     endfunction | ||||||
|  |  | ||||||
|  |     // ------------------------------------------------------------ | ||||||
|  |     virtual task run_test_phase(uvm_phase phase); | ||||||
|  |         axi_simple_seq seq; | ||||||
|  |  | ||||||
|  |         `uvm_info("run_test_phase", $sformatf("Starting stimulus"), UVM_LOW) | ||||||
|  |         #100ns; | ||||||
|  |         seq = axi_simple_seq::type_id::create("seq"); | ||||||
|  |         if (seq == null) begin | ||||||
|  |             `uvm_fatal("run_test_phase", "Failed to create sequence instance") | ||||||
|  |         end | ||||||
|  |         seq.start(env.get_axi_m_sequencer()); | ||||||
|  |  | ||||||
|  |         `uvm_info("run_test_phase", $sformatf("Finishing stimulus"), UVM_LOW) | ||||||
|  |     endtask | ||||||
|  | endclass | ||||||
		Reference in New Issue
	
	Block a user