#include <stdio.h> #include <stdlib.h> // GAL22V10 Simulator /* Looks like I have a design flaw below. I thought each OLMCC was simply the AND of multiple inputs. In fact it is the OR of multiple ANDs of the inputs: 7. Note the number of possible input equation values that use the OR statement for the output pins varies a lot. They are as follows:- Pins 23 & 14 = 8 (OR's) Pins 22 & 15 = 10 (OR's) Pins 21 & 16 = 12 (OR's) Pins 20 & 17 = 14 (OR's) Pins 18 & 19 = 16 (OR's) Remember the number of product terms indicated for each pin does not limit the AND statements, it limits only the number of OR statements. So... much more like a PLA than I thought! and explains the discrepancy in the number of gates I mention below! Now all I have to learn is wtf is Jedec, and how to translate the logic tables into Jedec format and output a .jed file... As I said in the README, this code is to help me understand better what is in a GAL. I may not even use it in the project (there are alternatives - PALASM for Windows and open source GALASM for Linux - which I didn't know about until most of the code below was written...) */ typedef unsigned char BIT; /* The input and I/O pins also have built-in active pull-ups. As a result, floating inputs will float to a TTL high (logic 1). However, Lattice Semiconductor recommends that all unused inputs and tri-stated I/O pins be connected to an adjacent active input, Vcc, or ground. Doing so will tend to improve noise immunity and reduce Icc for the device. */ typedef struct MASK { /* If the array element contains '1' then use that input in the calculation, otherwise ignore it. */ BIT Pin[24+1]; /* External pins on chip. (DIP Package) 1:24 */ BIT ES[64]; /* 64 User-programmable bits */ BIT Feedback_Low[10]; /* Feedback signal from all 10 OLMCCs */ BIT Feedback_High[10]; /* Inverted Feedback signal from all 10 OLMCCs */ } MASK; typedef struct OLMCC { MASK Use; BIT Output_Tristate_Control; BIT S0_Output_Active_High; BIT S1_No_Latch; int Max_In; /* How many inputs this OLMCC has */ BIT In[16]; /* (not all available) */ /* Outputs */ int Output_Pin; /* Number (1:24) of output pin for output value to be written to. */ BIT Feedback_Low; BIT Feedback_High; } OLMCC; /* The JEDEC map for the GAL22V10 contains the 64 extra fuses for the electronic signature, for a total of 5892 fuses. However, the GAL22V10 device can still be programmed with a standard 22V10 JEDEC map (5828 fuses) with any qualified device programmer. (GT: My data structure here contains nothing like 5828 bits - so what am I missing?) */ typedef struct Gal22V10 { BIT Pin[24+1]; /* External pins on chip. (DIP Package) 1:24 */ BIT ES[64]; /* 64 User-programmable bits */ BIT Q[10]; /* State of each latch (flip-flop) */ BIT Feedback_Low[10]; /* Feedback signal from all 10 OLMCCs */ BIT Feedback_High[10]; /* Inverted Feedback signal from all 10 OLMCCs */ OLMCC olmcc[10]; } Gal22V10; BIT NOT(BIT x) { return 1-x; } BIT MUX2(BIT Sel0, BIT Val0, BIT Val1) { switch (Sel0) { case 0: return Val0; case 1: return Val1; } } BIT MUX4(BIT Sel0, BIT Sel1, BIT Val0, BIT Val1, BIT Val2, BIT Val3) { switch ((Sel0<<1)|Sel1) { case 0: return Val0; case 1: return Val1; case 2: return Val2; case 3: return Val3; } } // These procedures are for converting the canonicalised input logic file // into specific settings for the GAL. They are used to define the chip, // not to simulate it. /* Pins 14, 23 - 8 terms */ void OLMCC8(int Pin, BIT Clk, BIT Output_Tristate_Control, BIT S0_Output_Active_High, BIT S1_No_Latch, BIT In0, BIT In1, BIT In2, BIT In3, BIT In4, BIT In5, BIT In6, BIT In7, BIT ES[64], /* Outputs */ BIT *Output_Pin, BIT *Feedback_Low, BIT *Feedback_High) { } /* Pins 15, 22 - 10 terms */ void OLMCC10(int Pin, BIT Clk, BIT Output_Tristate_Control, BIT S0_Output_Active_High, BIT S1_No_Latch, BIT In0, BIT In1, BIT In2, BIT In3, BIT In4, BIT In5, BIT In6, BIT In7, BIT In8, BIT In9, BIT ES[64], /* Outputs */ BIT *Output_Pin, BIT *Feedback_Low, BIT *Feedback_High) { } /* Pins 16, 21 - 12 terms */ void OLMCC12(int Pin, BIT Clk, BIT Output_Tristate_Control, BIT S0_Output_Active_High, BIT S1_No_Latch, BIT In0, BIT In1, BIT In2, BIT In3, BIT In4, BIT In5, BIT In6, BIT In7, BIT In8, BIT In9, BIT In10, BIT In11, BIT ES[64], /* Outputs */ BIT *Output_Pin, BIT *Feedback_Low, BIT *Feedback_High) { } /* Pins 17, 20 - 14 terms*/ void OLMCC14(int Pin, BIT Clk, BIT Output_Tristate_Control, BIT S0_Output_Active_High, BIT S1_No_Latch, BIT In0, BIT In1, BIT In2, BIT In3, BIT In4, BIT In5, BIT In6, BIT In7, BIT In8, BIT In9, BIT In10, BIT In11, BIT In12, BIT In13, BIT ES[64], /* Outputs */ BIT *Output_Pin, BIT *Feedback_Low, BIT *Feedback_High) { } /* Pins 18, 19 - 16 terms*/ void OLMCC16(int Pin, BIT Clk, BIT Output_Tristate_Control, BIT S0_Output_Active_High, BIT S1_No_Latch, BIT In0, BIT In1, BIT In2, BIT In3, BIT In4, BIT In5, BIT In6, BIT In7, BIT In8, BIT In9, BIT In10, BIT In11, BIT In12, BIT In13, BIT In14, BIT In15, BIT ES[64], /* Outputs */ BIT *Output_Pin, BIT *Feedback_Low, BIT *Feedback_High) { } void GAL22V10(BIT Clk, /* Inputs */ BIT Pin2, BIT Pin3, BIT Pin4, BIT Pin5, BIT Pin6, BIT Pin7, BIT Pin8, BIT Pin9, BIT Pin10, BIT GPin11, BIT Gnd, /* Input */ BIT Pin13, /* OLMCCs: Input/Output/Latch */ BIT Pin14, BIT Pin15, BIT Pin16, BIT Pin17, BIT Pin18, BIT Pin19, BIT Pin20, BIT Pin21, BIT Pin22, BIT Pin23, BIT Vcc) { } void Simulate(BIT Clk, Gal22V10 *Chip) { int i, Computed; for (i = 0; i < 10; i++) { int Pin, Olmcc, ESBit; Computed = 1; for (Pin = 1; Pin <= 24; Pin++) { // Software that sets up the 'Use' array only allows pins to be set that make sense. It would not // allow you to use Vcc or Gnd for example. #ifdef NEVER // An alternative formulation avoiding 'if' (to allow implemention in gates) would be: // If use this pin: Else: Computed = ( Chip->olmcc[i].Use.Pin[Pin] & Chip->Pin[Pin] & Computed ) | ( ~Chip->olmcc[i].Use.Pin[Pin] & Computed ) #else if (Chip->olmcc[i].Use.Pin[Pin]) { Computed &= Chip->Pin[Pin]; } #endif } for (ESBit = 0; ESBit < 64; ESBit++) { if (Chip->olmcc[i].Use.ES[ESBit]) { Computed &= Chip->ES[ESBit]; } } for (Olmcc = 0; Olmcc < 10; Olmcc++) { if (Chip->olmcc[i].Use.Feedback_High[Olmcc]) { if (Chip->olmcc[i].Use.Feedback_High[Olmcc] == i) { // quick check for simple feedback loop (unstable) fprintf(stderr, "Warning: feedback loop on OLMCC[%d] (Pin %d)\n", i, Chip->olmcc[i].Output_Pin); // Ideally we would perform a transitive closure to ensure no complex feedback loops. Later. } Computed &= Chip->Feedback_High[Olmcc]; } } for (Olmcc = 0; Olmcc < 10; Olmcc++) { if (Chip->olmcc[i].Use.Feedback_Low[Olmcc]) { if (Chip->olmcc[i].Use.Feedback_Low[Olmcc] == i) { fprintf(stderr, "Warning: feedback loop on OLMCC[%d] (Pin %d)\n", i, Chip->olmcc[i].Output_Pin); } Computed &= Chip->Feedback_Low[Olmcc]; } } // We now have the raw computed logic from the nand-gate array. // Is it latched? if (Chip->olmcc[i].S1_No_Latch) { if (!Chip->olmcc[i].S0_Output_Active_High) { // Is it inverted? (Feeds outout pin and feedback loop) Computed = NOT(Computed); } // Feedback signal and inverted signal: Chip->olmcc[i].Feedback_High = Computed; Chip->olmcc[i].Feedback_Low = NOT(Computed); } else { BIT Qbar; // Implement D-type flip-flop here. Q and Q' outputs. if (Clk) Chip->Q[i] = Computed; Qbar = NOT(Chip->Q[i]); Computed = MUX4(/* control */ Chip->olmcc[i].S0_Output_Active_High, Chip->olmcc[i].S1_No_Latch, /* inputs */ NOT(Computed), Computed, Chip->Q[i], Qbar); if (!Chip->olmcc[i].S0_Output_Active_High) { // Is it inverted? (Feeds output pin and feedback loop) // Diagrams in https://mil.ufl.edu/4712/docs/gal22v10.pdf are confusing/misleading // - I think this code (which follows the diagram) is double-inverting the output. Computed = NOT(Computed); } // Feedback signal and inverted signal: Chip->olmcc[i].Feedback_High = MUX2(/* control */ Chip->olmcc[i].S1_No_Latch, /* inputs */ Qbar, Computed); Chip->olmcc[i].Feedback_Low = NOT(Chip->olmcc[i].Feedback_High); } } } int main(int argc, char **argv) { Gal22V10 Max6809; const int Runtime = 2; int Clk; // FIRST DEFINE THE GAL. /* TO DO */ for (Clk = 0; Clk < Runtime; Clk++) { Simulate(Clk&1, &Max6809); } exit(EXIT_SUCCESS); return EXIT_FAILURE; }