class spi_driver; static bit my_cmd=1'b0; static bit[24:0] last_addr; static bit last_s; //MOSI data pkt, other input_signals are not packed spi_trans m_trans; //interface virtual spi_if vif; //MOSI data_stream input to SPI(DUT) bit stream[$]; //parameter for randomization int pktnum; int interval; rand int error_time; int half_sclk; bit autarchy; constraint cstr{ error_time <= 544; error_time >= -544; } function new(); endfunction extern task do_drive(); extern task make_pkt(spi_trans tr); endclass : spi_driver task spi_driver::do_drive(); $display("pkt_num:\t%0d",pktnum); while(!vif.rstn) begin vif.csn = 1'b1; vif.sclk = 1'b1; @(posedge vif.clk); end while(pktnum>0) begin //$display(my_cmd); make_pkt(m_trans); repeat(interval) @(posedge vif.clk); pktnum--; end endtask : do_drive task spi_driver::make_pkt(spi_trans tr); int i=0,j=0; int cs_time,mo_time; //**********************Create and Randomize a pkt**********************// tr = new(); if(!tr.randomize() with { cmd==my_cmd; (cmd==1'b0 || s==last_s); (cmd==1'b0 || addr==last_addr); addr[24:20] == 5'b00000 || addr[24:20] == 5'b00001 || addr[24:20] == 5'b00010; }) $fatal(0,"Randomize Failed"); if(tr.cmd == 1'b0) begin last_addr = tr.addr; last_s = tr.s; end my_cmd = ~my_cmd; //Autarchy: Testcase force to assign some params interval = tr.interval; if(!autarchy) begin half_sclk = tr.half_sclk; end //*****************initialize chip_select and input_clk******************// vif.csn <= 1'b1; vif.sclk <= 1'b1; vif.mosi <= stream[0]; @(posedge vif.clk); vif.csn <= 1'b0; vif.sclk <= 1'b1; //unpack into bitstream stream.delete(); tr.unpack(stream); //mosi valid time: time for bitstream to be all sent //csn valid_time: maybe a delay after or ahead of mosi_finished mo_time = (stream.size())*2*half_sclk; cs_time = (pktnum==1) ? (mo_time + error_time%mo_time) : mo_time; $display("***************************ONE PKT DRIVERED***************************"); $display("half_sclk:\t%0d\t\t\t\t\t\t **",half_sclk); $display("interval:\t%0d\t\t\t\t\t\t **",interval); //$display("error_time:\t%0d\t\t\t\t\t\t **",error_time); //$display("data_size:\t%0d\t\t\t\t\t\t **",tr.data.size()); //$display("cmd:\t\t%0d\t\t\t\t\t\t **",tr.cmd); //$display(stream); if(!tr.cmd) for(i=0;i