How to simulate circuit of logic gates and flipflops

1.1k Views Asked by At

I'm currently learning C# and WPF, and i'm trying to simulate a circuit of logic gates and flipflops, but it won't work.

Could someone please show me a possible way to achive this? (maybe a simple similar application?)

What i have tried so far:


Class:

    public class GateBase
    {
        public Type Type { get; set; }
        public GateBase Input1 { get; set; }
        public GateBase Input2 { get; set; }
        public List<GateBase> Outputs { get; set; }
        public bool Evaluated { get; set; }
        public bool Value { get; set; }
        public bool FlipFlop { get; set; }

        public GateBase(Type type = Type.OFF, Gate input1 = null, Gate input2 = null)
        {
            Type = type;
            Input1 = input1;
            Input2 = input2;
            Outputs = new List<GateBase>();
            Evaluated = false;
            Value = false;
            

            FlipFlop = false;

            switch (Type)
            {
                case Type.T:
                case Type.D:
                case Type.SR:
                case Type.JK: FlipFlop = true; break;
            }
        }

        public bool Evaluate()
        {
            if (!Evaluated)
            {
                bool input1 = false;
                bool input2 = false;

                if (Input1 != null)
                {
                    if (Input1.FlipFlop)
                        input1 = Input1.Value;
                    else
                        input1 = Input1.Evaluate();
                }

                if (Input2 != null)
                {
                    if (Input2.FlipFlop)
                        input2 = Input2.Value;
                    else
                        input2 = Input2.Evaluate();
                }

                switch (Type)
                {
                    case Type.OFF:
                        Value = false; break;
                    case Type.ON:
                        Value = true; break;
                    case Type.OUT:
                        Value = input1; break;
                    case Type.CON:
                        Value = input1; break;
                    case Type.NOT:
                        Value = input1; break;
                    case Type.AND:
                        Value = input1 & input2; break;
                    case Type.OR:
                        Value = input1 | input2; break;
                    case Type.XOR:
                        Value = input1 ^ input2; break;
                    case Type.NAND:
                        Value = !(input1 & input2); break;
                    case Type.NOR:
                        Value = !(input1 | input2); break;
                    case Type.XNOR:
                        Value = !(input1 ^ input2); break;
                    case Type.D:
                        Value = input1; break;
                    case Type.T:
                        Value = input1 ? Value : !Value; break;
                    case Type.SR:
                        Value = (input1 ^ input2) ? Value : Value; break;
                    case Type.JK:
                        Value = (input1 ^ input2) ? input1 : (input1 & input2) ? !Value : Value; break;
                    default: Value = false; break;
                }
            }
            Evaluated = true;
            return Value;
        }

        public void ResetOutputs()
        {
            Evaluated = false;
            foreach (Gate gate in Outputs)
            {
                if(!gate.FlipFlop)
                {
                    gate.ResetOutputs();
                }
            }
        }
    }

Loop:

  • Update all logic gates
  • Update all flipflops and unevaluate outputs of each flipflop (if they are not a flipflop)
     public List<GateBase> Gates { get; set; }
     while (loop)
            {
                bool evaluating = true;
                while (evaluating)
                {
                    evaluating = false;
                    foreach (Gate gate in Gates)
                    {
                        switch (gate.Type)
                        {
                            case Model.Type.ON:
                            case Model.Type.OFF:
                                gate.Value = gate.Evaluate();
                                break;
                            case Model.Type.OUT:
                            case Model.Type.CON:
                            case Model.Type.NOT:
                                if (gate.Input1 != null && (gate.Input1.Evaluated || gate.Input1.FlipFlop))
                                {
                                    gate.Value = gate.Evaluate();
                                }
                                break;
                            case Model.Type.AND:
                            case Model.Type.OR:
                            case Model.Type.XOR:
                            case Model.Type.NAND:
                            case Model.Type.NOR:
                            case Model.Type.XNOR:
                                if (gate.Input1 != null && gate.Input2 != null)
                                {
                                    if ((gate.Input1.Evaluated || gate.Input1.FlipFlop) && (gate.Input2.Evaluated || gate.Input2.FlipFlop))
                                    {
                                        gate.Value = gate.Evaluate();
                                    }
                                }
                                else
                                {
                                    evaluating = true;
                                }
                                break;
                        }
                    }
                }

                evaluating = true;
                while (evaluating)
                {
                    evaluating = false;
                    foreach (Gate gate in Gates)
                    {
                        switch (gate.Type)
                        {
                            case Model.Type.D:
                            case Model.Type.T:
                                if (gate.Input1 != null && (gate.Input1.Evaluated || gate.Input1.FlipFlop))
                                {
                                    gate.Value = gate.Evaluate();
                                    gate.ResetOutputs();
                                }
                                else
                                {
                                    evaluating = true;
                                }
                                break;
                            case Model.Type.SR:
                            case Model.Type.JK:
                                if (gate.Input1 != null && gate.Input2 != null)
                                {
                                    if ((gate.Input1.Evaluated || gate.Input1.FlipFlop) && (gate.Input2.Evaluated || gate.Input2.FlipFlop))
                                    {
                                        gate.Value = gate.Evaluate();
                                        gate.ResetOutputs();
                                    }
                                }
                                else
                                {
                                    evaluating = true;
                                }
                                break;

                        }
                    }
                }
            }

Problem:

If i'm using the JK-flipflop the results are not as expected. (but the T-flipflop works fine)


Here a link to the solution: Solution on GitHub

Thank You!

2

There are 2 best solutions below

1
bintreedev On

You have no break for your switch cases inside the while loop, so if the case is Model.Type.AND it will fall all the way down to the Model.Type.XNOR and I assume this isn't intended. This might be your problem (or at least a part of it).

Just to give you an idea, this small example will output "no break". x = 3 will output the string from default.

using System;

public class Program
{
    public static void Main()
    {
        int x = 1;
        switch(x){
            case 0:
                Console.WriteLine("Break");
                break;
            case 1:
            case 2:
                Console.WriteLine("no break");
                break;
            case 3:
            default:
                Console.WriteLine("End!");
                break;
        }
    }
}

You can read more about the traditional switch here: switch C# reference from Micrsoft

0
AudioBubble On

Now i fixed a problem and it's working much better than before. (i was resetting the gates before all flipflops were updated)

But it's still not working 100% correct...

Changes in the Loop:

// new list
List<Gate> gatesToResetOutputs = new List<Gate>();

while(loop)
{
    while(evaluating gates)
    {
        ...
    }

    while(evaluating flipflops)
    {
        ...
        // instead of
        gate.ResetOutputs();
    
        // replace with
        gatesToResetOutputs.Add(gate);
        ...
    }

    // and at the end of the loop
    foreach(Gate gate in gatesToResetOutputs)
    {
        gate.ResetOutputs();
    }
}