This post will explain how to use analysis FIFOs. Let’s assume I wanted a scoreboard that compares two streams of jelly beans; one stream is for “expected” jelly beans, the other is for “actual” jelly beans. Also assume the jelly beans are fed to the scoreboard asynchronously. To synchronize the jelly beans, I used two analysis FIFOs:
Asynchronous Jelly Bean Scoreboard
This is a sample code to implement the above scoreboard. The code should be self-explanatory. One note is that the get
is a blocking task to get the next item from the FIFO (lines 43 and 44).
When both the expected jelly bean and the actual jelly bean become available, the scoreboard compares them (line 45). Before finishing a simulation (extract_phase
), the scoreboard checks whether there are leftover jelly beans in either FIFO. Isn’t it easy?
class asynchronous_jelly_bean_scoreboard extends uvm_component;
`uvm_component_utils( asynchronous_jelly_bean_scoreboard )
uvm_analysis_export #( jelly_bean_transaction ) expected_analysis_export;
uvm_analysis_export #( jelly_bean_transaction ) actual_analysis_export;
uvm_tlm_analysis_fifo#( jelly_bean_transaction ) expected_jelly_bean_fifo;
uvm_tlm_analysis_fifo#( jelly_bean_transaction ) actual_jelly_bean_fifo;
// Function: new
//-------------------------------------------------------------------------
function new( string name, uvm_component parent );
super.new( name, parent );
endfunction: new
// Function: build_phase
//-------------------------------------------------------------------------
virtual function void build_phase( uvm_phase phase );
super.build_phase( phase );
expected_analysis_export = new( "expected_analysis_export", this );
actual_analysis_export = new( "actual_analysis_export", this );
expected_jelly_bean_fifo = new( "expected_jelly_bean_fifo", this );
actual_jelly_bean_fifo = new( "actual_jelly_bean_fifo", this );
endfunction: build_phase
// Function: connect_phase
//-------------------------------------------------------------------------
virtual function void connect_phase( uvm_phase phase );
super.connect_phase( phase );
expected_analysis_export.connect( expected_jelly_bean_fifo.analysis_export );
actual_analysis_export.connect( actual_jelly_bean_fifo.analysis_export );
endfunction: connect_phase
// Task: main_phase
//-------------------------------------------------------------------------
virtual task main_phase( uvm_phase phase );
jelly_bean_transaction expected_jelly_bean;
jelly_bean_transaction actual_jelly_bean;
super.main_phase( phase );
forever begin
expected_jelly_bean_fifo.get_peek_export.get( expected_jelly_bean );
actual_jelly_bean_fifo.get_peek_export.get( actual_jelly_bean );
if ( expected_jelly_bean.compare( actual_jelly_bean ) == 0 ) begin
`uvm_error( "main_phase",
{ "jelly bean mismatch: ",
"expected:", expected_jelly_bean.convert2string(),
"actual:", actual_jelly_bean.convert2string() } )
end
end
endtask: main_phase
// Function: extract_phase - checks leftover jelly beans in the FIFOs
//-------------------------------------------------------------------------
virtual function void extract_phase( uvm_phase phase );
jelly_bean_transaction jelly_bean;
super.extract_phase( phase );
if ( expected_jelly_bean_fifo.try_get( jelly_bean ) ) begin
`uvm_error( "expected_jelly_bean_fifo",
{ "found a leftover jelly bean: ", jelly_bean.convert2string() } )
end
if ( actual_jelly_bean_fifo.try_get( jelly_bean ) ) begin
`uvm_error( "actual_jelly_bean_fifo",
{ "found a leftover jelly bean: ", jelly_bean.convert2string() } )
end
endfunction: extract_phase
endclass: asynchronous_jelly_bean_scoreboard