Programming a ripple counter in C with JK flip flops

4.3k views Asked by At

I've decided to have a go at programming flip flops in C. I've had an attempt at both a D and JK flip flop (without preset and clear sections yet).

I'm testing if by cascading them, I can get them to produce a simple 4 bit ripple counter. After writing my code and running it, it seems to produce some really weird results in the form of:

Clk: 01010101010101010101

OuA: 01100110011001100110

OuB: 01000100010001000100

OuC: 01111000011110000111

OuD: 01010000010100000101

Where Clk is the input clock, OuA is output A, OuB, output B etc. As you can see, OuA and OuC seem somewhat acceptable with the ratio of on to off but B and D seem really odd!

My code is:

#include <stdio.h>
#include <stdlib.h>

void DFF(int Clk, int D, int *Q, int *NQ)
{
    if(Clk)
    {
        *Q = D;
        *NQ = !*Q;
    }
}

void JKF(int Clk, int J, int K, int *Q, int *NQ)
{
    if(Clk&J&(!K))
    {
        *Q = 1;
        *NQ = 0;
    }
    if(Clk&K&(!J))
    {
        *Q = 0;
        *NQ = 1;
    }
    if(Clk&J&K)
    {
        *Q = *NQ;
        *NQ = !*Q;
    }
}

int main()
{
    FILE *fptr;
    const int Len = 20;
    int Clk = 1, ClkA[Len];
    int n, OA[Len], OB[Len], OC[Len], OD[Len];
    int Q = 0, NQ = 1;
    int Q2 = 0, NQ2 = 1;
    int Q3 = 0, NQ3 = 1;
    int Q4 = 0, NQ4 = 1;

    for(n=0; n<Len; n++)
    {
        Clk^=1;

        JKF(Clk, 1, 1, &Q, &NQ);
        JKF(Q, 1, 1, &Q2, &NQ2);
        JKF(Q2, 1, 1, &Q3, &NQ3);
        JKF(Q3, 1, 1, &Q4, &NQ4);

        ClkA[n] = Clk;
        OA[n] = Q;
        OB[n] = Q2;
        OC[n] = Q3;
        OD[n] = Q4;
    }

    fptr = fopen("c:/ff.txt", "w");

    fprintf(fptr, "Clk: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", ClkA[n]);
    fprintf(fptr, "\nOuA: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OA[n]);
    fprintf(fptr, "\nOuB: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OB[n]);
    fprintf(fptr, "\nOuC: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OC[n]);
    fprintf(fptr, "\nOuD: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OD[n]);

    fclose(fptr);

    return 0;
}

I apologise about the clarity and I know its probably not particularly efficient but could someone please clear up what is happening with the outputs?

Cheers!

2

There are 2 answers

0
Duleeka Gunatilake On BEST ANSWER

According to the implementation of function JKF, it is level triggered rather than edge triggered.

Clk: 010

OuA: 011

OuB: 010

At the third clock transition, the OuA is still '1'. Hence JKF(Q, 1, 1, &Q2, &NQ2); toggles OuB to logic 0.

The transition of clock has to be considered rather than the current level of Clock in JKF function implementation.

As as simple remedy, the for loop can be changed as follows to take the clock transition into account.

for(n=0; n<Len; n++)
{
    Clk^=1;

    JKF(Clk, 1, 1, &Q, &NQ);
    if (n > 0)
    {
        if (OA[n -1] != Q)
        {
            JKF(Q, 1, 1, &Q2, &NQ2);
        }

        if (OB[n -1] != Q2)
        {
            JKF(Q2, 1, 1, &Q3, &NQ3);
        }

        if (OC[n -1] != Q3)
        {
            JKF(Q3, 1, 1, &Q4, &NQ4);
        }
    }
    else
    {
        JKF(Q, 1, 1, &Q2, &NQ2);
        JKF(Q2, 1, 1, &Q3, &NQ3);
        JKF(Q3, 1, 1, &Q4, &NQ4);
    }


    ClkA[n] = Clk;
    OA[n] = Q;
    OB[n] = Q2;
    OC[n] = Q3;
    OD[n] = Q4;
}
1
Duleeka Gunatilake On

A slightly improved version....

#include <stdio.h>
#include <stdlib.h>

typedef struct _JKFF
{
    int clk;
    int q;
    int nq;
}JKFF;


void JKFFn(int Clk, int J, int K, _JKFF * jkff)
{
    if ((Clk != jkff->clk) && !Clk)
    {   //Triggering FF on the falling edge
        if(J& (!K))
        {
            jkff->q = 1;
        }
        if(K &(!J))
        {
            jkff->q = 0;
        }
        if(J & K)
        {
            jkff->q = !jkff->q;
        }
        jkff->nq = !jkff->q;
    }
    jkff->clk = Clk;
}


int main()
{
    FILE *fptr;
    const int Len = 80;
    int Clk = 1, ClkA[Len];
    int n, OA[Len], OB[Len], OC[Len], OD[Len];

    _JKFF jkff[4];
    memset(jkff, 0, sizeof(jkff));

    for(n=0; n<Len; n++)
    {
        Clk^=1;

        JKFFn(Clk, 1, 1, &jkff[0]);
        JKFFn(jkff[0].q, 1, 1, &jkff[1]);
        JKFFn(jkff[1].q, 1, 1, &jkff[2]);
        JKFFn(jkff[2].q, 1, 1, &jkff[3]);

        ClkA[n] = Clk;
        OA[n] = jkff[0].q;
        OB[n] = jkff[1].q;
        OC[n] = jkff[2].q;
        OD[n] = jkff[3].q;
    }

    fptr = fopen("ff.txt", "w");

    fprintf(fptr, "Clk: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", ClkA[n]);
    fprintf(fptr, "\nOuA: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OA[n]);
    fprintf(fptr, "\nOuB: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OB[n]);
    fprintf(fptr, "\nOuC: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OC[n]);
    fprintf(fptr, "\nOuD: ");
    for(n = 0; n<Len; n++) fprintf(fptr, "%d", OD[n]);

    fclose(fptr);

    return 0;
}