// Voltage controlled oscillators
//
// Version 1b, 23 October 2006
//
// Ken Kundert
//
// Downloaded from The Designer's Guide (www.designers-guide.org).
// Post any questions to www.designers-guide.org/Forum

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

//
// Voltage controlled oscillator with no jitter
//

module vco (out, in);

input in; voltage in;				// input terminal
output out; voltage out;			// output terminal
parameter real vmin=0;				// input voltage that corresponds to minimum output frequency
parameter real vmax=vmin+1 from (vmin:inf);	// input voltage that corresponds to maximum output frequency
parameter real fmin=1 from (0:inf);		// minimum output frequency
parameter real fmax=2*fmin from (fmin:inf);	// maximum output frequency
parameter real vl=-1;				// high output voltage
parameter real vh=1;				// low output voltage
parameter real tt=0.01/fmax from (0:inf);	// output transition time
parameter real ttol=1u/fmax from (0:1/fmax);	// time tolerance
real freq, phase;
integer n;

analog begin
    // compute the freq from the input voltage
    freq = (V(in) - vmin)*(fmax - fmin) / (vmax - vmin) + fmin;

    // bound the frequency (this is optional)
    if (freq > fmax) freq = fmax;
    if (freq < fmin) freq = fmin;

    // bound the time step to assure no cycles are skipped
   // $bound_step(0.1/freq);

    // phase is the integral of the freq modulo 2p
    //idtmod(expr [ , ic [ , modulus [, offset [, abstol | nature ] ] ] ] ) 
    //offset < idtmod_output < offset+modulus
    phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5);
   // phase = 2*`M_PI*idtmod(freq, 0.0, 1.0);
    // identify the point where switching occurs
    @(cross(phase + `M_PI/2, +1, ttol) or cross(phase - `M_PI/2, +1, ttol))
	n = (phase >= -`M_PI/2) && (phase < `M_PI/2);

    // generate the output
    V(out) <+ transition(n ? vh : vl, 0, tt);
end
endmodule
