class spi2sysreg_refmodel; virtual sysreg_if vif; virtual spi_if wif; virtual sram_if xif; static int pktnum; //Vars as reg_model bit[31:0] imr=32'b0; bit[31:0] isr=32'b0; bit[31:0] intr=32'b0; bit[31:0] rst_time=32'd300; //Vars in rst-check int rst_error[4]={32'b0,32'b0,32'b0,32'b0}; function new(); endfunction extern task do_imitate(); extern task reg_updata(bit cmd,int size,bit[1:0] chip,bit[15:0] addr,bit[32:0] din_temp); extern task intr_collect(bit[15:0] addr); extern task rst_check(bit[31:0] rst_time,int i,int pkt_i); endclass : spi2sysreg_refmodel task spi2sysreg_refmodel::do_imitate(); //Vars in Progress_kill int pkt_i=0; //Temp Vars bit[31:0] cmd_temp; bit[31:0] din_temp; bit[1 :0] chip; bit[15:0] addr=16'b0; int size; bit cmd=0; int i=0,j=0; fork while(1) begin: spi_refmodel if(pkt_i==pktnum) break; @(negedge wif.csn); for(j=0;j<27;j++) begin @(posedge wif.sclk or posedge wif.csn) if(wif.error_check | wif.csn) break; cmd_temp[j] = wif.mosi; end cmd = cmd_temp[0]; size = cmd_temp[1] ? 16 : 1; chip = {<<{cmd_temp[6 :5 ]}}; addr = {<<{cmd_temp[26:11]}}; //$display("addr:%0h",addr); //$display("cmd:%0h",cmd); repeat(5) @(posedge wif.sclk); for(j=0;j<32;j++) begin @(posedge wif.sclk or posedge wif.csn) if(wif.error_check | wif.csn) break; din_temp[31-j] = wif.mosi; end @(posedge wif.csn); end: spi_refmodel while(1) begin: sysreg_refmodel if(pkt_i==pktnum) break; if(wif.csn) @(negedge wif.csn); //Not 32,"rden" occurs before the 32nd posedge sclk repeat(31) @(posedge wif.sclk); //if write,wait for din_temp update if(!cmd) @(posedge wif.csn); reg_updata(cmd,size,chip,addr,din_temp); end: sysreg_refmodel while(1) begin: intr_regmodel if(pkt_i==pktnum) break; intr_collect(addr); end: intr_regmodel begin: rst_checker for(i=0;i<4;i++) begin automatic int rst_i = i; fork while(1) begin if(pkt_i==pktnum) break; @(negedge wif.csn); //$display("check_rst%0d",rst_i); repeat(32) @(posedge wif.sclk); if(!cmd & addr[15: 2]==14'h09+rst_i & chip==2'b00) rst_check(rst_time,rst_i,pkt_i); end join_none end wait fork; end: rst_checker repeat(pktnum) begin: kill_progress @(negedge wif.csn); pkt_i++; end: kill_progress join endtask: do_imitate task spi2sysreg_refmodel::reg_updata( bit cmd, int size, bit[1:0] chip, bit[15:0] addr, bit[32:0] din_temp ); int i=0,j=0; if(cmd) begin @(posedge xif.rden); isr = intr; $display("intr:%0h",intr); @(posedge wif.csn); end else begin @(posedge xif.wren); repeat(2) @(posedge wif.clk); @(negedge wif.clk); case(addr[15: 2]) 14'h05: imr = (chip==2'b00) ? din_temp : imr; 14'h08: rst_time = (chip==2'b00) ? din_temp : rst_time; endcase //$display("addr:%0h",addr); $display("imr:%0h",imr); //$display("rst_time:%0h",rst_time); end endtask: reg_updata task spi2sysreg_refmodel::intr_collect(bit[15:0] addr); @(negedge wif.clk); //each MISR read should clr INTR once if(addr[15: 2] == 14'h07 && xif.rden) intr = 32'b0; //No else: whether clr INTR or not,we need to check the follow interrupt status begin intr[31] = vif.pll_lock | intr[31]; intr[30] = vif.pll_lost_lock | intr[30]; intr[ 5] = vif.ch0_dbg_upd | intr[ 5]; intr[ 4] = vif.ch0_dbg_fifo_e | intr[ 4]; intr[ 3] = vif.ch0_dbg_fifo_f | intr[ 3]; intr[ 2] = vif.ch0_ldst_addr_unalgn | intr[ 2]; intr[ 1] = vif.ch0_dec_err | intr[ 1]; intr[ 0] = vif.ch0_exit_irq | intr[ 0]; intr[13] = vif.ch1_dbg_upd | intr[13]; intr[12] = vif.ch1_dbg_fifo_e | intr[12]; intr[11] = vif.ch1_dbg_fifo_f | intr[11]; intr[10] = vif.ch1_ldst_addr_unalgn | intr[10]; intr[ 9] = vif.ch1_dec_err | intr[ 9]; intr[ 8] = vif.ch1_exit_irq | intr[ 8]; intr[21] = vif.ch2_dbg_upd | intr[21]; intr[20] = vif.ch2_dbg_fifo_e | intr[20]; intr[19] = vif.ch2_dbg_fifo_f | intr[19]; intr[18] = vif.ch2_ldst_addr_unalgn | intr[18]; intr[17] = vif.ch2_dec_err | intr[17]; intr[16] = vif.ch2_exit_irq | intr[16]; intr[29] = vif.ch3_dbg_upd | intr[29]; intr[28] = vif.ch3_dbg_fifo_e | intr[28]; intr[27] = vif.ch3_dbg_fifo_f | intr[27]; intr[26] = vif.ch3_ldst_addr_unalgn | intr[26]; intr[25] = vif.ch3_dec_err | intr[25]; intr[24] = vif.ch3_exit_irq | intr[24]; end endtask: intr_collect task spi2sysreg_refmodel::rst_check(bit[31:0] rst_time,int i,int pkt_i); int cnt=0; @(posedge xif.wren); repeat(2) @(posedge wif.clk); //$display("start rst check:%d",rst_time); cnt = rst_time; //$display("rst_time:%d",sys_cnt); while(cnt>0) begin @(posedge wif.clk); if(vif.soft_rstn[i]) break; cnt--; end @(negedge wif.clk); if(cnt!=0 | !vif.soft_rstn[i]) begin rst_error[i]++; $display("\nScoreBoard(ERROR): rst_time_error"); case(i) 0: $display("rst_module:\tSYS"); 1: $display("rst_module:\tMCU"); 2: $display("rst_module:\tAWG"); 3: $display("rst_module:\tDAC"); endcase $display("cnt:\t%d",cnt); $display("soft_rstn:\t%b",vif.soft_rstn[i]); $display("rst cmd time: @%0dth pkt.\n",pkt_i); end //else //$display("\nScoreBoard: @%0dth pkt, sys_rst successfully!\n",sys_i_save); if(!wif.csn) @(posedge wif.csn); endtask: rst_check