tunable_clock_gen.svh 1.48 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
`timescale 10fs/10fs

module tunable_clock_gen
  (
   input real vtune_i,
   input enable_i,
   output clk_o);

 
   parameter g_tunable 	       = 0;
   parameter g_tuning_range    = 20e-6; // 20 ppm
   parameter g_tuning_voltage  = 1.0;
   parameter real g_period     = 8ns;
   parameter real g_jitter     = 10ps;

   reg clk 		       = 1'b1;

   real cur_offset 	       = 0;
   real prev_err 	       = 0;
   real next_offset;
   real cur_err;
   real cur_period;
   int seed  = 1;

   real max_range;

   
   initial begin
      cur_offset   = 0;
      prev_err 	   = 0;
   end
   
   
   initial forever 
     if(enable_i) 
       begin
	  seed 	   = $urandom(seed);

	  
	  cur_err  = (real'($urandom_range(0, 1000)) -500.0)/ 1000.0 * g_jitter;


//	  $display("%.15f %.15f", cur_err, g_jitter);
	  
	  
	  if(g_tunable)
	    begin
	       realtime period_tune;



	       period_tune   = realtime'(real'(g_period/2) * (vtune_i-(real'(g_tuning_voltage/2)))/(real'(g_tuning_voltage/2)) * real'(g_tuning_range));
	       
		  
		 cur_period  = g_period/2 + period_tune ;
	       
	    end else
	      cur_period     = g_period/2;
	  
	  
	  next_offset 	     = -prev_err + cur_period + cur_err;
	  
	  prev_err 	     = cur_err;

//	  $display("NextOffs: %.15f", next_offset);
	  
	  #(integer'(next_offset)) clk = ~clk;
	  
	  end else begin // if (enable)
	     cur_offset  = 0;
	     cur_period  = 0;
	     clk 	 = 1;
	     #1;
	  end // else: !if(enable)

   assign clk_o 	 = clk;
endmodule // tunable_clock_gen