//Macros to create the uvm_analysis_imp ports (just an export + write function)
`uvm_analysis_imp_decl(_apb_port)
`uvm_analysis_imp_decl(_spi_port)
class spi_scoreboard extends uvm_scoreboard;
`uvm_component_utils(spi_scoreboard)
string m_name;
virtual irq_if irq_if_1;
///golden reference model
logic [31:0] dut_model_w[*];//for mimicing the writing into the dut reg
logic [31:0] dut_model_r[*];//for mimicing the reading from the dut reg
logic[31:0] ctrl_reg_value;// to know the ctrl register value
logic[127:0] Tx_reg_value,Rx_reg_value;
logic[6:0] char_len;
// for checking purpose
int k,l;
apb_seq_item apb_item,apb_item_2;
spi_seq_item spi_item,spi_item_2;
uvm_analysis_imp_apb_port#(apb_seq_item,spi_scoreboard)apb_imp;
uvm_analysis_imp_spi_port#(spi_seq_item,spi_scoreboard)spi_imp;
//queue to store data which will come from apb and spi side
apb_seq_item apb_dataQ[$];
spi_seq_item spi_dataQ[$];
logic[127:0] MOSIDATA,MISODATA;
extern function new(string name="spi_scoreboard",uvm_component parent =null);
extern function void build_phase(uvm_phase phase);
extern task run_phase( uvm_phase phase );
extern function void write_apb_port(apb_seq_item apb_item_1);
extern function void write_spi_port(spi_seq_item spi_item_1);
extern function void extract_phase( uvm_phase phase );
extern function void check_phase(uvm_phase phase);
extern function void report_phase( uvm_phase phase );
endclass:spi_scoreboard
function spi_scoreboard::new (string name="spi_scoreboard", uvm_component parent=null);
super.new(name, parent);
m_name=name;
endfunction : new
function void spi_scoreboard:: build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual irq_if)::get(this,"","irq_if",irq_if_1))
`uvm_fatal("NO IRQ IF",{"virtual interface of IRQ must be set for:",get_full_name(),".irq_if"});
spi_imp=new("spi_imp",this);
apb_imp=new("apb_imp",this);
endfunction:build_phase
function void spi_scoreboard:: write_apb_port(apb_seq_item apb_item_1);
$cast(apb_item,apb_item_1.clone());
`uvm_info(get_type_name(),$sformatf("writing in the apb write method \n %s",apb_item.sprint()), UVM_LOW)
apb_dataQ.push_back(apb_item);
endfunction
function void spi_scoreboard:: write_spi_port(spi_seq_item spi_item_1);
$cast(spi_item,spi_item_1.clone());
`uvm_info(get_type_name(),$sformatf("writing in spi write method \n %s",spi_item.sprint()),UVM_LOW)
spi_dataQ.push_back(spi_item);
endfunction
task spi_scoreboard:: run_phase( uvm_phase phase );
forever begin
foreach(apb_dataQ[i]) begin
apb_item_2=apb_dataQ.pop_front();
`uvm_info(m_name,$sformatf("Scoreboard \n %s",apb_item_2.sprint()),UVM_LOW)
if(apb_item_2.we) begin
dut_model_w[apb_item_2.addr]=apb_item_2.data;
// $display("dut_model_w=%p",dut_model_w);
end
else begin
dut_model_r[apb_item_2.addr]=apb_item_2.data;
//$display("dut_model_r=%p",dut_model_r);
end
end
Tx_reg_value={dut_model_w[32'h0c],dut_model_w[32'h08],dut_model_w[32'h04],dut_model_w[32'h00]};
Rx_reg_value={dut_model_r[32'h0c],dut_model_r[32'h08],dut_model_r[32'h04],dut_model_r[32'h00]};
ctrl_reg_value = dut_model_w[32'h10];
char_len=ctrl_reg_value[6:0];
wait(spi_dataQ.size())begin
spi_item_2= spi_dataQ.pop_front();
MOSIDATA=spi_item_2.MOSIDATA;
MISODATA=spi_item_2.MISODATA;
$display($time,"MOSIDATA[127:0]::%b\n MISODATA[127:0]::%b",MOSIDATA[127:0],MISODATA[127:0]);
end
end
endtask
function void spi_scoreboard:: extract_phase(uvm_phase phase);
super.extract_phase(phase);
foreach(apb_dataQ[i]) begin
apb_item_2=apb_dataQ.pop_front();
`uvm_info(m_name,$sformatf("Scoreboard \n %s",apb_item_2.sprint()),UVM_LOW)
if(apb_item_2.we) begin
dut_model_w[apb_item_2.addr]=apb_item_2.data;
// $display("dut_model_w=%p",dut_model_w);
end
else begin
dut_model_r[apb_item_2.addr]=apb_item_2.data;
//$display("dut_model_r=%p",dut_model_r);
end
end
Rx_reg_value={dut_model_r[32'h0c],dut_model_r[32'h08],dut_model_r[32'h04],dut_model_r[32'h00]};
endfunction
function void spi_scoreboard:: check_phase(uvm_phase phase);
super.check_phase(phase);
//compare logic
begin
for(int j=0;j<char_len;j++) begin
if(MOSIDATA[j]===Tx_reg_value[j])
k++;
else
break;
end
for(int m=0;m<char_len;m++) begin
if(MISODATA[m]===Rx_reg_value[m])
l++;
else
break;
end
end
apb_dataQ.delete();
spi_dataQ.delete();
endfunction
function void spi_scoreboard:: report_phase( uvm_phase phase );
//report
super.report_phase(phase);
`uvm_info(get_type_name(), "============================", UVM_NONE)
`uvm_info(get_type_name(), "Scoreboard Results", UVM_NONE)
if(char_len==k&&char_len==l)begin
`uvm_info(get_type_name(), "TEST PASSED", UVM_NONE)
`uvm_info(m_name,$sformatf("CONSIDERED CHARACTER LENGTH::%d",char_len),UVM_LOW)
`uvm_info(m_name,$sformatf("DATA SENT FROM APB MASTER IS MATCHED WITH DATA IN MOSI LINE::\n\n\n MOSI DATA SENT FROM APB MASTER::%b\n MOSI DATA COLLECTED FROM SPI MONITOR::%b\n\n",Tx_reg_value[127:0], MOSIDATA[127:0] ),UVM_LOW)
`uvm_info(m_name,$sformatf("DATA SENT FROM SPI SLAVE IS MATCHED WITH DATA IN MISO LINE::\n\n\n MISO DATA SENT FROM SPI SLAVE::%b\n MISO DATA COLLECTED FROM APB MONITOR::%b\n\n",MISODATA[127:0],Rx_reg_value[127:0]),UVM_LOW)
end
else begin
`uvm_info(get_type_name(), "TEST FAILED", UVM_NONE)
`uvm_info(get_type_name(), "============================", UVM_NONE)
end
endfunction