/* a simple DLL simulation in irsim */ #include #include "subckt.h" uptr flop_func(); uptr flop_init(); uptr dll_init(); uptr dll(); #define DEBUG 0 #define printf if (DEBUG) printf userSubCircuit subs[] = { { "flop", flop_func, flop_init }, { "dll", dll, dll_init }, { NULL, NULL, NULL } }; typedef struct _flopState { int prvClk ; int Q ; } flopState; uptr flop_init() { flopState *thisFlop = (flopState *)malloc(sizeof(flopState)); thisFlop->prvClk = HIGH ; thisFlop->Q = X ; return (uptr) thisFlop; } uptr flop_func( ins, outs, delay, data ) char *ins, *outs; double *delay; uptr *data; { flopState *ff = (flopState *)data ; if ( ff->prvClk == LOW && ins[1] == HIGH ) { printf("flop edge @ %.2fns\n", d2ns( cur_delta )); ff->Q = ins[0]; } delay[0] = 100.0 ; ff->prvClk = ins[1]; outs[0] = ff->Q; } typedef struct _dll_state { double chpmpV; /* the charge pump voltage */ int prvClk; } dll_state ; #define RAIL 3.3 /* rail of the charge pump 0 - 3.3 */ #define UDPULSE 2e-9 /* 2ns pulse */ #define CHPMP_I 100e-6 /* 100 uA chpmp current */ #define PMP_CAP 20e-12 /* 10 pf filter cap */ #define CHGPCKT (CHPMP_I*UDPULSE/PMP_CAP) /* charge packet */ uptr dll_init() { dll_state *t = (dll_state *)malloc(sizeof(dll_state)); t->chpmpV = 0.0 ; t->prvClk = LOW ; return (uptr) t; } #define DLY0 2800.0 /* 1.8ns start delay */ #define DLYSLOPE 1000.0 /* 1.0ns/V dline gain */ #define DLINE_TF(V) (DLY0+DLYSLOPE*(V)) uptr dll( in, out, delay, data ) char *in, *out; double *delay; uptr *data; #define clkOut (out[0]) { dll_state *d = (dll_state *)data ; char updn = in[0], clkIn = in[1], clkOutFb = in[2]; printf("dll called @ %.2fns voltage %lf \n", d2ns( cur_delta ), d->chpmpV); printf("\t updn=%c clkin=%c clkOutFb=%c prevClk=%c\n", pot2char[updn], pot2char[clkIn], pot2char[clkOutFb], pot2char[d->prvClk]); delay[0] = DLINE_TF(d->chpmpV); clkOut = clkIn; if ( d->prvClk == LOW && clkOutFb == HIGH ) { d->chpmpV += (updn == HIGH) ? CHGPCKT : -CHGPCKT ; printf("pumping %s @ %.2fns voltage %le\n", (updn == LOW) ? "up" : "dn", d2ns( cur_delta ), d->chpmpV); } d->prvClk = clkOutFb ; }