URL
https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk
Subversion Repositories qaz_libs
[/] [qaz_libs/] [trunk/] [avalon_lib/] [sim/] [src/] [amm_monitor/] [altera_avalon_mm_monitor_transactions.sv] - Rev 31
Compare with Previous | Blame | View Log
// (C) 2001-2016 Intel Corporation. All rights reserved.// Your use of Intel Corporation's design tools, logic functions and other// software and tools, and its AMPP partner logic functions, and any output// files any of the foregoing (including device programming or simulation// files), and any associated documentation or information are expressly subject// to the terms and conditions of the Intel Program License Subscription// Agreement, Intel MegaCore Function License Agreement, or other applicable// license agreement, including, without limitation, that your use is for the// sole purpose of programming logic devices manufactured by Intel and sold by// Intel or its authorized distributors. Please refer to the applicable// agreement for further details.// $File: //acds/rel/16.1/ip/sopc/components/verification/altera_avalon_mm_monitor_bfm/altera_avalon_mm_monitor_transactions.sv $// $Revision: #1 $// $Date: 2016/08/07 $// $Author: swbranch $//-----------------------------------------------------------------------------// =head1 NAME// altera_avalon_mm_monitor_transactions// =head1 SYNOPSIS// Memory Mapped Avalon Bus Protocol Checker//-----------------------------------------------------------------------------// =head1 DESCRIPTION// This module implements Avalon MM protocol transaction recording.//-----------------------------------------------------------------------------`timescale 1ps / 1psmodule altera_avalon_mm_monitor_transactions(clk,reset,tap);// =head1 PARAMETERSparameter AV_ADDRESS_W = 32; // address widthparameter AV_SYMBOL_W = 8; // default symbol is byteparameter AV_NUMSYMBOLS = 4; // number of symbols per wordparameter AV_BURSTCOUNT_W = 3; // burst port width// deprecated parameterparameter AV_WRITERESPONSE_W = 8;parameter AV_READRESPONSE_W = 8;parameter AV_CONSTANT_BURST_BEHAVIOR = 1; // Address, burstcount, transactionid and// avm_writeresponserequest need to be held constant// in burst transactionparameter AV_BURST_LINEWRAP = 0; // line wrapping addr is set to 1parameter AV_BURST_BNDR_ONLY = 0; // addr is multiple of burst sizeparameter REGISTER_WAITREQUEST = 0; // Waitrequest is registered at the slaveparameter AV_MAX_PENDING_READS = 1; // maximum pending read transfer countparameter AV_MAX_PENDING_WRITES = 0; // maximum pending write transfer countparameter AV_FIX_READ_LATENCY = 0; // fixed read latency in cyclesparameter USE_READ = 1; // use read portparameter USE_WRITE = 1; // use write portparameter USE_ADDRESS = 1; // use address portparameter USE_BYTE_ENABLE = 1; // use byteenable portparameter USE_BURSTCOUNT = 0; // use burstcount portparameter USE_READ_DATA = 1; // use readdata portparameter USE_READ_DATA_VALID = 1; // use readdatavalid portparameter USE_WRITE_DATA = 1; // use writedata portparameter USE_BEGIN_TRANSFER = 0; // use begintransfer portparameter USE_BEGIN_BURST_TRANSFER = 0; // use begintbursttransfer portparameter USE_WAIT_REQUEST = 1; // use waitrequest portparameter USE_ARBITERLOCK = 0; // Use arbiterlock pin on interfaceparameter USE_LOCK = 0; // Use lock pin on interfaceparameter USE_DEBUGACCESS = 0; // Use debugaccess pin on interfaceparameter USE_TRANSACTIONID = 0; // Use transactionid interface pinparameter USE_WRITERESPONSE = 0; // Use write response interface pinsparameter USE_READRESPONSE = 0; // Use read response interface pinsparameter USE_CLKEN = 0; // Use clken interface pinsparameter AV_READ_WAIT_TIME = 0; // Fixed wait time cycles whenparameter AV_WRITE_WAIT_TIME = 0; // USE_WAIT_REQUEST is 0localparam AV_DATA_W = AV_SYMBOL_W * AV_NUMSYMBOLS;localparam MAX_BURST_SIZE = USE_BURSTCOUNT ? 2**(lindex(AV_BURSTCOUNT_W)) : 1;localparam AV_TRANSACTIONID_W = 8;localparam INT_W = 32;localparam FIFO_MAX_LEVEL = 100;localparam FIFO_THRESHOLD = 50;parameter STORE_COMMAND = 1; // Store commands inside command queueparameter STORE_RESPONSE = 1; // Store responses inside response queuelocalparam TAP_W = 1 + // clken1 + // arbiterlock1 + // lock1 + // debugaccess((AV_TRANSACTIONID_W == 0)? 1:AV_TRANSACTIONID_W) + // transactionid((AV_TRANSACTIONID_W == 0)? 1:AV_TRANSACTIONID_W) + // readid((AV_TRANSACTIONID_W == 0)? 1:AV_TRANSACTIONID_W) + // writeid2 + // response1 + // writeresponserequest1 + // writeresponsevalid1 + // waitrequest1 + // readdatavalid((AV_DATA_W == 0)? 1:AV_DATA_W) + // readdata1 + // write1 + // read((AV_ADDRESS_W == 0)? 1:AV_ADDRESS_W) + // address((AV_NUMSYMBOLS == 0)? 1:AV_NUMSYMBOLS) + // byteenable((AV_BURSTCOUNT_W == 0)? 1:AV_BURSTCOUNT_W) + // burstcount1 + // beginbursttransfer1 + // begintransfer((AV_DATA_W == 0)? 1:AV_DATA_W); // writedata// =head1 PINS// =head2 Clock Interfaceinput clk;input reset;// =head2 Avalon Monitor Interface// Interface consists of Avalon Memory-Mapped Interface.// =cut// =podinput [TAP_W-1:0] tap;// =cutfunction int lindex;// returns the left index for a vector having a declared width// when width is 0, then the left index is set to 0 rather than -1input [31:0] width;lindex = (width > 0) ? (width-1) : 0;endfunction//--------------------------------------------------------------------------// synthesis translate_offimport verbosity_pkg::*;import avalon_mm_pkg::*;localparam VERSION = "16.1";typedef logic [lindex(AV_ADDRESS_W):0 ] AvalonAddress_t;typedef logic [lindex(AV_BURSTCOUNT_W):0 ] AvalonBurstCount_t;typedef logic [lindex(AV_TRANSACTIONID_W):0 ] AvalonTransactionId_t;typedef logic [lindex(MAX_BURST_SIZE):0][lindex(AV_NUMSYMBOLS):0 ] AvalonByteEnable_t;typedef logic [lindex(MAX_BURST_SIZE):0][lindex(AV_DATA_W):0 ] AvalonData_t;typedef logic [lindex(MAX_BURST_SIZE):0][lindex(INT_W):0 ] AvalonIdle_t;typedef logic [lindex(MAX_BURST_SIZE):0][lindex(INT_W):0 ] AvalonLatency_t;typedef logic [lindex(MAX_BURST_SIZE):0][lindex(AV_READRESPONSE_W):0 ] AvalonReadResponse_t;typedef logic [lindex(MAX_BURST_SIZE):0][lindex(AV_WRITERESPONSE_W):0] AvalonWriteResponse_t;typedef logic [lindex(MAX_BURST_SIZE):0][1:0] AvalonReadResponseStatus_t;typedef struct packed {Request_t request;AvalonAddress_t address;AvalonBurstCount_t burst_count;AvalonData_t data;AvalonByteEnable_t byte_enable;AvalonIdle_t idle;int burst_cycle;logic arbiterlock;logic lock;logic debugaccess;AvalonTransactionId_t transaction_id;time begin_time;} Command_t;typedef struct packed {Request_t request;AvalonAddress_t address;AvalonBurstCount_t burst_count;AvalonData_t data;AvalonByteEnable_t byte_enable;AvalonLatency_t wait_latency;AvalonLatency_t read_latency;int write_latency;int seq_count;int burst_size;AvalonTransactionId_t read_id;AvalonTransactionId_t write_id;AvalonReadResponseStatus_t read_response;AvalonResponseStatus_t write_response;time begin_time;time end_time;} Response_t;// unpack Avalon bus interface tap into individual port signalslogic avs_waitrequest;logic avs_readdatavalid;logic [lindex(AV_DATA_W):0] avs_readdata;logic avs_write;logic avs_read;logic [lindex(AV_ADDRESS_W):0] avs_address;logic [lindex(AV_NUMSYMBOLS):0] avs_byteenable;logic [lindex(AV_BURSTCOUNT_W):0] avs_burstcount;logic avs_beginbursttransfer;logic avs_begintransfer;logic [lindex(AV_DATA_W):0] avs_writedata;logic avs_arbiterlock;logic avs_lock;logic avs_debugaccess;logic [lindex(AV_TRANSACTIONID_W):0] avs_transactionid;logic [lindex(AV_TRANSACTIONID_W):0] avs_readid;logic [lindex(AV_TRANSACTIONID_W):0] avs_writeid;logic [1:0] avs_response;logic avs_writeresponserequest;logic avs_writeresponsevalid;logic avs_clken;logic clken_register = 1'b1;string message = "*uninitialized*";int transaction_fifo_max = FIFO_MAX_LEVEL;int transaction_fifo_threshold = FIFO_THRESHOLD;int response_addr_offset = 0;int command_addr_offset = 0;int command_sequence_counter = 1;Command_t command_queue[$];Command_t current_command = '0;Command_t client_command = '0;Response_t write_response_queue[$];Response_t read_response_queue[$];Response_t new_response = '0;Response_t return_response = 'x;Response_t completed_command = 'x;Response_t completed_read_command = 'x;Response_t completed_write_command = 'x;Response_t issued_read_command_queue[$];Response_t issued_write_command_queue[$];AvalonResponseStatus_t null_response_status;int consolidate_write_burst_transactions = 1;int wait_time = 0;int write_burst_response_counter = 0;int write_latency = 0;int write_burst_command_counter = 0;int read_latency = 0;int command_waitrequested_start = 0;int read_response_burst_counter = 0;bit start_construct_complete_read_response = 0;bit start_construct_complete_write_response = 0;int clock_counter = 0;int current_time = 0;int clock_snapshot[$];AvalonBurstCount_t avs_burstcount_int;//--------------------------------------------------------------------------// =head1 Public Methods API// This section describes the public methods in the application programming// interface (API). In this case the application program is the test bench// which instantiates and controls and queries state of this component.// Test programs must only use these public access methods and events to// communicate with this BFM component. The API and the module pins// are the only interfaces in this component that are guaranteed to be// stable. The API will be maintained for the life of the product.// While we cannot prevent a test program from directly accessing internal// tasks, functions, or data private to the BFM, there is no guarantee that// these will be present in the future. In fact, it is best for the user// to assume that the underlying implementation of this component can// and will change.//--------------------------------------------------------------------------event signal_fatal_error; // public// Signal that a fatal error has occurred. Terminates simulation.event signal_transaction_fifo_threshold; // public// Signal that the transaction FIFO threshold level has been exceededevent signal_transaction_fifo_overflow; // public// Signal that the FIFO is full and further transactions are being droppedfunction automatic string get_version(); // public// Return component version as a string of three integers separated by// periods. For example, version 9.1 sp1 is encoded as "9.1.1".string ret_version = "10.1";return ret_version;endfunctionfunction automatic void set_transaction_fifo_max( // publicint level);// Set the maximum fullness level of the FIFO. The event// signal_transaction_fifo_max is triggered when this// level is exceeded.transaction_fifo_max = level;endfunctionfunction automatic int get_transaction_fifo_max();// Get the maximum transaction FIFO depth.return transaction_fifo_max;endfunctionfunction automatic void set_transaction_fifo_threshold( // publicint level);// Set the threshold alert level of the FIFO. The event// signal_transaction_fifo_threshold is triggered when this// level is exceeded.transaction_fifo_threshold = level;endfunctionfunction automatic int get_transaction_fifo_threshold();// Get the transaction FIFO threshold level.return transaction_fifo_threshold;endfunction//--------------------------------------------------------------------------// Command Transaction API//--------------------------------------------------------------------------event signal_command_received; // public// This event notifies the test bench that a command has been detected// on the Avalon port.// The testbench can respond with a set_interface_wait_time// call on receiving this event to dynamically back pressure the driving// Avalon master. Alternatively, wait_time which was previously set may// be used continuously for a set of transactions.function automatic void set_command_transaction_mode( // publicint mode);// By default, write burst commands are consolidated into a single// command transaction containing the write data for all burst cycles// in that command. This mode is set when the mode argument equals 0.// When the mode argument is set to 1, the default is overridden and// write burst commands yield one command transaction per burst cycle.$sformat(message, "%m: method called arg0 %0d ", mode);print(VERBOSITY_DEBUG, message);consolidate_write_burst_transactions = (mode == 0) ? 1:0;endfunctionfunction automatic void pop_command(); // public// Pop the command descriptor from the queue so that it can be// queried with the get_command methods by the test bench.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);client_command = command_queue.pop_back();case(client_command.request)REQ_READ: $sformat(message, "%m: read addr %0x",client_command.address);REQ_WRITE: $sformat(message,"%m: write addr %0x",client_command.address);REQ_IDLE: $sformat(message, "%m: idle transaction");default: $sformat(message, "%m: illegal transaction");endcaseprint(VERBOSITY_DEBUG, message);endfunctionfunction automatic int get_command_queue_size(); // public// Query the command queue to determine number of pending commands$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return command_queue.size();endfunctionfunction automatic Request_t get_command_request(); // public// Get the received command descriptor to determine command request type.// A command type may be REQ_READ or REQ_WRITE. These type values// are defined in the enumerated type called Request_t which is// imported with the package named avalon_mm_pkg.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.request;endfunctionfunction automatic logic [lindex(AV_ADDRESS_W):0] get_command_address(); // public// Query the received command descriptor for the transaction address.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.address;endfunctionfunction automatic [lindex(AV_BURSTCOUNT_W):0] get_command_burst_count();// public// Query the received command descriptor for the transaction burst count.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.burst_count;endfunctionfunction automatic logic [AV_DATA_W-1:0] get_command_data( // publicint index);// Query the received command descriptor for the transaction write data.// The burst commands with burst count greater than 1, the index// selects the write data cycle.$sformat(message, "%m: method called arg0 %0d", index);print(VERBOSITY_DEBUG, message);if (__check_transaction_index(index))return client_command.data[index];elsereturn('x);endfunctionfunction automatic logic [AV_NUMSYMBOLS-1:0] get_command_byte_enable(// publicint index);// Query the received command descriptor for the transaction byte enable.// The burst commands with burst count greater than 1, the index// selects the data cycle.$sformat(message, "%m: method called arg0 %0d", index);print(VERBOSITY_DEBUG, message);if (__check_transaction_index(index))return client_command.byte_enable[index];elsereturn('x);endfunctionfunction automatic int get_command_burst_cycle(); // public// Write burst commands are received and processed by the slave BFM as// a sequence of discrete commands. The number of commands corresponds// to the burst count. A separate command descriptor is constructed for// each write burst cycle, corresponding to a partially completed burst.// Write data is incrementally added to each new descriptor in each burst// cycle until the command descriptor in final burst cycle contains// the full burst command data array.// The burst cycle field returned by this method tells the test bench// which burst cycle was active when this descriptor was constructed.// This facility enables the testbench to query partially completed// write burst operations. In other words, the testbench can query// the write data word on each burst cycle as it arrives and begin to// process it immediately rather than waiting until the entire burst// has been received. This makes it possible to perform pipelined write// burst processing in the test bench.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.burst_cycle;endfunctionfunction automatic logic get_command_arbiterlock(); // public// Query the received command descriptor for the transaction arbiterlock.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.arbiterlock;endfunctionfunction automatic logic get_command_lock(); // public// Query the received command descriptor for the transaction lock.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.lock;endfunctionfunction automatic logic get_command_debugaccess(); // public// Query the received command descriptor for the transaction debugaccess.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.debugaccess;endfunctionfunction automatic logic [AV_TRANSACTIONID_W-1:0] get_command_transaction_id(); // public// Query the received command descriptor for the transaction ID.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.transaction_id;endfunctionfunction automatic logic [AV_TRANSACTIONID_W-1:0] get_command_write_response_request(); // public$sformat(message, "%m: This API is no longer supported.");print(VERBOSITY_DEBUG, message);return 0;endfunctionfunction automatic time get_command_begin_time(); // public// Returns the begin time of the transaction in the response descriptor that// has been popped from the response queue.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return client_command.begin_time;endfunction//--------------------------------------------------------------------------// Response Transaction API//--------------------------------------------------------------------------event signal_read_response_complete; // public// This event signals that the read response has been received and// pushed into the response queue.event signal_write_response_complete; // public// This event signals that the write response has been received and// pushed into the response queue.event signal_response_complete; // public// This event will fire when either signal_read_response_complete// or signal_write_response_complete fires and indicates that either// a read or a write response has been received and pushed into the// response queue.function automatic int get_command_issued_queue_size(); // public// Query the issued command queue to determine the number of// commands that have been driven to the system interconnect// fabric, but have not yet completed.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return (issued_read_command_queue.size() + issued_write_command_queue.size());endfunctionfunction automatic logic [lindex(AV_ADDRESS_W):0] get_response_address(); // public// Returns the transaction address in the response descriptor that// has been popped from the response queue.$sformat(message, "%m: called");print(VERBOSITY_DEBUG, message);return return_response.address;endfunctionfunction automatic logic [AV_NUMSYMBOLS-1:0] get_response_byte_enable(// publicint index);// Returns the value of the byte enables in the response descriptor// that has been popped from the response queue. Each cycle of a// burst response is addressed individually by the specified index.$sformat(message, "%m: method called arg0 %0d", index);print(VERBOSITY_DEBUG, message);if (__check_transaction_index(index))return return_response.byte_enable[index];elsereturn 'x;endfunctionfunction automatic logic [lindex(AV_BURSTCOUNT_W):0] get_response_burst_size();// public// Returns the size of the response transaction burst in the// response descriptor that has been popped from the response queue.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return return_response.burst_count;endfunctionfunction automatic logic [AV_DATA_W-1:0] get_response_data( //publicint index);// Returns the transaction data in the response descriptor// that has been popped from the response queue. Each cycle in a// burst response is addressed individually by the specified index.// In the case of read responses, the data is the data captured on// the avs_readdata interface pin. In the case of write responses,// the data on the driven avs_writedata pin is captured and// reflected here.$sformat(message, "%m: method called arg0 %0d", index);print(VERBOSITY_DEBUG, message);if (__check_transaction_index(index))return return_response.data[index];elsereturn 'x;endfunctionfunction automatic int get_response_latency( // publicint index = 0);// Returns the transaction read latency in the response descriptor// that has been popped from the response queue. Each cycle in a// burst read has its own latency entry. For write transaction// responses the returned value will always be 0.$sformat(message, "%m: method called arg0 %0d", index);print(VERBOSITY_DEBUG, message);if (return_response.request == REQ_READ)if (__check_transaction_index(index)) beginreturn return_response.read_latency[index];end else beginreturn -1;endelse if (return_response.request == REQ_WRITE) beginif (index > 0) begin$sformat(message, "%m: Write response does not require burst index. Index value will be ignored");print(VERBOSITY_WARNING, message);endreturn return_response.write_latency;end else beginreturn -1;endendfunctionfunction automatic time get_response_begin_time(); // public// Returns the begin time of the transaction in the response descriptor that// has been popped from the response queue.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return return_response.begin_time;endfunctionfunction automatic time get_response_end_time(); // public// Returns the begin time of the transaction in the response descriptor that// has been popped from the response queue.$sformat(message, "%m: method called. Returning %0t", return_response.end_time);print(VERBOSITY_DEBUG, message);return return_response.end_time;endfunctionfunction automatic Request_t get_response_request(); // public// Returns the transaction command type in the response descriptor// that has been popped from the response queue.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return return_response.request;endfunctionfunction automatic int get_response_queue_size(); // public// Queries the write and read response queue to determine// number of response descriptors currently stored in the BFM.// This is the number of responses the test program can immediately// pop off the response queue for further processing.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return read_response_queue.size() + write_response_queue.size();endfunctionfunction automatic int get_response_wait_time( // publicint index);// Returns the wait time for a transaction in the response descriptor// that has been popped from the response queue. Each cycle in a burst// has its own wait time entry.$sformat(message, "%m: method called arg0 %0d", index);print(VERBOSITY_DEBUG, message);if (__check_transaction_index(index))return return_response.wait_latency[index];elsereturn -1;endfunctionfunction automatic void pop_response(); // public// Pop the transaction descriptor from the queue so that it can be// queried with the get_response methods by the test bench.int read_queue_head_seq_count = read_response_queue[$].seq_count;int write_queue_head_seq_count = write_response_queue[$].seq_count;$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);if (read_queue_head_seq_count == write_queue_head_seq_count) begin$sformat(message,"%m: Identical sequence count in read and write response queues");print(VERBOSITY_ERROR, message);-> signal_fatal_error;return;end else beginif ((read_response_queue.size() > 0) &&((read_queue_head_seq_count < write_queue_head_seq_count) ||(write_queue_head_seq_count == 0))) beginreturn_response = read_response_queue.pop_back();$sformat(message,"%m: Pop read response");print(VERBOSITY_DEBUG, message);end else if (write_response_queue.size() > 0) beginreturn_response = write_response_queue.pop_back();$sformat(message,"%m: Pop write response");print(VERBOSITY_DEBUG, message);end else begin$sformat(message,"%m: Failed to pop from response queues");print(VERBOSITY_ERROR, message);-> signal_fatal_error;return;endendif (return_response.seq_count == 0) begin// sequence counter is initialized to 1$sformat(message,"%m: Response transaction has sequence count of 0");print(VERBOSITY_WARNING, message);end__print_response("Master Response", return_response);///fooendfunctionfunction automatic AvalonResponseStatus_t get_read_response_status( // publicint index);// Returns the transaction response status in the read response// descriptor that has been popped from the response queue.// If API is called when read response is not enabled, it will// return default value i.e. OKAY$sformat(message, "%m: called");print(VERBOSITY_DEBUG, message);if (return_response.request == REQ_READ) beginif (USE_READRESPONSE == 1) beginreturn AvalonResponseStatus_t'(return_response.read_response[index]);end else begin$sformat(message, "%m: Read response is disabled, returning default value");print(VERBOSITY_WARNING, message);return null_response_status;endend else begin$sformat(message, "%m: Read response queried on write response transaction");print(VERBOSITY_WARNING, message);return null_response_status;endendfunctionfunction automatic AvalonReadResponse_t get_response_read_response( // publicint index);// API is no longer supported$sformat(message, "%m: API is not longer supported. Please use get_read_response_status API");print(VERBOSITY_WARNING, message);return '0;endfunctionfunction automatic AvalonWriteResponse_t get_response_write_response( // publicint index);// API is no longer supported$sformat(message, "%m: API is not longer supported. Please use get_write_response_status API");print(VERBOSITY_WARNING, message);return '0;endfunctionfunction automatic AvalonTransactionId_t get_response_read_id(); // public// Returns the read id of transaction in the response descriptor that// has been popped from the response queue.$sformat(message, "%m: called");print(VERBOSITY_DEBUG, message);if (return_response.request == REQ_WRITE) begin$sformat(message, "%m: Read response queried on write response transaction");print(VERBOSITY_WARNING, message);endreturn return_response.read_id;endfunctionfunction automatic AvalonResponseStatus_t get_write_response_status(); // public// Returns the transaction response status in the write response// descriptor that has been popped from the response queue.// If API is called when write response is not enabled or enabled but// write response not requested, it will return default value i.e. OKAY$sformat(message, "%m: called");print(VERBOSITY_DEBUG, message);if (return_response.request == REQ_WRITE) beginif (USE_WRITERESPONSE == 1) beginreturn return_response.write_response;end else begin$sformat(message,"%m: Write response is disabled or enabled but no write response requested, returning default value");print(VERBOSITY_WARNING, message);return null_response_status;endend else begin$sformat(message, "%m: Write response queried on read response transaction");print(VERBOSITY_WARNING, message);return null_response_status;endendfunctionfunction automatic AvalonTransactionId_t get_response_write_id(); // public// Returns the write id of transaction in the response descriptor that// has been popped from the response queue.$sformat(message, "%m: called");print(VERBOSITY_DEBUG, message);if (return_response.request == REQ_READ) begin$sformat(message, "%m: Write response queried on read response transaction");print(VERBOSITY_WARNING, message);endreturn return_response.write_id;endfunctionfunction automatic logic get_clken(); // public// Return the clken status$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return clken_register;endfunctionfunction automatic int get_write_response_queue_size(); // public// Queries the write response queue to determine// number of response descriptors currently stored in the BFM.// This is the number of responses the test program can immediately// pop off the response queue for further processing.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return write_response_queue.size();endfunctionfunction automatic int get_read_response_queue_size(); // public// Queries the read response queue to determine// number of response descriptors currently stored in the BFM.// This is the number of responses the test program can immediately// pop off the response queue for further processing.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);return read_response_queue.size();endfunctiontask automatic init(); // public// Initializes the counters and clear the queue.$sformat(message, "%m: method called");print(VERBOSITY_DEBUG, message);__init_descriptors();__init_queues();endtask// =cut//--------------------------------------------------------------------------// Private Methods// Note that private methods and events are prefixed with '__'//--------------------------------------------------------------------------event __command_issued;function automatic int __check_transaction_index(int index);if (index > lindex(MAX_BURST_SIZE)) begin$sformat(message,"%m: Cycle index %0d exceeds MAX_BURST_SIZE-1 %0d",index, lindex(MAX_BURST_SIZE));print(VERBOSITY_ERROR, message);->signal_fatal_error;return 0;end else beginreturn 1;endendfunctionfunction automatic void __print_response(string text,Response_t response);string message = "";print_divider(VERBOSITY_DEBUG);$sformat(message, "%m: %s", text);print(VERBOSITY_DEBUG, message);$sformat(message, "Request: %s", __request_str(response.request));print(VERBOSITY_DEBUG, message);$sformat(message, "Address: %0x", response.address);print(VERBOSITY_DEBUG, message);$sformat(message, "Burst Count: %0x", response.burst_count);print(VERBOSITY_DEBUG, message);for (int i=0; i<response.burst_count; i++) beginif (response.request == REQ_WRITE) begin$sformat(message, " index: %0d wait: %0d",i, response.wait_latency[i]);end else if (response.request == REQ_READ) begin$sformat(message," index: %0d data: %0x wait: %0d read latency: %0d",i, response.data[i],response.wait_latency[i], response.read_latency[i]);end else begin$sformat(message, " Invalid request field");endprint(VERBOSITY_DEBUG, message);endendfunctionfunction automatic void __init_descriptors();new_response = '0;current_command = '0;return_response = '0;completed_command = '0;command_addr_offset = 0;response_addr_offset = 0;client_command = '0;return_response = '0;command_sequence_counter = 1;wait_time = 0;write_burst_response_counter = 0;write_latency = 0;write_burst_command_counter = 0;read_latency = 0;command_waitrequested_start = 0;start_construct_complete_read_response = 0;start_construct_complete_write_response = 0;read_response_burst_counter = 0;endfunctionfunction automatic void __init_queues();issued_read_command_queue = {};issued_write_command_queue = {};read_response_queue = {};write_response_queue = {};command_queue = {};endfunctionfunction automatic string __request_str(Request_t request);case(request)REQ_READ: return "Read";REQ_WRITE: return "Write";REQ_IDLE: return "Idle";endcaseendfunction//--------------------------------------------------------------------------// Local Machinery//--------------------------------------------------------------------------always @(signal_fatal_error) abort_simulation();always @(*) begin{avs_clken,avs_arbiterlock,avs_lock,avs_debugaccess,avs_transactionid,avs_readid,avs_writeid,avs_response,avs_writeresponserequest,avs_writeresponsevalid,avs_waitrequest,avs_readdatavalid,avs_readdata,avs_write,avs_read,avs_address,avs_byteenable,avs_burstcount,avs_beginbursttransfer,avs_begintransfer,avs_writedata} <= tap;endassign avs_burstcount_int = (USE_BURSTCOUNT ? avs_burstcount : 'd1);//-----------------------------------------------------------------------------// This two block monitoring the response transaction//-----------------------------------------------------------------------------always @(posedge clk or posedge reset) beginclock_counter = clock_counter +1;if (reset) begininit();end else beginif (!USE_CLKEN || avs_clken == 1) beginsampled_response();endendendalways @(posedge clk or posedge reset) beginif (reset) begininit();end else beginif (!USE_CLKEN || avs_clken == 1) beginif ((get_command_issued_queue_size() == 0) &&(start_construct_complete_write_response == 0) &&start_construct_complete_read_response == 0) begin@__command_issued;endif (issued_write_command_queue.size() > 0) beginif (start_construct_complete_write_response == 0) begincompleted_write_command = issued_write_command_queue.pop_back();start_construct_complete_write_response = 1;endendif (issued_read_command_queue.size() > 0) beginif (read_response_burst_counter == 0 &&start_construct_complete_read_response == 0) begincompleted_read_command = issued_read_command_queue.pop_back();start_construct_complete_read_response = 1;endendif (start_construct_complete_read_response)monitor_response(completed_read_command);if (start_construct_complete_write_response)monitor_response(completed_write_command);endendend//-----------------------------------------------------------------------------// This task monitoring the command port info and pass it to response// transaction.//-----------------------------------------------------------------------------task automatic sampled_response();if (avs_read) beginresponse_addr_offset = 0;new_response.request = REQ_READ;new_response.data = 'x;new_response.wait_latency = 'x;new_response.byte_enable = 'x;new_response.write_latency = 'x;new_response.burst_count = avs_burstcount_int;new_response.burst_size = avs_burstcount_int;new_response.seq_count = command_sequence_counter++;;new_response.address = avs_address;new_response.read_id = 'x;new_response.read_response = 'x;new_response.begin_time = $time;if (USE_READ_DATA_VALID || USE_BURSTCOUNT)new_response.read_latency = 'x;elsenew_response.read_latency = AV_FIX_READ_LATENCY;if (avs_waitrequest) beginwait_time++;return;endnew_response.wait_latency[response_addr_offset] = wait_time;new_response.byte_enable[response_addr_offset] = avs_byteenable;issued_read_command_queue.push_front(new_response);-> __command_issued;write_burst_response_counter = 0;wait_time = 0;clock_snapshot.push_front(clock_counter);end else if (avs_write) beginif (write_burst_response_counter == 0) beginwrite_burst_response_counter = avs_burstcount_int;new_response.seq_count = command_sequence_counter++;;response_addr_offset = 0;endnew_response.read_latency = 'x;new_response.request = REQ_WRITE;new_response.data[response_addr_offset] = avs_writedata;new_response.byte_enable[response_addr_offset] = avs_byteenable;new_response.write_latency = 'x;if (response_addr_offset == 0) beginnew_response.burst_count = avs_burstcount_int;new_response.burst_size = avs_burstcount_int;new_response.address = avs_address;new_response.begin_time = $time;endnew_response.read_id = 'x;new_response.read_response = 'x;if (avs_waitrequest) beginwait_time++;return;endnew_response.wait_latency[response_addr_offset] = wait_time;if (USE_WRITERESPONSE == 0) beginif (response_addr_offset == (new_response.burst_count-1)) beginif (STORE_RESPONSE == 1) beginif (get_response_queue_size() < transaction_fifo_max) beginnew_response.end_time = $time;write_response_queue.push_front(new_response);if (get_response_queue_size() > transaction_fifo_threshold)->signal_transaction_fifo_threshold;end else begin$sformat(message, "%m(%0d): FIFO overflow! Transaction dropped.", `__LINE__);print(VERBOSITY_WARNING, message);->signal_transaction_fifo_overflow;endend-> signal_write_response_complete;endend else beginif (response_addr_offset == (new_response.burst_count-1)) beginissued_write_command_queue.push_front(new_response);-> __command_issued;endendresponse_addr_offset++;write_burst_response_counter--;wait_time = 0;endendtask//-----------------------------------------------------------------------------// This task monitoring the response port and construct a full response// transaction.//-----------------------------------------------------------------------------task automatic monitor_response(ref Response_t completed_response);case(completed_response.request)REQ_WRITE: begin// no response transaction while USE_WRITERESPONSE = 0if (USE_WRITERESPONSE == 1) beginif (!avs_writeresponsevalid) beginwrite_latency++;return;endcompleted_response.write_id = avs_writeid;completed_response.write_latency = write_latency;if (!$cast(completed_response.write_response, avs_response))begin$sformat(message, "%m: Response value is not valid when write response is valid");print(VERBOSITY_FAILURE, message);endwrite_latency = 0;if (STORE_RESPONSE == 1) beginif (get_response_queue_size() < transaction_fifo_max) begincompleted_response.end_time = $time;write_response_queue.push_front(completed_response);if (get_response_queue_size() > transaction_fifo_threshold) begin->signal_transaction_fifo_threshold;endend else begin$sformat(message, "%m(%0d): FIFO overflow! Transaction dropped.", `__LINE__);print(VERBOSITY_WARNING, message);->signal_transaction_fifo_overflow;endend-> signal_write_response_complete;start_construct_complete_write_response = 0;endendREQ_READ: beginif (USE_READ_DATA_VALID || USE_BURSTCOUNT) beginif (!avs_readdatavalid) beginread_latency++;return;endcompleted_response.data[read_response_burst_counter] = avs_readdata;completed_response.read_latency[read_response_burst_counter] = read_latency;if (USE_READRESPONSE) begincompleted_response.read_id = avs_readid;if (!$cast(completed_response.read_response[read_response_burst_counter], avs_response))begin$sformat(message, "%m: Response value is not valid when read response is valid");print(VERBOSITY_FAILURE, message);endendread_latency = 0;end else beginif (AV_FIX_READ_LATENCY > 0) beginif (clock_counter - clock_snapshot[$] < AV_FIX_READ_LATENCY) beginreturn;endcurrent_time = clock_snapshot.pop_back();endcompleted_response.read_latency[0] = AV_FIX_READ_LATENCY;completed_response.data[0] = avs_readdata;if (USE_READRESPONSE) begincompleted_response.read_id = avs_readid;if (!$cast(completed_response.read_response[0], avs_response))begin$sformat(message, "%m: Response value is not valid when read response is valid");print(VERBOSITY_FAILURE, message);endendread_latency = 0;endif (read_response_burst_counter == completed_response.burst_count-1) beginif (STORE_RESPONSE == 1) beginif (get_response_queue_size() < transaction_fifo_max) begincompleted_response.end_time = $time;read_response_queue.push_front(completed_response);if (get_response_queue_size() > transaction_fifo_threshold)->signal_transaction_fifo_threshold;end else begin$sformat(message, "%m(%0d): FIFO overflow! Transaction dropped.", `__LINE__);print(VERBOSITY_WARNING, message);->signal_transaction_fifo_overflow;endend->signal_read_response_complete;read_response_burst_counter = 0;start_construct_complete_read_response = 0;end else beginread_response_burst_counter++;endendendcaseendtaskalways @(signal_read_response_complete orsignal_write_response_complete orposedge reset) beginif (!reset) begin->signal_response_complete;endend//-----------------------------------------------------------------------------// This block monitoring the command transaction//-----------------------------------------------------------------------------always @(posedge clk or posedge reset) beginclken_register <= avs_clken;if (reset) begininit();end else beginif (!USE_CLKEN || avs_clken == 1) beginmonitor_command();endendend//-----------------------------------------------------------------------------// This task monitoring the command port and construct a full command// transaction.//-----------------------------------------------------------------------------task automatic monitor_command();if (avs_write) beginif (write_burst_command_counter == 0) beginwrite_burst_command_counter = avs_burstcount_int;command_addr_offset = 0;endcurrent_command.request = REQ_WRITE;current_command.data[command_addr_offset] = avs_writedata;current_command.byte_enable[command_addr_offset] = avs_byteenable;if (command_addr_offset == 0) begincurrent_command.address = avs_address;current_command.burst_count = avs_burstcount_int;current_command.transaction_id = avs_transactionid;endcurrent_command.burst_cycle = command_addr_offset;current_command.arbiterlock = avs_arbiterlock;current_command.lock = avs_lock;current_command.debugaccess = avs_debugaccess;if (command_waitrequested_start == 0) beginif ((consolidate_write_burst_transactions &&(command_addr_offset == current_command.burst_count-1)) ||!consolidate_write_burst_transactions) beginif (STORE_COMMAND == 1) beginif (get_command_queue_size() < transaction_fifo_max) begincurrent_command.begin_time = $time;command_queue.push_front(current_command);if (get_command_queue_size() > transaction_fifo_threshold)->signal_transaction_fifo_threshold;end else begin$sformat(message, "%m(%0d): FIFO overflow! Transaction dropped.", `__LINE__);print(VERBOSITY_WARNING, message);->signal_transaction_fifo_overflow;endend->signal_command_received;endif (avs_waitrequest) begincommand_waitrequested_start = 1;return;endend else beginif (avs_waitrequest)return;elsecommand_waitrequested_start = 0;endcommand_addr_offset++;write_burst_command_counter--;end else if (avs_read) begincurrent_command = 'x;write_burst_command_counter = 0;command_addr_offset = 0;current_command.request = REQ_READ;current_command.address = avs_address;current_command.data = 'x;current_command.byte_enable = avs_byteenable;current_command.burst_count = avs_burstcount_int;current_command.arbiterlock = avs_arbiterlock;current_command.lock = avs_lock;current_command.debugaccess = avs_debugaccess;current_command.transaction_id = avs_transactionid;if (command_waitrequested_start == 0) beginif (STORE_COMMAND == 1) beginif (get_command_queue_size() < transaction_fifo_max) begincurrent_command.begin_time = $time;command_queue.push_front(current_command);if (get_command_queue_size() > transaction_fifo_threshold)->signal_transaction_fifo_threshold;end else begin$sformat(message, "%m(%0d): FIFO overflow! Transaction dropped.", `__LINE__);print(VERBOSITY_WARNING, message);->signal_transaction_fifo_overflow;endend->signal_command_received;if (avs_waitrequest) begincommand_waitrequested_start = 1;return;endend else beginif (avs_waitrequest)return;elsecommand_waitrequested_start = 0;endendendtask// synthesis translate_onendmodule
