The Designer's Guide Community
Forum
Welcome, Guest. Please Login or Register. Please follow the Forum guidelines.
Mar 29th, 2024, 2:23am
Pages: 1
Send Topic Print
how to make sdm based fractional pll's transient simulation more accurate? (Read 55 times)
lwzunique
Community Member
***
Offline



Posts: 38

how to make sdm based fractional pll's transient simulation more accurate?
Oct 24th, 2019, 7:24pm
 
Hi,everyone!

the problem is as following:
1. this fractional pll is based on veriloga. all blocks are veriloga model.
2. charge pump current is Icp=16uA, VCO gain kvco=100Mhz, LPF ’s C1=36pf, R1=100K, C2=3.6pf,R3=65K,C3=1pf。
3.when doing transient simulation,after pll locked, using freq function in viva calculator to measure the vco’s frequency, the frequency‘s fluctuation is about 200khz peak to peak, and the center frequency is 4.8G.

it should have fluctuation, but isn't  this value  too large? which magnitude should this fluctuation should
be?

if the magnitude is about 10khz or less, what's wrong with my model.

the model is as below:


PFD code:
Code:
`include "constants.vams"
`include "disciplines.vams"

module PFD_V1_VA (ref_clk, fb_clk, up_out, down_out);
inout ref_clk, fb_clk, up_out, down_out;
electrical ref_clk, fb_clk, up_out, down_out;
parameter real vdd=3.3,
ttol=10f,
ttime=0.2n ;
integer state; // state=1 for down, -1 for up
real td_up, td_down ;
/*
analog begin
@(cross( V(ref_clk) - vdd/2 , 1 , ttol )) begin
state = state - 1;
if(V(up_out)>vdd/2) td_up=480p; else td_up=1005p;
if(V(down_out)<vdd/2) td_down=480p; else td_down=1090p;
end
@(cross( V(fb_clk) - vdd/2 , 1 , ttol )) begin
state = state + 1;
if(V(up_out)>vdd/2) td_up=480p; else td_up=1005p;
if(V(down_out)<vdd/2) td_down=480p; else td_down=1090p;
end
if ( state > 1 ) state = 1 ;
if ( state < -1 ) state = -1;
V(down_out) <+ transition( (state + 1)/2*vdd , td_down , ttime );
V(up_out) <+ transition( (state - 1)/2*vdd+vdd , td_up , ttime );
end
*/
analog begin
@(cross( V(ref_clk) - vdd/2 , 1 , ttol )) begin
if(state<1) state = state + 1;
end
@(cross( V(fb_clk) - vdd/2 , 1 , ttol )) begin
if(state>-1) state = state - 1;
end
V(up_out) <+ transition( (state==1)?1.2:0 , 0 , 10p );
V(down_out) <+ transition( (state==-1)?1.2:0 , 0 , 10p );
end
endmodule 



CP code:
Code:
`include "constants.vams"
`include "disciplines.vams"

module CP_VA(up,down,iout);
input up,down;
output iout;
electrical up,down,iout;
parameter Vhigh=1 from[0:inf);
parameter Vlow=0 from[0:inf);
parameter Vtrans=0.5;
parameter vp_h=1.2;
parameter vp_l=0;
/*
real iuptemp,idowntemp,chargecurrent;
analog begin
  chargecurrent=50u;
  iuptemp=(V(up)>Vtrans)?1:0;
  idowntemp=(V(down)>Vtrans)?-1:0;
  I(iout)<+ -iuptemp*chargecurrent-idowntemp*chargecurrent;
  end
endmodule
*/
real iuptemp,idowntemp,chargecurrentdown,chargecurrentup;
analog begin
  if(V(iout)>(vp_l+200m))
     chargecurrentdown=16u;
  if(V(iout)>vp_l && V(iout)<=(vp_l+200m) )
     chargecurrentdown=V(iout)*80u;
  if(V(iout)<=vp_l)
     chargecurrentdown=0;

   if(V(iout)<(vp_h-200m))
     chargecurrentup=16u;
  if(V(iout)>=(vp_h-200m) && V(iout)<vp_h )
     chargecurrentup=(vp_h-V(iout))*80u;
  if(V(iout)>=vp_h)
     chargecurrentup=0;
/*
  iuptemp=(V(up)>Vtrans)?1:0;
  idowntemp=(V(down)>Vtrans)?-1:0;
*/

@(cross(V(up)-Vtrans,1)) iuptemp=1;
@(cross(V(up)-Vtrans,-1)) iuptemp=0;
@(cross(V(down)-Vtrans,1)) iuptemp=-1;
@(cross(V(down)-Vtrans,-1)) iuptemp=0;
  I(iout)<+ -iuptemp*chargecurrentup-idowntemp*chargecurrentdown;
    

end
endmodule 



VCO code:
Code:
`include "constants.vams"
`include "disciplines.vams"

module VCO_BITS_TP_FD_VA(loopin,tp,bits,freqout);
input loopin,tp;
input [3:0] bits;
output freqout;
electrical loopin,tp;
electrical [3:0] bits;
electrical freqout;
parameter vhigh=1.2;
parameter vlow=0;
parameter vtrans=(vhigh+vlow)/2;
real tempbits;
real freq;
real fmax;
real fmin;
real vmax;
real vmin;
real initial_freq;
real space;
real kvco;
real gain;
analog begin
kvco=100M;
initial_freq=4720M;
space=20M;
vmax=800m;
vmin=400m;

tempbits=0;
tempbits=tempbits+((V(bits[3])>vtrans)?1:0)*8;
tempbits=tempbits+((V(bits[2])>vtrans)?1:0)*4;
tempbits=tempbits+((V(bits[1])>vtrans)?1:0)*2;
tempbits=tempbits+((V(bits[0])>vtrans)?1:0)*1;
case(tempbits)
0,1,2,3 : gain=1.6M;
4,5,6,7: gain=1.8M;
8,9,10,11:gain=2M;
12,13,14,15:gain=2.4M;
default gain=1.6M;
endcase
fmin=initial_freq+tempbits*space;
fmax=initial_freq+(vmax-vmin)*kvco+tempbits*space;

freq=(V(loopin)-vmin)*kvco+fmin+(V(tp)-0.6)*gain;


if (freq > fmax) freq = fmax;
if (freq < fmin) freq = fmin;
//$bound_step(1/(freq*100));

V(freqout) <+   freq/1e6;


end
endmodule 



freq to sin wave conversion code:
Code:
`include "constants.vams"
`include "disciplines.vams"
`define PI	  3.14159265358979323846264338327950288419716939937511
module FREQ2VOL_V1_VA(vin, rst, vout);
input vin, rst;
output vout;

electrical vin, rst, vout;

parameter real amp=0.6;
parameter integer steps_per_period=32;
parameter real vco_gain=1e6;

real phase, inst_freq, phase_modulus;
analog begin
	if(V(rst)>0.6) begin
		inst_freq=1e6;
		phase_modulus=1e-3;
		end
	else begin
		inst_freq=vco_gain*V(vin);
		phase_modulus=1;
		end
	$bound_step(1.0 / (steps_per_period*inst_freq));
	phase=idtmod(inst_freq, 0, phase_modulus);
	V(vout) <+ 0.6+amp*sin(2*`PI*phase-`PI);
	end


endmodule
 



DIVIDER code:
Code:
// VerilogA for nb1820_t55lp_lwz_v01, DIV_VAR_FD_VA, veriloga

`include "constants.vams"
`include "disciplines.vams"

module DIV_VAR_FD_VA(ratio,freqin,freqout);
input freqin,ratio;
output freqout;
electrical freqin,ratio, freqout;

real tempratio;

analog begin

    tempratio=2*V(ratio);

    
    V(freqout) <+ V(freqin)/tempratio;

end


endmodule 




Back to top
 

pll_model.png
View Profile   IP Logged
lwzunique
Community Member
***
Offline



Posts: 38

Re: how to make sdm based fractional pll's transient simulation more accurate?
Reply #1 - Oct 24th, 2019, 7:29pm
 
mash code:
Code:
`include "constants.h"
`include "discipline.h"

module MASH_VA(fset, cp, f, f_av);
output f;
output f_av;
input cp;
input fset;

electrical f;
electrical cp;
electrical f_av;
electrical fset;

parameter integer BIT = 8;
parameter real vtrans = 0.5;
parameter real outOffset = 0;

   integer out_value;
   real av_out_value;
   integer sum1, sum3, sum2;
   integer sum1_d, sum2_d, sum3_d;
   integer c1, c2, c3;
   integer c3_d;
   integer c2c3, c2c3_d;
   integer c1c2c3;
   integer j, n,  m , k;

   real unconverted;
   real vref;
   real halfref;
   integer vd[0:BIT-1];
   integer w[0:BIT-1];

   analog begin
	@(initial_step ) begin
	  
	  for ( j = 0; j <= BIT-1 ; j=j+1 ) begin
	    w[j] = 1;
	  end
	  for ( j = 1; j <= BIT-1 ; j=j+1 ) begin
	     for ( n = 1; n <= j; n=n+1 ) begin
		 w[j] = 2*w[j];
	     end
	  end
	  for ( j = 0; j <= BIT-1 ; j=j+1 ) begin
	   //  $strobe("w[%d]=%d\n",j,w[j]);
	  end
	  vref = 1.0;
	  halfref = vref / 2;
	  out_value = 0;
	  av_out_value = 0;
	  n = 1;
	  m = 1;
	  for ( j = 1; j <= BIT ; j=j+1 ) begin
	    m = m * 2;
	  end  
	  k = 0;
	  if ( k >= m ) begin
	     $strobe("k must be less than 2^%d", BIT);
	     $finish;
	  end
	  
	  c1 = 0;
	  c2 = 0;
	  c3 = 0;
	  sum1 = 0;
	  sum2 = 0;
	  sum3 = 0;
	  sum1_d =0;
	  sum2_d =0;
	  sum3_d =0;
	  c3_d = 0;
	  c2c3 = 0;
	  c2c3_d = 0;
	  c1c2c3 = 0;
	end

	sum1 = k + sum1_d;
	sum2 = sum1_d + sum2_d;
	sum3 = sum2_d + sum3_d;

	if ( sum1 >= m ) begin
	 c1 = 1;
	 sum1 = sum1 - m;
	end else begin
	 c1 = 0;
	end

	if ( sum2 >= m ) begin
	 c2 = 1;
	 sum2 = sum2 - m;
	end else begin
	 c2 = 0;
	end

	if ( sum3 >= m ) begin
	 c3 = 1;
	 sum3 = sum3 - m;
	end else begin
	 c3 = 0;
	end
	c2c3 = c2 + c3 - c3_d;
	c1c2c3 = c1 + c2c3 - c2c3_d;
	out_value = c1c2c3;

	@(cross(V(cp)-vtrans, 1, 10f, cp.potential.abstol) ) begin
	  n = n + 1;
	  // update k , it is input analogue to digital
	  unconverted = V(fset);
	  for (j = (BIT-1); j >= 0 ; j = j - 1) begin
	     vd[j] = 0;
	     if (unconverted >= halfref) begin
		  vd[j] = 1;
		  unconverted = unconverted - halfref;
	     end else begin
		  vd[j] = 0;
	     end
	     unconverted = unconverted * 2;
	  end
	  k = 0;
	  for ( j = 0; j <= BIT-1 ; j=j+1 ) begin
	    k = k + vd[j]*w[j];
	  end
	   // $strobe("k=%d\n",k);
	  av_out_value = av_out_value + out_value;
	  sum1_d = sum1;
	  sum2_d = sum2;
	  sum3_d = sum3;
	  c3_d = c3;
	  c2c3_d = c2c3;
	end

	V(f) <+ out_value + outOffset;
	V(f_av) <+ outOffset + av_out_value/n;

   end 

Back to top
 
« Last Edit: Oct 25th, 2019, 12:33am by lwzunique »  
View Profile   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2384
Silicon Valley
Re: how to make sdm based fractional pll's transient simulation more accurate?
Reply #2 - Oct 26th, 2019, 11:43am
 
If you are asking other people to help you with your code, you should take a little time and clean it up to make it easy to read.

If you are going to create a 5kV signal, be sure to run transient with relref=alllocal or errpreset=conservative. Otherwise the simulator will not control errors on normal sized signals.

-Ken
Back to top
 
 
View Profile WWW   IP Logged
lwzunique
Community Member
***
Offline



Posts: 38

Re: how to make sdm based fractional pll's transient simulation more accurate?
Reply #3 - Oct 26th, 2019, 7:18pm
 
Ken Kundert wrote on Oct 26th, 2019, 11:43am:
If you are asking other people to help you with your code, you should take a little time and clean it up to make it easy to read.

If you are going to create a 5kV signal, be sure to run transient with relref=alllocal or errpreset=conservative. Otherwise the simulator will not control errors on normal sized signals.

-Ken


thanks for reply.

after posting this question,I have done a simulation, changing the bandwidth of pll from 100k to 10k, the fluctuation changed from about 150khz to 2khz. which means 100khz bandwidth can't suppress the quantization noise of sdm. so maybe it's not errors in the code that caused bad accuracy, it's bad system parameters that matters.

I have always thought it was the code and simulation accuracy caused this fluctuation,it seems to be the mis-understanding of thinking.

in my model, vco's output is its frequency ,so  5kv means its freq is 5Ghz, and divider is also frequency domain, after the divider, the freq_to_vol block will change frequency to voltage to form the feedback signal for pfd block.

I will change relref and errpreset to check if this can make the result more accurate.
Back to top
 
 
View Profile   IP Logged
Pages: 1
Send Topic Print
Copyright 2002-2024 Designer’s Guide Consulting, Inc. Designer’s Guide® is a registered trademark of Designer’s Guide Consulting, Inc. All rights reserved. Send comments or questions to editor@designers-guide.org. Consider submitting a paper or model.