Okay, simulating the analog parts of the actual physical ring oscillator last night made me ask some questions, so I thought it might be useful to try a very simple discrete simulation. If you looked at the schematic I posted yesterday, you’ll note that the ring is really just made up of single transistor inverters. The capacitors in combination with the resistors implement a delay line. So, that’s what I decided to code up: a ring of simple inverters, each with a “gate delay” of values which are very close to 1 second. Whenever the input to the inverter is scheduled, the output is swapped to its negation at the time in the future plus its gate delay, which resets the clock of the next gate, and so on. I normally would use a priority queue and the like to keep track of which gate should fire next, but for as few stages as I’m likely to implement, I frankly just search for the gate with the lowest time by linear search, and then proceed. To make the “simulation” a tiny bit more interesting, I print the values of the gates in “pseudo-real” time (I spend it up by a factor of 10). Here’s the code.
[sourcecode lang=”C”]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define N 79
unsigned char val[N] ;
double delay[N] ;
double clock[N] ;
#define BIG 1e6
main()
{
int i, idx ;
double t = 0., soonest ;
for (i=0; i<N; i++) {
val[i] = 0 ;
delay[i] = clock[i] = 1.0 + drand48() * 0.01 – 0.005 ;
}
for (;;) {
/* find the inverter that will trip soonest */
idx = 0 ;
soonest = clock[idx] ;
for (i=1; i<N; i++)
if (clock[i] < soonest) {
soonest = clock[i] ;
idx = i ;
}
/* subtract the clock from all the inputs */
for (i=0; i<N; i++)
clock[i] -= soonest ;
t += soonest ;
val[(idx+1)%N] = 1-val[idx] ;
clock[(idx+1)%N] = delay[(idx+1)%N] ;
clock[idx] = BIG ;
usleep(soonest * 1000000. / 10.) ;
for (i=0; i<N; i++)
putchar("_X"[val[i]]) ;
printf("\r") ;
fflush(stdout) ;
}
}
[/sourcecode]
It’s pretty interesting to watch (at least to me). I’ll have more to comment tonight.