// Voltage controlled oscillators // // Version 2, 2 April 2019 // // 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 // output is sinusoidal with no jitter // module vco0 (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 va=1; // amplitude 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.2/freq); // phase is the integral of the freq modulo 2 pi phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5); V(out) <+ va*sin(phase); end endmodule // // Voltage controlled oscillator // output is square wave with no jitter // module vco1 (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: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.6/freq); // phase is the integral of the freq modulo 2 pi phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5); // 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 // // Voltage controlled oscillator // output is square wave with white accumulating jitter // module vco2 (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:0.1/fmax); // time tolerance parameter real jitter=0 from [0:0.25/fmax); // period jitter (produces white accumulating jitter) real freq, phase, dT; integer n, seed; analog begin @(initial_step) seed = -561; // 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; // add the phase noise freq = freq/(1 + dT*freq); // bound the time step to assure no cycles are skipped $bound_step(0.6/freq); // phase is the integral of the freq modulo 2 pi phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5); // update jitter twice per period // `M_SQRT2=sqrt(K), K=2 jitter updates/period @(cross(phase + `M_PI/2, +1, ttol) or cross(phase - `M_PI/2, +1, ttol)) begin dT = `M_SQRT2*jitter*$rdist_normal(seed,0, 1); n = (phase >= -`M_PI/2) && (phase < `M_PI/2); end // generate the output V(out) <+ transition(n ? vh : vl, 0, tt); end endmodule // // Differential quadrature voltage controlled oscillator // output is square wave with white accumulating jitter // module quadVco (PIout,NIout, PQout,NQout, Pin,Nin); input Pin, Nin; voltage Pin, Nin; // input terminals output PIout, NIout; voltage PIout, NIout; // output terminals output PQout, NQout; voltage PQout, NQout; // output terminals 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:0.1/fmax); // time tolerance parameter real jitter=0 from [0:0.25/fmax); // period jitter (produces white accumulating jitter) real freq, phase, dT; integer i, q, seed; analog begin @(initial_step) seed = 133; // compute the freq from the input voltage freq = (V(Pin,Nin) - vmin) * (fmax - fmin) / (vmax - vmin) + fmin; // bound the frequency (this is optional) if (freq > fmax) freq = fmax; if (freq < fmin) freq = fmin; // add the phase noise freq = freq/(1 + dT*freq); // bound the time step to assure no cycles are skipped $bound_step(0.6/freq); // phase is the integral of the freq modulo 2 pi phase = 2*`M_PI*idtmod(freq, 0.0, 1.0, -0.5); // update jitter where phase crosses p/2 // 2=sqrt(K), K=4 jitter updates per period @(cross(phase - 3*`M_PI/4, +1, ttol) or cross(phase - `M_PI/4, +1, ttol) or cross(phase + `M_PI/4, +1, ttol) or cross(phase + 3*`M_PI/4, +1, ttol)) begin dT = 2*jitter*$rdist_normal(seed,0,1); i = (phase >= -3*`M_PI/4) && (phase < `M_PI/4); q = (phase >= -`M_PI/4) && (phase < 3*`M_PI/4); end // generate the I and Q outputs V(PIout) <+ transition(i ? vh : vl, 0, tt); V(NIout) <+ transition(i ? vl : vh, 0, tt); V(PQout) <+ transition(q ? vh : vl, 0, tt); V(NQout) <+ transition(q ? vl : vh, 0, tt); end endmodule