SPI_Test/tb/sysreg_tb/sys_refmodel.sv

245 lines
5.7 KiB
Systemverilog
Raw Normal View History

2024-06-25 16:41:01 +08:00
//For system_regfile, the ROreg: isr is updated by the intrrupt_status
//at last clk_posedge due to dff(status->irisr) & dff(irisr->isr)
class sys_refmodel;
virtual sysreg_if vif;
virtual spi_if wif;
virtual sram_if#(25,32) xif;
//interrupt buffer
bit[31:0] irisr = 32'b0;
bit irisr_clr = 1'b0;
//poor-quality register model
bit[31:0] rm[17];
//members to be sent to scoreboard
int rst_error[5];
bit[31:0] dout[$];
sysreg_trans sysout[$];
function new();
endfunction
extern task do_imitate();
extern task RWreg_write (bit[24:0] addr,bit[32:0] din);
extern task ROreg_update (bit[24:0] addr );
extern task reg_read (bit[24:0] addr );
extern task rst_check (bit[31:0] rst_time,int i );
extern task output_trace (bit[24:0] addr );
endclass : sys_refmodel
task sys_refmodel::do_imitate();
int i=0,j=0;
rm[ 0] = 32'h41574743; //IDR
rm[ 1] = 32'h55535443; //VIDR
rm[ 2] = 32'h20220831; //DATER
rm[ 3] = 32'h00000001; //VERR
rm[ 4] = 32'h01234567; //TESTR
rm[ 5] = 32'b0; //IMR
rm[ 6] = 32'b0; //ISR
rm[ 7] = 32'd300; //SFRTR
rm[ 8] = 32'd0; //SFRR
rm[ 9] = 32'd0; //CH0RSTR
rm[10] = 32'd0; //CH1RSTR
rm[11] = 32'd0; //CH2RSTR
rm[12] = 32'd0; //CH3RSTR
rm[13] = 32'd0; //DBGCFGR
rm[14] = 32'd0;
rm[15] = 32'd0;
rm[16] = 32'd0; //MISR
fork
while(1) begin: write_reg_RW
@(negedge xif.wren);
RWreg_write(xif.addr,xif.din);
end: write_reg_RW
while(1) begin: update_reg_RO
ROreg_update(xif.addr);
end: update_reg_RO
while(1) begin: read_reg
@(negedge xif.rden);
repeat(3) @(posedge xif.clk);
reg_read(xif.addr);
end: read_reg
begin: rst_port
for(i=0;i<5;i++) begin
automatic int rst_i = i;
fork
while(1) begin
@(negedge xif.wren);
if(xif.addr[24: 2]==23'h08+rst_i)
rst_check(rm[7],rst_i);
end
join_none
end
wait fork;
end: rst_port
while(1) begin: dbg_port
@(negedge xif.wren);
output_trace(xif.addr);
end: dbg_port
join
endtask: do_imitate
task sys_refmodel::RWreg_write(bit[24:0] addr,bit[32:0] din);
//delay caused by decoder
@(posedge wif.clk);
case(addr[24: 2])
23'h04: rm[ 4] = din; //TESTR
23'h05: rm[ 5] = din; //IMR
23'h07: rm[ 7] = din; //SFRTR
23'h0d: rm[13] = {rm[13][31:6],din[5:0]}; //DBGCFGR
endcase
// $display("addr:%0h",addr);
// $display("rm[%d]:%h",addr[24:2],rm[addr[24: 2]]);
// $display("din:%h",din);
endtask: RWreg_write
task sys_refmodel::ROreg_update(bit[24:0] addr);
//irisr->isr
@(posedge wif.clk);
rm[ 6] = irisr ;
rm[14] = irisr & rm[5] ;
//intr_status->irisr
if(irisr_clr)
irisr = vif.status;
else
irisr = irisr | vif.status ;
endtask: ROreg_update
task sys_refmodel::reg_read(bit[24:0] addr);
case(addr[24: 2])
23'h00: dout.push_back(rm[ 0]); //IDR
23'h01: dout.push_back(rm[ 1]); //VIDR
23'h02: dout.push_back(rm[ 2]); //DATER
23'h03: dout.push_back(rm[ 3]); //VERR
23'h04: dout.push_back(rm[ 4]); //TESTR
23'h05: dout.push_back(rm[ 5]); //IMm
23'h06: dout.push_back(rm[ 6]); //ISR
23'h07: dout.push_back(rm[ 7]); //SFRTR
23'h08: dout.push_back(rm[ 8]); //SFRR
23'h09: dout.push_back(rm[ 9]); //CH0RSTR
23'h0a: dout.push_back(rm[10]); //CH1RSTR
23'h0b: dout.push_back(rm[11]); //CH2RSTR
23'h0c: dout.push_back(rm[12]); //CH3RSTR
23'h0d: dout.push_back(rm[13]); //DBGCFGR
23'h0e: dout.push_back(0);
23'h10: begin //MISR
dout.push_back(rm[16]);
irisr_clr = 1'b1;
end
23'h11: dout.push_back(0);
endcase
// $display("dout:%h",dout[$]);
@(posedge wif.clk);
irisr_clr = 1'b0;
endtask: reg_read
task sys_refmodel::rst_check(bit[31:0] rst_time,int i);
int cnt=0;
//delay caused by decoder
@(posedge wif.clk);
cnt = rst_time;
//$display("%h",addr);
//$display("rst_time:%h",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\t@%t",$realtime);
case(i)
0: $display("rst_module:\tSYS");
1: $display("rst_module:\tch0");
2: $display("rst_module:\tch1");
3: $display("rst_module:\tch2");
4: $display("rst_module:\tch3");
endcase
$display("cnt:\t%d",cnt);
$display("soft_rstn:\t%b",vif.soft_rstn[i]);
end
endtask: rst_check
task sys_refmodel::output_trace(bit[24:0] addr);
if(addr[24:20] == 5'h0);
begin
sysreg_trans tr_temp;
bit irq = |rm[14];
//delay caused by decoder
@(posedge wif.clk);
@(negedge wif.clk);
tr_temp = new();
tr_temp.dbg_enable = rm[13][0:0]; //DBGCFGR
tr_temp.dbg_data_sel = rm[13][1:1];
tr_temp.dbg_ch_sel = rm[13][3:2];
tr_temp.irq = irq;
sysout.push_back(tr_temp);
end
// $display("addr:%0h",addr);
//$display("rm:%h",rm[addr[24: 2]]);
//$display("din:%h",din);
endtask: output_trace