//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