301 lines
13 KiB
Systemverilog
301 lines
13 KiB
Systemverilog
//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
|