当前位置: 首页 > 工具软件 > MST > 使用案例 >

UVM验证平台搭建三:spi_mst_agent-spi_slv_agent

栾和风
2023-12-01


一、概述

spi/i2s接口可以用于spi协议或者i2s音频协议与外部器件进行通信。spi主要特性:

  • 主模式或从模式操作
  • 基于三条线的全双工同步传输
  • 基于双线的半双工同步传输,其中一条可作为双向数据线
  • 基于双线的单工同步模式,其中一条可作为单向数据线
  • 8位/16位传输帧格式选择

二、spi mst transaction

`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

三、spi mst sequencer

`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

四、spi mst driver

`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

五、spi mst monitor

`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

六、spi mst agent

`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


 类似资料: