`include "discipline.h" `include "constants.h" // Divide by N counter // // Contains no hidden state, and so it works with SpectreRF // // Will fail if N is large, say greater than 1000. Can tighten tolerances // to increase the range of N, or you can break N into integer factors and // implement the divide by N with several counters in series. // // Downloaded from The Designer's Guide Community (www.designers-guide.org). // Post any questions on www.designers-guide.org/Forum. module divideByN(pout, nout, pin, nin); output pout, nout; input pin, nin; electrical pin, nin, pout, nout; electrical vg, chg, hold; parameter integer n = 2 from [2:inf); // divide ratio parameter integer nhi = 1 from [1:n-1]; // number of hi counts per output pulse parameter integer dir = 1 from [-1:1] exclude 0; // +1 for rising edge triggered // -1 for falling edge triggered parameter real tt=0.01; // output transition time parameter real vdd=5, vss=0; // defines output high and low levels parameter real thresh=(vdd+vss)/2; // input threshold is at midpoint real vmax; integer out, count; real g; real vchg; analog begin vmax = max(abs(vdd),abs(vss)); g = 5*ln(n); @(cross(V(pin,nin) - thresh, 0)); // hold capacitor with capacitance tt I(vg,hold) <+ tt*ddt(V(vg,hold)); // clamp hold capacitor during dc analysis if (analysis("static")) I(vg,hold) <+ V(vg,hold); // ideal op amp V(hold): V(vg) == 0; // titrating capacitor with capacitance tt I(chg) <+ tt*ddt(V(chg)); // titrating capacitor is precharged when input is high // if V(hold) is in range, // precharge to vmax/n volts to increment hold cap one level, // else // precharge with equal but opposite the charge on the hold cap // in order to reset hold cap to zero if ((V(hold) < vmax*(1.5/n-1)) && (dir*V(pin,nin) < dir*thresh)) begin vchg = V(hold); end else begin vchg = vmax/n; end // determine the count count = -n*V(hold)/vmax; // charge or discharge when input is high through g Siemen switches if (dir*V(pin,nin) > dir*thresh) begin // dump titrating charge onto hold cap I(vg,chg) <+ g*V(vg,chg); end else begin // precharge titrating capacitor I(chg) <+ g*(V(chg)-vchg); // use discrete-level feedback to correct for any errors in hold chg I(vg) <+ -n*V(hold)/vmax - count; end // output pulse when V(in) is high and V(hold) below threshold out = count >= (n - nhi); V(pout,nout) <+ transition(vss + out*(vdd-vss), 0.0, tt, tt); end endmodule // used to check the divider above // connect in to input of divider and reset to output of divider // set parameter values in the same way as on the divider // this module has hidden state and so cannot be used with SpectreRF module counter(reset, in); input in, reset; electrical in, reset; parameter real vdd=5, vss=0; parameter real thresh=(vdd+vss)/2; parameter integer dir = 1 from [-1:1] exclude 0; integer n; analog begin @(cross(V(in) - thresh, dir)) n = n + 1; @(cross(V(reset) - thresh, dir)) begin $strobe( "count = %d\n", n ); n = 0; end end endmodule // Periodic Track & Hold // // Works with SpectreRF (has no hidden state) // Almost ideal ... // Has buffered input and output (infinite input Z, zero out Z) // Exhibits no offset or distortion errors // Only nonideality is finite aperture time and very small amount of droop `include "discipline.h" `include "constants.h" module th (Pout, Nout, Pin, Nin); electrical Pin, Nin, Pout, Nout; input Pin, Nin; output Pout, Nout; parameter real period=1 from (0:inf); parameter real tdelay=0 from [0:inf); parameter real aperture=period/100 from (0:period/2); parameter real tc=aperture/10 from (0:aperture); integer n; real tstart, tstop; electrical hold; analog begin // Determine the point where the aperture begins; n = ($abstime - tdelay + aperture) / period + 0.5; tstart = n*period + tdelay - aperture; @(timer(tstart)); // Determine the time where the aperture ends; n = ($abstime - tdelay) / period + 0.0; tstop = n*period + tdelay; @(timer(tstop)); // Implement switch with effective series resistence of 1 Ohm if (($abstime > tstop - aperture) && ($abstime <= tstop)) I(hold) <+ V(hold) - V(Pin, Nin); else I(hold) <+ 1.0e-12 * V(hold); // Implement capacitor with an effective capacitance of tc I(hold) <+ tc * ddt(V(hold)); // Buffer output V(Pout, Nout) <+ V(hold); // Control time step tightly during aperture and loosely otherwise if (($abstime >= tstop - aperture) && ($abstime < tstop)) begin $bound_step(tc); end else begin $bound_step(period/5); end end endmodule