SPI_Test/tb/pllreg_tb/pll_refmodel.sv

301 lines
13 KiB
Systemverilog
Raw Permalink Normal View History

2024-06-25 16:41:01 +08:00
//For intpll_regfile, the ROreg: status is updated by the pll_lock at present
//update output wire after wren, but the divsync_r & syncoe_r needn't update
class pll_refmodel;
virtual pllreg_if pif;
virtual spi_if wif;
virtual sram_if#(25,32) xif;
//poor-quality register model
bit[31:0] rm[22];
bit[31:0] update_rm[22];
//members to be sent to scoreboard
int rst_error[5];
bit[31:0] dout[$];
pllreg_trans pllout[$];
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 output_trace (bit[24:0] addr );
endclass : pll_refmodel
task pll_refmodel::do_imitate();
int i=0,j=0;
rm[ 0] = 32'h0006_0000; //INTPLL_REFCTRL 8'h00
rm[ 1] = 32'h000C_0000; //INTPLL_PCNT 8'h04
rm[ 2] = 32'h0006_0000; //INTPLL_PFDCTRL 8'h08
rm[ 3] = 32'h0004_0000; //INTPLL_SPDCTRL 8'h0C
rm[ 4] = 32'h0058_0000; //INTPLL_PTATCTRL 8'h10
rm[ 5] = 32'h0003_0000; //INTPLL_FLLCTRL 8'h14
rm[ 6] = 32'h0002_0000; //INTPLL_SELCTRL 8'h18
rm[ 7] = 32'h0ff0_0000; //INTPLL_VCOCTRL 8'h1C
rm[ 8] = 32'h0; //INTPLL_VCOFBADJ 8'h20
rm[ 9] = 32'h0; //INTPLL_AFCCTRL 8'h24
rm[10] = 32'h00C8_0000; //INTPLL_AFCCNT 8'h28
rm[11] = 32'h0640_0000; //INTPLL_AFCLDCNT 8'h2C
rm[12] = 32'h0003_0000; //INTPLL_AFCPRES 8'h30
rm[13] = 32'h0; //INTPLL_AFCLDTCC 8'h34
rm[14] = 32'h0; //INTPLL_AFCFBTCC 8'h38
rm[15] = 32'h0; //INTPLL_DIVCFG 8'h3C
rm[16] = 32'h0; //INTPLL_TCLKCFG 8'h40
rm[17] = 32'h1_0000; //INTPLL_DCLKSEL 8'h44
rm[18] = 32'h0; //INTPLL_STATUS 8'h48
rm[19] = 32'h0; //INTPLL_SYNCFG 8'h4C
rm[20] = 32'h0; //INTPLL_UPDATE 8'h50
rm[21] = 32'h0; //INTPLL_CLKRXPD 8'h54
update_rm[ 0] = 32'h0006_0000;
update_rm[ 1] = 32'h000C_0000;
update_rm[ 2] = 32'h0006_0000;
update_rm[ 3] = 32'h0004_0000;
update_rm[ 4] = 32'h0058_0000;
update_rm[ 5] = 32'h0003_0000;
update_rm[ 6] = 32'h0002_0000;
update_rm[ 7] = 32'h0ff0_0000;
update_rm[ 8] = 32'h0;
update_rm[ 9] = 32'h0;
update_rm[10] = 32'h00C8_0000;
update_rm[11] = 32'h0640_0000;
update_rm[12] = 32'h0003_0000;
update_rm[13] = 32'h0;
update_rm[14] = 32'h0;
update_rm[15] = 32'h0;
update_rm[16] = 32'h0;
update_rm[17] = 32'h1_0000;
update_rm[18] = 32'h0;
update_rm[19] = 32'h0;
update_rm[20] = 32'h0;
update_rm[21] = 32'h0;
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);
reg_read(xif.addr);
end: read_reg
while(1) begin: output_port
@(negedge xif.wren);
output_trace(xif.addr);
end: output_port
join
endtask: do_imitate
task pll_refmodel::RWreg_write(bit[24:0] addr,bit[32:0] din);
//delay caused by decoder
@(posedge wif.sclk);
case(addr[24: 2])
23'h7C0000: rm[ 0] = {rm[ 0][31:17+ 2],din[16+ 2:16],rm[ 0][15:0]}; //INTPLL_REFCTRL
23'h7C0001: rm[ 1] = {rm[ 1][31:17+ 6],din[16+ 6:16],rm[ 1][15:0]}; //INTPLL_PCNT
23'h7C0002: rm[ 2] = {rm[ 2][31:17+ 2],din[16+ 2:16],rm[ 2][15:0]}; //INTPLL_PFDCTRL
23'h7C0003: rm[ 3] = {rm[ 3][31:17+ 5],din[16+ 5:16],rm[ 3][15:0]}; //INTPLL_SPDCTRL
23'h7C0004: rm[ 4] = {rm[ 4][31:17+ 6],din[16+ 6:16],rm[ 4][15:0]}; //INTPLL_PTATCTRL
23'h7C0005: rm[ 5] = {rm[ 5][31:17+ 2],din[16+ 2:16],rm[ 5][15:0]}; //INTPLL_FLLCTRL
23'h7C0006: rm[ 6] = {rm[ 6][31:17+ 2],din[16+ 2:16],rm[ 6][15:0]}; //INTPLL_SELCTRL
23'h7C0007: rm[ 7] = {rm[ 7][31:17+11],din[16+11:16],rm[ 7][15:0]}; //INTPLL_VCOCTRL
23'h7C0008: rm[ 8] = {rm[ 8][31:17+ 6],din[16+ 6:16],rm[ 8][15:0]}; //INTPLL_VCOFBADJ
23'h7C0009: rm[ 9] = {rm[ 9][31:17+ 4],din[16+ 4:16],rm[ 9][15:0]}; //INTPLL_AFCCTRL
23'h7C000a: rm[10] = {rm[10][31:17+10],din[16+10:16],rm[10][15:0]}; //INTPLL_AFCCNT
23'h7C000b: rm[11] = {rm[11][31:17+10],din[16+10:16],rm[11][15:0]}; //INTPLL_AFCLDCNT
23'h7C000c: rm[12] = {rm[12][31:17+ 3],din[16+ 3:16],rm[12][15:0]}; //INTPLL_AFCPRES
23'h7C000d: rm[13] = {rm[13][31:17+14],din[16+14:16],rm[13][15:0]}; //INTPLL_AFCLDTCC
23'h7C000e: rm[14] = {rm[14][31:17+14],din[16+14:16],rm[14][15:0]}; //INTPLL_AFCFBTCC
23'h7C000f: rm[15] = {rm[15][31:17+ 0],din[16+ 0:16],rm[15][15:0]}; //INTPLL_DIVCFG
23'h7C0010: rm[16] = {rm[16][31:17+ 2],din[16+ 2:16],rm[16][15:0]}; //INTPLL_TCLKCFG
23'h7C0011: rm[17] = {rm[17][31:17+ 7],din[16+ 7:16],rm[17][15:0]}; //INTPLL_DCLKSEL
23'h7C0013: rm[19] = {rm[19][31:17+ 1],din[16+ 1:16],rm[19][15:0]}; //INTPLL_SYNCFG
23'h7C0015: rm[21] = {rm[21][31:17+ 0],din[16+ 0:16],rm[21][15:0]}; //CLKRXPD
endcase
//$display("addr:%0h",addr);
//$display("rm:%h",rm[addr[15: 2]]);
//$display("din:%h",din);
endtask: RWreg_write
task pll_refmodel::ROreg_update(bit[24:0] addr);
@(negedge wif.sclk);
rm[18] = pif.pll_lock ;
endtask: ROreg_update
task pll_refmodel::reg_read(bit[24:0] addr);
//delay caused be decoder
@(posedge wif.clk);
case(addr[24: 2])
23'h7C0000: dout.push_back(rm[ 0]); //INTPLL_REFCTRL 8'h00
23'h7C0001: dout.push_back(rm[ 1]); //INTPLL_PCNT 8'h04
23'h7C0002: dout.push_back(rm[ 2]); //INTPLL_PFDCTRL 8'h08
23'h7C0003: dout.push_back(rm[ 3]); //INTPLL_SPDCTRL 8'h0C
23'h7C0004: dout.push_back(rm[ 4]); //INTPLL_PTATCTRL 8'h10
23'h7C0005: dout.push_back(rm[ 5]); //INTPLL_FLLCTRL 8'h14
23'h7C0006: dout.push_back(rm[ 6]); //INTPLL_SELCTRL 8'h18
23'h7C0007: dout.push_back(rm[ 7]); //INTPLL_VCOCTRL 8'h1C
23'h7C0008: dout.push_back(rm[ 8]); //INTPLL_VCOFBADJ 8'h20
23'h7C0009: dout.push_back(rm[ 9]); //INTPLL_AFCCTRL 8'h24
23'h7C000a: dout.push_back(rm[10]); //INTPLL_AFCCNT 8'h28
23'h7C000b: dout.push_back(rm[11]); //INTPLL_AFCLDCNT 8'h2C
23'h7C000c: dout.push_back(rm[12]); //INTPLL_AFCPRES 8'h30
23'h7C000d: dout.push_back(rm[13]); //INTPLL_AFCLDTCC 8'h34
23'h7C000e: dout.push_back(rm[14]); //INTPLL_AFCFBTCC 8'h38
23'h7C000f: dout.push_back(rm[15]); //INTPLL_DIVCFG 8'h3C
23'h7C0010: dout.push_back(rm[16]); //INTPLL_TCLKCFG 8'h40
23'h7C0011: dout.push_back(rm[17]); //INTPLL_DCLKSEL 8'h44
23'h7C0012: dout.push_back({rm[18][15:0],rm[18][31:16]}); //INTPLL_STATUS 8'h48
23'h7C0013: dout.push_back(rm[19]); //INTPLL_SYNCFG 8'h4C
23'h7C0014: dout.push_back({rm[20][15:0],rm[20][31:16]}); //INTPLL_UPDATE 8'h50
23'h7C0015: dout.push_back(rm[21]); //INTPLL_CLKRXPD 8'h54
23'h7C0016: dout.push_back(0);
endcase
//$display("dout:%h",dout[$]);
endtask: reg_read
task pll_refmodel::output_trace(bit[24:0] addr);
pllreg_trans tr_temp;
//delay caused by decoder
// @(posedge wif.sclk);
if(addr[24:2]==23'h7c0014) begin
update_rm[ 0] = rm[ 0]; //INTPLL_REFCTRL
update_rm[ 1] = rm[ 1]; //INTPLL_PCNT
update_rm[ 2] = rm[ 2]; //INTPLL_PFDCTRL
update_rm[ 3] = rm[ 3]; //INTPLL_SPDCTRL
update_rm[ 4] = rm[ 4]; //INTPLL_PTATCTRL
update_rm[ 5] = rm[ 5]; //INTPLL_FLLCTRL
update_rm[ 6] = rm[ 6]; //INTPLL_SELCTRL
update_rm[ 7] = rm[ 7]; //INTPLL_VCOCTRL
update_rm[ 8] = rm[ 8]; //INTPLL_VCOFBADJ
update_rm[ 9] = rm[ 9]; //INTPLL_AFCCTRL
update_rm[10] = rm[10]; //INTPLL_AFCCNT
update_rm[11] = rm[11]; //INTPLL_AFCLDCNT
update_rm[12] = rm[12]; //INTPLL_AFCPRES
update_rm[13] = rm[13]; //INTPLL_AFCLDTCC
update_rm[14] = rm[14]; //INTPLL_AFCFBTCC
update_rm[15] = rm[15]; //INTPLL_DIVCFG
update_rm[16] = rm[16]; //INTPLL_TCLKCFG
update_rm[17] = rm[17]; //INTPLL_DCLKSEL
//update_rm[18] = rm[18];
//update_rm[21] = rm[21];
end
@(negedge wif.sclk);
tr_temp = new();
if(addr[24:20] == 5'h1F) begin
tr_temp.ref_sel = update_rm[ 0][16+0] ; // Clock source selection for a frequency divider;
// 1'b0:External clock source
// 1'b1:internal phase-locked loop clock source
tr_temp.ref_en = update_rm[ 0][16+1] ; // Input reference clock enable
// 1'b0:enable,1'b1:disable
tr_temp.ref_s2d_en = update_rm[ 0][16+2] ; // Referenced clock differential to single-ended conversion enable
// 1'b0:enable,1'b1:disable
tr_temp.p_cnt = update_rm[ 1][16+6 :16]; // P counter
tr_temp.pfd_delay = update_rm[ 2][16+0 ]; // PFD Dead Zone
tr_temp.pfd_dff_Set = update_rm[ 2][16+1 ]; // Setting the PFD register,active high
tr_temp.pfd_dff_4and = update_rm[ 2][16+2 ]; // PFD output polarity
tr_temp.spd_div = update_rm[ 3][16+3 :16]; // SPD Frequency Divider
tr_temp.spd_pulse_width = update_rm[ 3][16+4 ]; // Pulse Width of SPD
tr_temp.spd_pulse_sw = update_rm[ 3][16+5 ]; // Pulse sw of SPD
tr_temp.cpc_sel = update_rm[ 4][16+6 ]; // current source selection
tr_temp.swcp_i = update_rm[ 4][16+5 :16+4]; // PTAT current switch
tr_temp.sw_ptat_r = update_rm[ 4][16+3 :16+0]; // PTAT current adjustment
tr_temp.sw_fll_cpi = update_rm[ 5][16+1 :16+0]; // Phase-locked loop charge pump current
tr_temp.sw_fll_delay = update_rm[ 5][16+2 ]; // PLL Dead Zone
tr_temp.pfd_sel = update_rm[ 6][16+0 ]; // PFD Loop selection
tr_temp.spd_sel = update_rm[ 6][16+1 ]; // SPD Loop selection
tr_temp.fll_sel = update_rm[ 6][16+2 ]; // FLL Loop selection
tr_temp.vco_tc = update_rm[ 7][16+0 ]; // VCO temperature compensation
tr_temp.vco_tcr = update_rm[ 7][16+1 ]; // VCO temperature compensation resistor
tr_temp.vco_gain_adj = update_rm[ 7][16+2 ]; // VCO gain adjustment
tr_temp.vco_gain_adj_r = update_rm[ 7][16+3 ]; // VCO gain adjustment resistor
tr_temp.vco_cur_adj = update_rm[ 7][16+6 :16+4]; // VCO current adjustment
tr_temp.vco_buff_en = update_rm[ 7][16+7 ]; // VCO buff enable,active high
tr_temp.vco_en = update_rm[ 7][16+8 ]; // VCO enable,active high
tr_temp.pll_dpwr_adj = update_rm[ 7][16+11:16+9]; // PLL frequency division output power adjustment
tr_temp.vco_fb_adj = update_rm[ 8][16+6 :16+0]; // VCO frequency band adjustment
tr_temp.afc_en = update_rm[ 9][16+0 ]; // AFC enable
tr_temp.afc_reset = update_rm[ 9][16+1 ]; // AFC reset
tr_temp.afc_shutdown = update_rm[ 9][16+2 ]; // AFC module shutdown signal
tr_temp.flag_out_sel = update_rm[ 9][16+3 ]; // Read and choose the signs
tr_temp.afc_det_speed = update_rm[ 9][16+4 ]; // AFC detection speed
tr_temp.afc_cnt = update_rm[10][16+10:16]; // AFC frequency band adjustment function counter
// counting time adjustment
tr_temp.afc_ld_cnt = update_rm[11][16+10:16] ; // Adjust the counting time of the AFC lock detection
// feature counter
tr_temp.afc_pres = update_rm[12][16+ 3:16] ; // Adjusting the resolution of the AFC comparator
tr_temp.afc_ld_tcc = update_rm[13][16+14:16] ; // AFC Lock Detection Function Target Cycle Count
tr_temp.afc_fb_tcc = update_rm[14][16+14:16] ; // Target number of cycles for AFC frequency band
// adjustment function
repeat(1) @(posedge wif.sclk);
tr_temp.div_rstn_sel = rm[15][16+0 ] ; // DAC frequency divider frequency control
tr_temp.test_clk_sel = rm[16][16+1:16+0] ; // ADC frequency divider frequency control
tr_temp.test_clk_oen = rm[16][16+2 ] ; // DIGITAL frequency divider frequency contr
tr_temp.dig_clk_sel = rm[17][16+7:16+0] ;
tr_temp.div_sync_en = rm[19][16+0 ] ; // Frequency Divider Synchronous Clear Enable
tr_temp.sync_oe = rm[19][16+1] ; // SYNC signal output enable, hign active
tr_temp.clkrx_pdn = rm[21][16+0] ; //
pllout.push_back(tr_temp);
end
//$display("addr:%0h",addr);
//$display("rm:",rm);
//$display("din:%h",din);
endtask: output_trace