一、spi_cfg
`ifndef SPI_CFG_SVH
`define SPI_CFG_SVH
package spi_cfg_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
class spi_cfg extends uvm_object;
`uvm_object_utils(spi_cfg)
//spi cr1
bit cpha;
bit cpol;
bit mstr;
bit [2:0] br;
bit spe;
bit lsbfirst;
bit ssi;
bit ssm;
bit rxonly;
bit dff;
bit crcnext;
bit crcen;
bit bidioe;
bit bidimode;
.......
function new(string name = "spi_cfg");
super.new(name);
endfunction
endclass: spi_cfg
endpackage: spi_cfg_pkg
`endif //SPI_CFG_SVH
二、spi interface
interface spi_if(input spi_clk, input spi_rstn);
logic spi_miso_pin;
logic spi_miso_pout;
logic spi_mosi_pin;
logic spi_mosi_pout;
logic spi_nss_pin;
logic spi_nss_pout;
logic spi_sck_pin;
logic spi_sck_pout;
logic spi_nss_poe;
logic spi_sck_poe;
logic spi_mosi_poe;
logic spi_miso_poe;
endinterface
三、spi scoreboard
`ifnef SPI_SCOREBOARD_SVH
`define SPI_SCOREBOARD_SVH
`include "spi_work_mode_define.sv"
class spi_scoreboard extends uvm_scoreboard;
`uvm_component_utils(spi_scoreboard)
process processes[string];
spi_cfg cfg;
virtual spi_if sif;
uvm_blocking_get_port #(apb_trans) apb_tdr_port;
uvm_blocking_get_port #(apb_trans) apb_rdr_port;
uvm_blocking_get_port #(spi_slv_transaction) vip_slv_port;
uvm_blocking_get_port #(spi_slv_transaction) vip_mst_port;
apb_trans apb_tdr_queue[$], apb_rdr_queue[$];
spi_slv_transaction vip_slv_queue[$];
spi_mst_transaction vip_mst_queue[$];
function new(string name = "spi_scoreboard", uvm_compoent parent);
supre.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual spi_if)::get(this,"","sif",sif)) begin
`uvm_fatal("spi_scoreboard","No Interface specified for this scoreboard!")
end
if(!uvm_config_db#(spi_cfg)::get(this,"","sif",sif)) begin
`uvm_fatal("spi_scoreboard","No specified for this spi_sys_cofig!")
end
apb_tdr_port = new("apb_tdr_port",this);
apb_rdr_port = new("apb_rdr_port",this);
vip_slv_port = new("vip_slv_port",this);
vip_mst_port = new("vip_mst_port",this);
endfunction
extern virtual task run_phase(uvm_phase phase);
extern virtual function void compare_fun(input [15:0] tdr_data,input [15:0] rdr_data, input [15:0] vip_txdata, input [15:0] vip_rxdata, output dut_compare_tx, output dut_compare_rx, input [3:0] pstrb);
extern virtual function void compare_fun_rcv_only(input [15:0] tdr_data,input [15:0] rdr_data, input [15:0] vip_txdata, input [15:0] vip_rxdata, output dut_compare_tx, output dut_compare_rx);
extern virtual task dut_rdr_save(apb_trans get_rdr, ref int rdr_cnt_num);
extern virtual task dut_tdr_save(apb_trans get_tdr, ref int tdr_cnt_num);
extern virtual task get_dut_tdr(ref apb_trans tdr_tr);
extern virtual task get_dut_rdr(ref apb_trans rdr_tr);
extern virtual task dut_rdr_save_rcv_only(apb_trans get_rdr, ref int rdr_cnt_num);
extern virtual task get_vip_slv_data(ref spi_slv_transaction vip_slv);
extern virtual task get_vip_mst_data(ref spi_mst_transaction vip_mst);
extern virtual wait_reset();
endclass: spi_scoreboard
//function or task
......
`endif SPI_SCOREBOARD_SVH
四、spi_monitor
`ifndef SPI_MONITOR_SVH
`define SPI_MONITOR_SVH
class spi_monitor extends uvm_monitor;
`uvm_component_utils(spi_monitor)
virtual apb_if bif;
process processes[string];
uvm_analysis_port #(apb_trans) ap;
function new(string name = "spi_monitor", uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual apb_if)::get(this,"","bif",bif)) begin
`uvm_fatal("spi_monitor","No Interface speceifed for spi monitor")
end
ap = new("ap",this);
endfunction
extern task run_phase(uvm_phase phase);
extern task collect_data(apb_trans apb_tr);
extern virtual task wait_reset();
endclass
task spi_monitor::run_phase(uvm_phase phase);
apb_trans apb_tr;
process proc_monitor;
fork
begin
while(1) begin
proc_monitor = process::self();
processes["proc_monitor"] = proc_monitor;
apb_tr = new("apb_tr");
collect_data(apb_tr);
ap.write(apb_tr);
end
end
begin
wait_reset();
end
join
endtask:run_phase
task spi_monitor::collect_data(apb_trans apb_tr);
......
......
endtask:collec_data
task spi_monitor::wait_reset();
forever begin
@(negedge bif.presetn);
foreach(precesses[i])
processes[i].kill();
@(posedge bif.presetn);
end
endtask:wait_reset
`endif //SPI_MONITOR_SVH
五、spi coverage
`ifndef SPI_COVERAGE_SVH
`define SPI_COVERAGE_SVH
class spi_coverage extends uvm_subscriber #(apb_trans);
`uvm_component_utils(spi_coverage)
apb_trans apb_tr;
ral_block_reg_model rm;
covergroup spi_reg_cv;
option.per_instance = 0;
endgroup
function new(string name = "spi_coverage", uvm_component parent = null);
super.new(name,parent);
spi_reg_cv = new();
endfunction
function void write(T t);
spi_reg_cv.sample();
endfunction
endclass
`endif //SPI_COVERAGE_SVH
六、spi env
class spi_env extends uvm_env;
virtual spi_if sif;
virtual apb_if bif;
apb_agent apb_agt;
spi_slv_agent slv_agt;
spi_mst_agent mst_agt;
spi_scoreboard spi_scb;
spi_monitor spi_mon;
ral_block_reg_model p_rm;
uvm_tlm_analysis_fifo #(apb_trans) apb_tdr_scb_fifo;
uvm_tlm_analysis_fifo #(apb_trans) apb_rdr_scb_fifo;
uvm_tlm_analysis_fifo #(spi_mst_transaction) vip_mst_scb_fifo;
uvm_tlm_analysis_fifo #(spi_slv_transaction) vip_slv_scb_fifo;
function new(string name = "spi_env", uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
p_rm = ral_block_reg_block::type_id::create("p_rm",this);
apb_agt = apb_agent::type_id::create("apb_agt",this);
apb_agt.is_active = UVM_ACTIVE;
slv_agt = spi_slv_agent::type_id::create("slv_agt",this);
slv_agt.is_active = UVM_ACTIVE;
mst_agt = spi_mst_agent::type_id::create("mst_agt",this);
mst_agt.is_active = UVM_ACTIVE;
spi_scb = spi_scoreboard::type_id::create("spi_scb",this);
spi_cvr = spi_coverage::type_id::create("spi_cvr",this);
spi_mon = spi_monitor::type_id::create("spi_mon",this);
apb_tdr_scb_fifo = new("apb_tdr_scb_fifo",this);
apb_rdr_scb_fifo = new("apb_rdr_scb_fifo",this);
vip_mst_scb_fifo = new("vip_mst_scb_fifo",this);
vip_slv_scb_fifo = new("vip_slv_scb_fifo",this);
if(!uvm_config_db#(virtual spi_if)::get(this,"","sif",sif)) begin
`uvm_fatal("spi_env","No Interface specified for this spi!")
end
if(!uvm_config_db#(virtual apb_if)::get(this,"","bif",bif)) begin
`uvm_fatal("spi_env","No Interface specified for this spi!")
end
endfunction
extern virtual function void connect_phase(uvm_phase phase);
`uvm_component_utils(spi_env)
endclass
//connect_phase
function void spi_env::connect_phase(uvm_phase phase);
super.connect_phase(phase);
//apb_tx_monitor and spi scb connect
apb_agt.tdr_ap.connect(apb_tdr_scb_fifo.analysis_export);
spi_scb.apb_tdr_port.connect(apb_tdr_scb_fifo.blocking_get_export);
//apb_rx_monitor and spi_scb connect
apb_agt.rdr_ap.connect(apb_rdr_fifo.analysis_export);
spi_scb.apb_rdr_port.connec(apb_rdr_fifo.blocking_export);
//spi_mst_agt and spi_scb connect
mst_agt.mst_ap.connect(vip_mst_scb_fifo.analysis_export);
spi_scb.vip_mst_port.connect(vip_mst_scb_fifo.blocking_get_export);
//spi_slv_agt and spi_scb connect
slv_agt.slv_ap.connect(vip_slv_scb_fifo.analysis_export);
spi_scb.vip_slv_port.connect(vip_slv_scb_fifo.blocking_export);
endfunction: connect_phase
七、spi vsqr
`ifndef SPI_VSQR_SVH
`define SPI_VSQR_SVH
class spi_vsqr extends uvm_sequencer;
virtual spi_if p_sif;
virtual apb_if p_bif;
apb_sequencer p_apb_sqr;
ral_block_reg_model p_rm;
spi_slv_sequencer p_slv_sqr;
spi_mst_sequencer p_mst_sqr;
spi_cfg cfg;
function new(string name = "spi_vsqr", uvm_component parent);
supre.new(name,parent);
endfunction
`uvm_component_utils(spi_vsqr)
endclass: spi_vsqr
`endif //SPI_VSQR_SVH
八、spi base test
`ifndef SPI_BASE_TEST
`define SPI_BASE_TEST
class spi_base_test extends uvm_test;
virtual spi_if sif;
virtual apb_if bif;
spi_env env;
spi_vsqr v_sqr;
ral_block_reg_model rm;
apb_adgpter reg_sqr_adapter;
spi_cfg cfg;
spi_scoreboard scb;
function new(string name = "spi_base_test", uvm_component parent);
super.new(name,parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
extern virtual function void connect_phase(uvm_phase phase);
extern virtual function void report_phase(uvm_phase phase);
extern virtual function void final_phase(uvm_phase phase);
extern virtual task wait_scb_done();
`uvm_component_utils(spi_base_test)
endclass: spi_base_test
function void spi_base_test::build_phase(uvm_phase phase);
super.build_phase(phase);
env = spi_env::type_id::create("env",this);
cfg = spi_cfg::type_id::create("cfg",this);
v_sqr = spi_vsqr::type_id::create("v_sqr",this);
rm = ral_block_reg_model:type_id::create("rm", this);
rm.configure(null, "");
rm.build();
rm.lock_model();
rm.reset();
rm.set_hdl_path_root("top_tb.spi_dut");
reg_sqr_adapter = new("reg_sqr_adapter");
endfunction
function void spi_base_test::connect_phase(uvm_phase phase);
super.connect_phase(phase);
v_sqr.p_apb_sqr = env.apb_agt.sqr;
v_sqr.p_slv_sqr = env.slv_agt.slv_sqr;
v_sqr.p_mst_sqr = env.mst_agt.mst_sqr;
v_sqr.cfg = this.cfg;
v_sqr.p_sif = env.sif;
v_sqr.p_bif = env.bif;
env.p_rm = this.rm;
env.spi_cvr.rm = this.rm;
scb = env.spi_scb;
rm.default_map.set_sequencer(env.apb_agt.sqr, reg_sqr_adapter);
rm.default_map.set_auto_predict(1);
endfunction
funciton void spi_base_test::report_phase(uvm_phase phase);
uvm_report_server server;
int err_num;
super.report_phase(phase);
server = get_report_server();
err_num = server.get_severity_count(UVM_ERROR);
if(err_num != 0) begin
$display("TEST CASE FAILED");
end
else begin
$display("TEST CASE PASSED");
end
endfunction
function void spi_base_test::final_phase(uvm_phase phase);
super.final_phase(phase);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
//uvm_top.print_topology();
//factory.print();
endfunction
task spi_base_test::wait_scb_done();
wait(scb.apb_tdr_queue.size() == 0);
wait(scb.apb_rdr_queue.size() == 0);
wait(scb.vip_slv_queue.size() == 0);
wait(scb.vip_mst_queue.size() == 0);
endtask: wait_scb_done
`endif //SPI_BASE_TEST