SPI_Test/case1/spi_driver.sv

402 lines
13 KiB
Systemverilog

//2024-06-24 linear search for all addr
class spi_driver;
static bit my_cmd=1'b0;
static bit[24:0] last_addr=25'h190_0000;
static int last_size;
static bit[24:0] addr_list[$];
//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;
int half_sclk;
bit autarchy;
rand int error_time;
constraint cstr{
error_time <= 544;
error_time >= -544;
}
covergroup SYSAddr;
coverpoint m_trans.addr{
bins IDR = {[25'h00:25'h03]};
bins VIDR = {[25'h04:25'h07]};
bins DATER = {[25'h08:25'h0B]};
bins VERR = {[25'h0C:25'h0F]};
bins TESTR = {[25'h10:25'h13]};
bins IMR = {[25'h14:25'h17]};
bins ISR = {[25'h18:25'h1B]};
bins SFRTR = {[25'h1C:25'h1F]};
bins SFRR = {[25'h20:25'h23]};
bins CH0RSTR = {[25'h24:25'h27]};
bins CH1RSTR = {[25'h28:25'h2B]};
bins CH2RSTR = {[25'h2C:25'h2F]};
bins CH3RSTR = {[25'h30:25'h33]};
bins DBGCFGR = {[25'h34:25'h37]};
bins MISR = {[25'h40:25'h43]};
}
option.per_instance = 1;
endgroup
covergroup INSTRAddr;
coverpoint m_trans.addr{
bins INSTRCTION[8192] = {[25'h010_0000:25'h010_7FFF]};
}
option.per_instance = 1;
endgroup
covergroup DATAAddr;
coverpoint m_trans.addr{
bins DATA[8192] = {[25'h020_0000:25'h020_7FFF]};
}
option.per_instance = 1;
endgroup
covergroup CTRAddr;
coverpoint m_trans.addr{
bins MCUPARAR0 = {[25'h30_0000:25'h30_0003]};
bins MCUPARAR1 = {[25'h30_0004:25'h30_0007]};
bins MCUPARAR2 = {[25'h30_0008:25'h30_000B]};
bins MCUPARAR3 = {[25'h30_000C:25'h30_000F]};
bins MCURESR0 = {[25'h30_0010:25'h30_0013]};
bins MCURESR1 = {[25'h30_0014:25'h30_0017]};
bins MCURESR2 = {[25'h30_0018:25'h30_001B]};
bins MCURESR3 = {[25'h30_001C:25'h30_001F]};
bins RTIMR = {[25'h30_0098:25'h30_009B]};
bins ICNTR = {[25'h30_009C:25'h30_009F]};
bins FSIR = {[25'h30_00A0:25'h30_00A3]};
bins MODMR = {[25'h30_0100:25'h30_0103]};
bins INTPMR = {[25'h30_0104:25'h30_0107]};
bins MIXNCOCR = {[25'h30_0108:25'h30_010B]};
bins MIXNFCWHR = {[25'h30_010C:25'h30_010F]};
bins MIXNFCWLR = {[25'h30_0110:25'h30_0113]};
bins MIXNPHAR = {[25'h30_0114:25'h30_0117]};
bins MIXMR = {[25'h30_0118:25'h30_011B]};
bins MIXODTR = {[25'h30_011C:25'h30_011F]};
bins MIXODFR = {[25'h30_0120:25'h30_0123]};
bins ROLER = {[25'h30_0128:25'h30_012B]};
bins MIXNCOSCER = {[25'h30_012C:25'h30_012F]};
bins MODDOTR = {[25'h30_0130:25'h30_0133]};
bins STR = {[25'h30_0134:25'h30_0137]};
}
option.per_instance = 1;
endgroup
covergroup ENVELOPEIDAddr;
coverpoint m_trans.addr{
bins ENVELOPEID[64] = {[25'h040_0000:25'h040_00FF]};
}
option.per_instance = 1;
endgroup
covergroup ENVELOPEDATAAddr;
coverpoint m_trans.addr{
bins ENVELOPEDATA[8192] = {[25'h050_0000:25'h050_7FFF]};
}
option.per_instance = 1;
endgroup
covergroup DACAddr;
coverpoint m_trans.addr{
bins PRBSCR = {[25'h060_0000:25'h060_0003]};
bins SET0CR = {[25'h060_0004:25'h060_0007]};
bins SET1CR = {[25'h060_0008:25'h060_000B]};
bins SET2CR = {[25'h060_000C:25'h060_000F]};
bins SET3CR = {[25'h060_0010:25'h060_0013]};
bins SET4CR = {[25'h060_0014:25'h060_0017]};
bins SET5CR = {[25'h060_0018:25'h060_001B]};
bins SET6CR = {[25'h060_001C:25'h060_001F]};
bins SET7CR = {[25'h060_0020:25'h060_0023]};
bins SET8CR = {[25'h060_0024:25'h060_0027]};
bins SET9CR = {[25'h060_0028:25'h060_002B]};
bins SET10CR = {[25'h060_002C:25'h060_002F]};
bins SET11CR = {[25'h060_0030:25'h060_0033]};
bins SET12CR = {[25'h060_0034:25'h060_0037]};
bins SET13CR = {[25'h060_0038:25'h060_003B]};
bins SET14CR = {[25'h060_003C:25'h060_003F]};
bins SET15CR = {[25'h060_0040:25'h060_0043]};
bins DACADDR = {[25'h060_0044:25'h060_0047]};
bins DACDW = {[25'h060_0048:25'h060_004B]};
bins DACREF = {[25'h060_004C:25'h060_004F]};
bins PRBSRST0 = {[25'h060_0050:25'h060_0053]};
bins PRBSSET0 = {[25'h060_0054:25'h060_0057]};
bins PRBSRST1 = {[25'h060_0058:25'h060_005B]};
bins PRBSSET1 = {[25'h060_005C:25'h060_005F]};
bins PRBSREV = {[25'h060_0060:25'h060_0063]};
bins CALSIG = {[25'h060_0064:25'h060_0067]};
bins CALEND = {[25'h060_0068:25'h060_006B]};
bins CALRSTN = {[25'h060_006C:25'h060_006F]};
bins CALDIVRSTN = {[25'h060_0070:25'h060_0073]};
}
option.per_instance = 1;
endgroup
covergroup MCUAddr;
coverpoint m_trans.addr{
bins MCUPARAR0 = {[25'h70_0000:25'h70_0003]};
bins MCUPARAR1 = {[25'h70_0004:25'h70_0007]};
bins MCUPARAR2 = {[25'h70_0008:25'h70_000B]};
bins MCUPARAR3 = {[25'h70_000C:25'h70_000F]};
bins MCURESR0 = {[25'h70_0010:25'h70_0013]};
bins MCURESR1 = {[25'h70_0014:25'h70_0017]};
bins MCURESR2 = {[25'h70_0018:25'h70_001B]};
bins MCURESR3 = {[25'h70_001C:25'h70_001F]};
bins CWFR0 = {[25'h70_0040:25'h70_0043]};
bins CWFR1 = {[25'h70_0044:25'h70_0047]};
bins CWFR2 = {[25'h70_0048:25'h70_004B]};
bins CWFR3 = {[25'h70_004C:25'h70_004F]};
bins CWPRR = {[25'h70_0050:25'h70_0053]};
bins GAPR0 = {[25'h70_0054:25'h70_0057]};
bins GAPR1 = {[25'h70_0058:25'h70_005B]};
bins GAPR2 = {[25'h70_005C:25'h70_005F]};
bins GAPR3 = {[25'h70_0060:25'h70_0063]};
bins GAPR4 = {[25'h70_0064:25'h70_0067]};
bins GAPR5 = {[25'h70_0068:25'h70_006B]};
bins GAPR6 = {[25'h70_006C:25'h70_006F]};
bins GAPR7 = {[25'h70_0070:25'h70_0073]};
bins LCPR = {[25'h70_0074:25'h70_0077]};
bins AMPR0 = {[25'h70_0078:25'h70_007B]};
bins AMPR1 = {[25'h70_007C:25'h70_007F]};
bins AMPR2 = {[25'h70_0080:25'h70_0083]};
bins AMPR3 = {[25'h70_0084:25'h70_0087]};
bins BIASR0 = {[25'h70_0088:25'h70_008B]};
bins BIASR1 = {[25'h70_008C:25'h70_008F]};
bins BIASR2 = {[25'h70_0090:25'h70_0093]};
bins BIASR3 = {[25'h70_0094:25'h70_0097]};
bins RTIMR = {[25'h70_0098:25'h70_009B]};
bins ICNTR = {[25'h70_009C:25'h70_009F]};
bins FSIR = {[25'h70_00A0:25'h70_00A3]};
bins INTPSELR = {[25'h70_00A4:25'h70_00A7]};
}
option.per_instance = 1;
endgroup
covergroup DBGAddr;
coverpoint m_trans.addr{
bins DBGAddr[1024] = {[25'h190_0000:25'h190_0FFF]};
}
option.per_instance = 1;
endgroup
covergroup PLLAddr;
coverpoint m_trans.addr{
bins INTPLL_REFCTRL = {[25'h1f0_0000:25'h1f0_0003]};
bins INTPLL_PCNT = {[25'h1f0_0004:25'h1f0_0007]};
bins INTPLL_PFDCTRL = {[25'h1f0_0008:25'h1f0_000B]};
bins INTPLL_SPDCTRL = {[25'h1f0_000C:25'h1f0_000F]};
bins INTPLL_PTATCTRL = {[25'h1f0_0010:25'h1f0_0013]};
bins INTPLL_FLLCTRL = {[25'h1f0_0014:25'h1f0_0017]};
bins INTPLL_SELCTRL = {[25'h1f0_0018:25'h1f0_001B]};
bins INTPLL_VCOCTRL = {[25'h1f0_001C:25'h1f0_001F]};
bins INTPLL_VCOFBADJ = {[25'h1f0_0020:25'h1f0_0023]};
bins INTPLL_AFCCTRL = {[25'h1f0_0024:25'h1f0_0027]};
bins INTPLL_AFCCNT = {[25'h1f0_0028:25'h1f0_002B]};
bins INTPLL_AFCLDCNT = {[25'h1f0_002C:25'h1f0_002F]};
bins INTPLL_AFCPRES = {[25'h1f0_0030:25'h1f0_0033]};
bins INTPLL_AFCLDTCC = {[25'h1f0_0034:25'h1f0_0037]};
bins INTPLL_AFCFBTCC = {[25'h1f0_0038:25'h1f0_003B]};
bins INTPLL_DIVCFG = {[25'h1f0_003C:25'h1f0_003F]};
bins INTPLL_TCLKCFG = {[25'h1f0_0040:25'h1f0_0043]};
bins INTPLL_DCLKSEL = {[25'h1f0_0044:25'h1f0_0047]};
bins INTPLL_STATUS = {[25'h1f0_0048:25'h1f0_004B]};
bins INTPLL_SYNCFG = {[25'h1f0_004C:25'h1f0_004F]};
bins INTPLL_UPDATE = {[25'h1f0_0050:25'h1f0_0053]};
bins INTPLL_CLKRXPD = {[25'h1f0_0054:25'h1f0_0057]};
}
option.per_instance = 1;
endgroup
function new();
SYSAddr = new();
INSTRAddr = new();
DATAAddr = new();
CTRAddr = new();
ENVELOPEIDAddr = new();
ENVELOPEDATAAddr = new();
DACAddr = new();
MCUAddr = new();
DBGAddr = new();
PLLAddr = new();
endfunction
extern task do_drive();
extern task make_pkt(spi_trans tr);
endclass : spi_driver
task spi_driver::do_drive();
int i=0,j=0;
for(i=0;i<14;i++)
addr_list[i]=4*i;
addr_list[14] = 25'h000_0040;
addr_list.delete(8);
addr_list.delete(8);
// $display(addr_list);
pktnum=addr_list.size()*2;
$display("pkt_num:\t%0d",pktnum);
while(!vif.rstn) begin
vif.csn = 1'b1;
vif.sclk = 1'b1;
@(posedge vif.clk);
end
for(j=0;j<pktnum;j++) begin
m_trans = new();
if(!m_trans.randomize() with {
cmd==my_cmd;
(cmd==1'b0 || data.size()==last_size);
//(cmd==1'b0 || addr==last_addr);
addr == addr_list[j/2];
// addr[24:20] == 5'h0 || //sys
// addr[24:20] == 5'h1 || //instruction srams
// addr[24:20] == 5'h2 || //data srams
// addr[24:20] == 5'h3 || //awg
// addr[24:20] == 5'h4 || //envelope id srams
// addr[24:20] == 5'h5 || //envelope data srams
// addr[24:20] == 5'h6 || //dac
// addr[24:20] == 5'h7 || //mcu
// addr[24:20] == 5'h19 || //dbg srams
// addr[24:20] == 5'h1F ; //pll
addr[24: 20] == 5'h0;
addr[1:0] == 0;
// data.size == 2;
interval == 50;
})
$fatal(0,"Randomize Failed");
if(m_trans.cmd == 1'b0) begin
last_addr = m_trans.addr;
last_size = m_trans.data.size();
end
my_cmd = ~my_cmd;
//Autarchy: Testcase force to assign some params
interval = m_trans.interval;
if(!autarchy) begin
half_sclk = m_trans.half_sclk;
end
if((m_trans.addr <= 25'h000_001F) &&
((m_trans.addr + (m_trans.data.size()-1) * 4) >= 25'h000_001C))
m_trans.data[(25'h000_001C - m_trans.addr)/4] =
m_trans.data[(25'h000_001C - m_trans.addr)/4] % 4 + 1;
make_pkt(m_trans);
//$display(m_trans.addr);
SYSAddr.sample();
INSTRAddr.sample();
DATAAddr.sample();
CTRAddr.sample();
ENVELOPEIDAddr.sample();
ENVELOPEDATAAddr.sample();
DACAddr.sample();
MCUAddr.sample();
DBGAddr.sample();
PLLAddr.sample();
repeat(interval)
@(posedge vif.clk);
//pktnum--;
end
$finish(0);
//$display(SYSAddr.get_inst_coverage());
//$display(MCUAddr.get_inst_coverage());
//$display(AWGAddr.get_inst_coverage());
endtask : do_drive
task spi_driver::make_pkt(spi_trans tr);
int i=0,j=0;
int cs_time,mo_time;
//*****************initialize chip_select and input_clk******************//
vif.csn <= 1'b1;
vif.sclk <= 1'b1;
vif.mosi <= stream[0];
vif.cfgid <= tr.cfgid;
@(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()+1)*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("id:\t\t%h\t\t\t\t\t\t **",tr.cfgid);
//$display("addr:\t\t%h\t\t\t\t\t\t **",tr.addr);
//$display(stream);
//if(!tr.cmd)
//for(i=0;i<tr.data.size;i++)
//$display("mosi:\t\t%h\t\t **",tr.data[i]);
//********************drive the stream onto interface********************//
fork
//************************Make sclk************************//
begin
for(j=0;j<cs_time;j++) begin
if(j % half_sclk == 0 && j!=0)
vif.sclk <= ~vif.sclk;
@(posedge vif.clk);
end
vif.sclk = 1'b1;
@(posedge vif.clk);
vif.csn = 1'b1;
end
//************************Send data************************//
begin
for(i=0;i<mo_time;i++) begin
// data will be sampled at posedge,
// so prepare them at the negedge before each posedge
if(i % (2*half_sclk) == half_sclk)begin
vif.mosi <= stream[(i/half_sclk-1)/2];
//$display(i);
end
@(posedge vif.clk);
end
end
join
//$display("**********************************************************************");
endtask