module: vco_quantizer
parameters: double mismatch int n_stages double a double b double c double d double e double f
inputs:  double_interp clk double vc
outputs:  double out
static_variables: 
  double phase_threshold
  double phase_offset
  double vco_phase
  double count
  double kv
classes:  
  Vco vco("fc + Kv*x","fc,Kv,Ts",0,1,Ts)
  List mm_list()
  List phase_list()
  Rand rand_mm("gauss")
  EdgeDetect clk_edge()
init:
  int i;
  double phase_acc;
  double mm_sum;
  phase_offset = 2*PI/n_stages/4;
  phase_acc = 0;
  count = 0;
  for (i = 0; i < 2*n_stages; i++)
    mm_list.inp(2*PI/n_stages*(1+mismatch/100*rand_mm.inp()));
  mm_sum = mm_list.mean()*(2*n_stages-0);
  phase_list.inp(0.0);
  for (i = 1; i < 2*n_stages; i++) {
    phase_list.inp(2*PI*mm_list.read()/mm_sum + phase_acc);
    phase_acc = 2*PI*mm_list.read()/mm_sum + phase_acc;
  }
//  for (i = 0; i < 2*n_stages; i++) {
//    printf("i = %i: phase_list.read = %e\n",i,phase_list.read());
//  }
  phase_list.reset();
  phase_threshold = phase_list.read();
code:
  if (clk_edge.inp(clk)) {
    out = count;
    count = 0;
  }
//  vco.inp((a+b1*vc*(c1-exp((vc+d1)/e1))+b2*vc*(c2-exp((d2-vc)/e2)))/2/n_stages);
  vco.inp((a+b*vc+c*vc*vc+d*vc*vc*vc+e*vc*vc*vc*vc+f*vc*vc*vc*vc*vc)/2/n_stages);
  vco_phase = vco.phase - phase_offset;
  if (vco_phase > phase_threshold) {
    if (phase_threshold == 0) {
      if (vco_phase < phase_offset) {
        count = count + 1; 
        phase_threshold = phase_list.read();
      }
    }
    else {
      count = count + 1; 
      phase_threshold = phase_list.read();
    }
  }
