Simulating a (simplified) Ring Oscillator

January 5, 2011 | Amateur Science, electronics, Games and Diversions | By: Mark VandeWettering

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.

#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) ;


    }
}

It’s pretty interesting to watch (at least to me). I’ll have more to comment tonight.

Share Button
Be Sociable, Share!

Comments

Comment from Alan Yates
Time 1/9/2011 at 5:59 am

Mark,

This simulation is very interesting, in particular how a small region of alternating values seems to propagate backwards against the rest of the flow of the pattern.

I have some old java code for simulating arbitrary automata that I had planned to rewrite to support more continuous time simulations, but alas other ideas consumed the weekend. Hopefully I’ll get around to it this coming week.

Like yourself I want to do more software study, especially of cross-connected loops and bifurcated chains of simple stages like this, and eventually build them in hardware. I dug through the old capacitor box today and found a large cache of 470 uF and 10 uF capacitors, combined with other devices I have in bulk just itching for some use I think this will be a great way to give them some life beyond drying out in my junkbox.

Regards,
Alan

Write a comment