spi/i2s接口可以用于spi协议或者i2s音频协议与外部器件进行通信。spi主要特性:
`ifndef SPI_MST_TRANSACTION_SVH
`define SPI_MST_TRANSACTION_SVH
class spi_mst_transaction extends uvm_sequence_item;
randc bit [15:0] txdata;
bit [15:0] rxdata;
bit [15:0] tx_crc_data;
bit [15:0] rx_crc_data;
bit [15:0] tx_lsb_data;
`uvm_object_utils_begin(spi_mst_transaction)
`uvm_field_int(txdata, UVM_ALL_ON);
`uvm_field_int(rxdata, UVM_ALL_ON);
`uvm_object_utils_end
function new(string name = "spi_mst_transaction");
super.new(name);
endfunction
endclass
`endif //SPI_MST_TRANSACTION_SVH
`ifndef SPI_MST_SEQUENCER_SVH
`define SPI_MST_SEQUENCER_SVH
class spi_mst_sequencer extends uvm_sequencer#(spi_mst_transaction);
`uvm_component_utils(spi_mst_sequencer)
function new(string name = "spi_mst_sequencer", uvm_component parent = null);
super.new(name,parent);
endfunction
endclass
`endif //SPI_MST_SEQUENCER
`ifndef SPI_MST_DRIVER_SVH
`define SPI_MST_DRIVER_SVH
class spi_mst_driver extends uvm_driver#(spi_mst_transaction);
`uvm_component_utils(spi_mst_driver)
virtual spi_if sif;
spi_cfg cfg;
process processes[string];
int bit_num;
int i2s_bit_num;
int i2s_ws_num;
bit [15:0] tx_data_crc_temp = 16'h0;
bit [15:0] tx_data_crc = 16'h0;
int vip_mst_tx_data_cnt = 1;
int vip_mst_tx_sck_cnt = 1;
int vip_ti_mode_sta_sck_num;
function new(string name = "spi_mst_driver", uvm_component parent = null);
super.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_mst_driver","No specified for this spi configure!")
end
if(!uvm_config_db#(spi_cfg)::get(this,"","cfg",cfg)) begin
`uvm_fatal("spi_mst_driver","No specified for this spi configure!"
end
endfunction
virtual task reset_phase(uvm_phase phase);
super.reset_phase(phase);
sif.spi_sck_pin = (cfg.cpol | cfg.ckpol) ? 1'b1 : 1'b0;
sif.spi_nss_pin = (cfg.i2s_mod & cfg.i2sstd == 2'b0) ? 1'b1 : 1'b0;
endtask
virtual task configure_phase(uvm_phase phase);
super.configure_phase(phase);
if(cfg.crcen)
begin
if(cfg.dff & cfg.ds == 15)
bit_num = 16;
else if(~cfg.dff & cfg.ds == 7)
bit_num = 8;
end
else begin
case(cfg.ds)
4'h3: bit_num = 4;
4'h4: bit_num = 5;
4'h5: bit_num = 6;
4'h6: bit_num = 7;
4'h7: bit_num = 8;
4'h8: bit_num = 9;
4'h9: bit_num = 10;
4'ha: bit_num = 11;
4'hb: bit_num = 12;
4'hc: bit_num = 13;
4'hd: bit_num = 14;
4'he: bit_num = 15;
4'hf: bit_num = 16;
default: bit_num = 8;
endcase
end
i2s_bit_num = cfg.chlen ? 32 : 16;
i2s_ws_num = cfg.chlen ? 32 :16;
vip_ti_mode_sta_sck_num = cfg.cpol ? 4 : 2;
endtask
virtual task mian_phase(uvm_phase phase);
process proc_mst_driver;
super.main_phase(phase);
fork
begin
while(!sif.spi_rstn)
@(posedge sif.spi_clk);
forever begin
proc_mst_driver = process::self();
processes["proc_mst_driver"] = proc_mst_driver;
seq_item_port.get_next_item(req);
case(cfg.spi_work_mode)
5'b01000: vip_mst_full_duplex_mode_driver(req);
5'b01001: vip_mst_half_duplex_snd_mode_driver(req);
5'b01010: vip_mst_half_duplex_rcv_mode_driver(req);
5'b01011: vip_mst_simplex_snd_mode_driver(req);
5'b01100: vip_mst_simplex_rcv_mode_driver(req);
5'b01101: vip_i2s_mst_rx_driver(req);
5'b01110: vip_i2s_mst_tx_driver(req);
5'b11000: vip_ti_mst_full_duplex_mode_driver(req);
5'b11001: vip_ti_mst_half_duplex_snd_mode_driver(req);
5'b11010: vip_ti_mst_half_duplex_rcv_mode_driver(req);
5'b11011: vip_ti_mst_simpex_snd_mode_driver(req);
5'b11100: vip_ti_mst_simplex_rcv_mode_driver(req):
default: vip_mst_full_duplex_mode_driver(req);
endcase
seq_item_port.item_done();
end
end
begin
wait_reset();
end
join
endtask
extern virtual task vip_mst_full_duplex_mode_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_half_duplex_snd_mode_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_half_dumplex_rcv_mode_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_simplex_snd_mode_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_simplex_rcv_mode_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_simplex_snd_mode_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_send_data(spi_mst_transaction vip_mst_tr);
extern vitual task vip_mst_receive_data(spi_mst_transaction vip_mst_tr);
extern virtual task vip_mst_sck_gen(spi_mst_transaction vip_mst_tr);
extern virtual task vip_i2s_mst_rx_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_i2s_mst_tx_driver(spi_mst_transaction vip_mst_tr);
extern virtual task vip_i2s_mst_ck_gen(spi_mst_transaction vip_mst_tr);
extern virtual task vip_i2s_mst_ws_gen(spi_mst_transaction vip_mst_tr);
exterun vitual function void vip_spi_mst_crc_cal(spi_mst_transaction vip_mst_tr);
......
endclass
//task or function
......
......
`endif //SPI_MST_DRIVER_SVH
`ifndef SPI_MST_MONITOR_SVH
`define SPI_MST_MONITOR_SVH
class spi_mst_monitor extends uvm_monitor;
virtual spi_if sif;
spi_cfg cfg;
process precesses[string];
int bit_num;
int i2s_bit_num;
bit [15:0] rx_data_crc_tem;
bit [15:0] rx_data_crc;
int rx_crc_cnt = 1;
uvm_analysis_port #(spi_mst_transaction) mst_ap;
`uvm_component_utils(spi_mst_monitor)
function new(string name = "spi_mst_monitor", uvm_component parent = null);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
mst_ap = new("mst_apb",this);
if(!uvm_config_db#(spi_cfg)::get(this,"","cfg",cfg)) begin
`uvm_fatal("spi_mst_monitor","No Specified for spi_config")
end
if(!uvm_config_db#(virtual spi_if)::get(this,"","sif",sif)) begin
`uvm_fatal("spi_mst_monitor","No Interface specified for this driver")
end
endfunction
......
extern task run_phase(uvm_phase phase);
extern task spi_collect_data(spi_mst_transaction mst_tr);
extern task spi_ti_collect_data(spi_mst_transaction mst_tr);
extern task spi_i2s_collect_data(spi_mst_transaction mst_tr);
extern function void vip_spi_mst_crc_cal(spi_transaction mst_tr);
extern task wait_reset();
endclass
//task or function
......
`endif //SPI_MST_MONITOR_SVH
`ifndef SPI_MST_AGENT_SVH
`define SPI_MST_AGENT_SVH
class spi_mst_agent extend uvm_agent;
`uvm_component_utils(spi_mst_agent)
spi_mst_sequencer mst_sqr;
spi_mst_driver mst_drv;
spi_mst_monitor mst_mon;
uvm_analysis_port #(spi_mst_transaction) mst_ap;
function new(string name = "spi_mst_agent", uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
mst_sqr = spi_mst_sequencer::type_id::create("mst_sqr",this);
mst_drv = spi_mst_driver::type_id::create("mst_drv",this);
mst_mon = spi_mst_monitor::type_id::create("mst_mon",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
mst_drv.seq_item_port.connect(mst_sqr.seq_item_export);
mst_ap = mst_mon.mst_ap;
endfunction
endclass
`endif //SPI_MST_AGENT_SVH
…
…