This is the low level flash driver. It has some stuff at the top of the cpp file that lets me see the pins states. I originally planned to use the Arduino LED blinking to know what was going on. The use of the serial port is much better.

Right now the diagnostic code is made of functions living in the file aren’t part of the class. I’ll change that going forward, or I’ll remove it.

But, for now, the code seems to work.

 1 #ifndef INCLUDE_FLASHLOW
 2 #define INCLUDE_FLASHLOW
 3 #include <Arduino.h>
 4 
 5 class FlashLow
 6 {
 7 public:
 8     FlashLow();
 9 
10     // Setsw the input/output pin mode
11     void EnablePins(bool enable);
12 
13     // Resets the CPLD
14     bool Reset();
15 
16     // Write data to *ptr.
17     // NOTE: This is a NOT toggle bit operation, just sends data to *ptr
18     // returns true if successful
19     void Write(long ptr, byte data);
20 
21     // Read data at *ptr into *pData
22     // returns true if successful
23     void Read(long, byte* pData);
24 
25     // Force update of all address bits
26     void UpdateAddress(long addr);
27 
28     // Update address bits only on parts that are different
29     void UpdateAddressDiff(long addr);
30 
31     // Update address bits 3:0
32     void UpdateAddress_3_0(long addr);
33 
34     // Update address bits 7:4
35     void UpdateAddress_7_4(long addr);
36 
37     // Update address bits 17:8
38     void UpdateAddress_17_8(long addr);
39 
40     // Update chip control where bits 3-0 are drive, CS*, WR*, and RD*
41     void UpdateChip(int chip);
42 
43     // Update the CTRL register that tells which register to pulse data in and out
44     void UpdateCtrl(int ctrl);
45 
46     // Swaps a data byte on Din/Dout
47     byte ReadWrite(byte data);
48 
49     // Pulse CLK high and low
50     void PulseClk();
51 
52     // Pulse nCTRL low and high
53     void PulseCtrl();
54 
55     // Control pins directly
56     void DirectWrite(bool enable, bool clk, bool din, bool ctrl);
57     void DirectRead(bool* enable, bool* clk, bool* din, bool* dout, bool* ctrl);
58 
59     // Reads until the toggle bits stop toggling
60     // Returns true if the read data matches expected
61     // Use expected of 0xff for erase operations
62     bool Toggle(byte expected);
63 
64     // Send CPLD reset sequence
65     void ResetSequence();
66 
67 private:
68     // Update an arbitrary part of the address bits
69     void UpdateAddress_start_end(long addr, int startBit, int endBit);
70 
71     int m_lastAddr;
72 
73 public:
74     static const int PIN_nCTRL = 
75     static const int PIN_Dout = 3;
76     static const int PIN_Din = 4;
77     static const int PIN_CLK = 5;
78     static const int PIN_ENABLE = 6;
79 };
80 
81 #endif

Here is the cpp part:

  1 #include "flashLow.h"
  2 
  3 //#define SUPER_SLO_MO() delay(1000)
  4 #define SUPER_SLO_MO() SendOutPins()
  5 
  6 void SendOutPins()
  7 {
  8     byte progress[10] = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  9 
 10     progress[1] =
 11         (digitalRead(FlashLow::PIN_ENABLE) ? 0x01 : 0) |
 12         (digitalRead(FlashLow::PIN_nCTRL) ? 0x02 : 0) |
 13         (digitalRead(FlashLow::PIN_CLK) ? 0x04 : 0) |
 14         (digitalRead(FlashLow::PIN_Din) ? 0x08 : 0) |
 15         (digitalRead(FlashLow::PIN_Dout) ? 0x10 : 0);
 16     Serial.write(progress, 10);
 17 
 18     delay(250);
 19 }
 20 
 21 void BlinkOutPins()
 22 {
 23     digitalWrite(13, HIGH);
 24     delay(1000);
 25     digitalWrite(13, LOW);
 26     delay(1000);
 27 
 28     if (digitalRead(FlashLow::PIN_ENABLE))
 29     {
 30         digitalWrite(13, HIGH);
 31         delay(500);
 32         digitalWrite(13, LOW);
 33         delay(500);
 34     }
 35     else
 36     {
 37         digitalWrite(13, HIGH);
 38         delay(250);
 39         digitalWrite(13, LOW);
 40         delay(250);
 41         digitalWrite(13, HIGH);
 42         delay(250);
 43         digitalWrite(13, LOW);
 44         delay(250);
 45     }
 46 
 47     delay(1000);
 48     if (digitalRead(FlashLow::PIN_nCTRL))
 49     {
 50         digitalWrite(13, HIGH);
 51         delay(500);
 52         digitalWrite(13, LOW);
 53         delay(500);
 54     }
 55     else
 56     {
 57         digitalWrite(13, HIGH);
 58         delay(250);
 59         digitalWrite(13, LOW);
 60         delay(250);
 61         digitalWrite(13, HIGH);
 62         delay(250);
 63         digitalWrite(13, LOW);
 64         delay(250);
 65     }
 66 
 67     delay(1000);
 68     if (digitalRead(FlashLow::PIN_CLK))
 69     {
 70         digitalWrite(13, HIGH);
 71         delay(500);
 72         digitalWrite(13, LOW);
 73         delay(500);
 74     }
 75     else
 76     {
 77         digitalWrite(13, HIGH);
 78         delay(250);
 79         digitalWrite(13, LOW);
 80         delay(250);
 81         digitalWrite(13, HIGH);
 82         delay(250);
 83         digitalWrite(13, LOW);
 84         delay(250);
 85     }
 86 
 87     delay(1000);
 88     if (digitalRead(FlashLow::PIN_Din))
 89     {
 90         digitalWrite(13, HIGH);
 91         delay(500);
 92         digitalWrite(13, LOW);
 93         delay(500);
 94     }
 95     else
 96     {
 97         digitalWrite(13, HIGH);
 98         delay(250);
 99         digitalWrite(13, LOW);
100         delay(250);
101         digitalWrite(13, HIGH);
102         delay(250);
103         digitalWrite(13, LOW);
104         delay(250);
105     }
106 
107     delay(1000);
108     if (digitalRead(FlashLow::PIN_Dout))
109     {
110         digitalWrite(13, HIGH);
111         delay(500);
112         digitalWrite(13, LOW);
113         delay(500);
114     }
115     else
116     {
117         digitalWrite(13, HIGH);
118         delay(250);
119         digitalWrite(13, LOW);
120         delay(250);
121         digitalWrite(13, HIGH);
122         delay(250);
123         digitalWrite(13, LOW);
124         delay(250);
125     }
126 
127     delay(1000);
128 }
129 
130 FlashLow::FlashLow()
131 {
132     m_lastAddr = -1;
133 }
134 
135 void FlashLow::EnablePins(bool enable)
136 {
137     if (enable)
138     {
139         pinMode(PIN_ENABLE, OUTPUT);
140         pinMode(PIN_nCTRL, OUTPUT);
141         pinMode(PIN_Dout, INPUT);
142         pinMode(PIN_Din, OUTPUT);
143         pinMode(PIN_CLK, OUTPUT);
144     }
145     else
146     {
147         pinMode(PIN_ENABLE, INPUT_PULLUP);
148         pinMode(PIN_nCTRL, INPUT_PULLUP);
149         pinMode(PIN_Dout, INPUT);
150         pinMode(PIN_Din, INPUT_PULLUP);
151         pinMode(PIN_CLK, INPUT_PULLUP);
152     }
153 
154 }
155 
156 void FlashLow::Write(long addr, byte data)
157 {
158     UpdateAddressDiff(addr);
159     ReadWrite(data);
160 
161     UpdateChip(0x1); // drive, CS, WR
162     UpdateChip(0x3); // drive, CS
163     UpdateChip(0xf); // done
164 }
165 
166 void FlashLow::Read(long addr, byte* pData)
167 {
168     UpdateAddressDiff(addr);
169     *pData = ReadWrite(0);
170 }
171 
172 void FlashLow::UpdateAddressDiff(long addr)
173 {
174     if (m_lastAddr == -1)
175     {
176         UpdateAddress(addr);
177     }
178     else
179     {
180         long diffs = (addr ^ m_lastAddr);
181         if ((diffs & 0x0000f) != 0)
182         {
183             UpdateAddress_3_0(addr);
184         }
185         if ((diffs & 0x000f0) != 0)
186         {
187             UpdateAddress_7_4(addr);
188         }
189         if ((diffs & 0xfff00) != 0)
190         {
191             UpdateAddress_17_8(addr);
192         }
193 
194         m_lastAddr = addr;
195     }
196 }
197 
198 void FlashLow::UpdateAddress(long addr)
199 {
200     UpdateAddress_3_0(addr);
201     UpdateAddress_7_4(addr);
202     UpdateAddress_17_8(addr);
203     m_lastAddr = addr;
204 }
205 
206 void FlashLow::UpdateAddress_start_end(long addr, int endBit, int startBit)
207 {
208     int i;
209     for (i = startBit; i <= endBit; ++i)
210     {
211         long mask = 1L << i;
212         m_lastAddr &= ~mask;
213         m_lastAddr |= (mask & addr);
214         digitalWrite(PIN_Din, (addr & (1L << i)) ? HIGH : LOW);
215         SUPER_SLO_MO();
216         PulseClk();
217     }
218 }
219 
220 void FlashLow::UpdateAddress_3_0(long addr)
221 {
222     UpdateCtrl(0x01);
223     UpdateAddress_start_end(addr, 3, 0);
224 }
225 
226 void FlashLow::UpdateAddress_7_4(long addr)
227 {
228     UpdateCtrl(0x02);
229     UpdateAddress_start_end(addr, 7, 4);
230 }
231 
232 void FlashLow::UpdateAddress_17_8(long addr)
233 {
234     UpdateCtrl(0x03);
235     UpdateAddress_start_end(addr, 17, 8);
236 }
237 
238 void FlashLow::UpdateChip(int chip)
239 {
240     int i;
241     UpdateCtrl(0x07);
242     for (i = 0; i < 4; ++i)
243     {
244         digitalWrite(PIN_Din, (chip & 1) ? HIGH : LOW);
245         SUPER_SLO_MO();
246         PulseClk();
247         chip >>= 1;
248     }
249     PulseCtrl();
250 }
251 
252 void FlashLow::UpdateCtrl(int ctrl)
253 {
254     int i;
255     digitalWrite(PIN_nCTRL, LOW);
256     SUPER_SLO_MO();
257     for (i = 0; i < 3; ++i)
258     {
259         int bit = ctrl & 1;
260         ctrl = ctrl >> 1;
261         digitalWrite(PIN_Din, bit ? HIGH : LOW);
262         SUPER_SLO_MO();
263         PulseClk();
264     }
265     digitalWrite(PIN_nCTRL, HIGH);
266     SUPER_SLO_MO();
267 }
268 
269 byte FlashLow::ReadWrite(byte data)
270 {
271     int i;
272     byte outData = 0;
273     UpdateCtrl(0x00);
274     for (i = 0; i < 8; ++i)
275     {
276         if (digitalRead(PIN_Dout) == HIGH)
277         {
278             outData |= 0x80;
279         }
280         digitalWrite(PIN_Din, (data & 1) ? HIGH : LOW);
281         SUPER_SLO_MO();
282         PulseClk();
283         outData >>= 1;
284         data >>= 1;
285     }
286     return outData;
287 }
288 
289 bool FlashLow::Toggle(byte expected)
290 {
291     bool toggling = true;
292     byte data0;
293     byte data1;
294     Read(m_lastAddr, &data0);
295     while (toggling)
296     {
297         Read(m_lastAddr, &data1);
298         if ((data1 ^ data0) & 0x40)
299         {
300             // toggle bit toggling
301             data0 = data1; // set up for next toggle check
302         }
303         else
304         {
305             toggling = false;
306         }
307     }
308     return data1 == expected;
309 }
310 
311 void FlashLow::PulseClk()
312 {
313     digitalWrite(PIN_CLK, HIGH);
314     SUPER_SLO_MO();
315     digitalWrite(PIN_CLK, LOW);
316     SUPER_SLO_MO();
317 }
318 
319 void FlashLow::PulseCtrl()
320 {
321     digitalWrite(PIN_nCTRL, LOW);
322     SUPER_SLO_MO();
323     digitalWrite(PIN_nCTRL, HIGH);
324     SUPER_SLO_MO();
325 }
326 
327 void FlashLow::ResetSequence()
328 {
329     m_lastAddr = -1;
330 
331     // initialize pins before setting output mode
332     digitalWrite(PIN_ENABLE, HIGH);
333     digitalWrite(PIN_CLK, HIGH);
334     digitalWrite(PIN_nCTRL, HIGH);
335     digitalWrite(PIN_Din, HIGH);
336 
337     // set pin modes
338     pinMode(PIN_ENABLE, OUTPUT);
339     pinMode(PIN_nCTRL, OUTPUT);
340     pinMode(PIN_Dout, INPUT);
341     pinMode(PIN_Din, OUTPUT);
342     pinMode(PIN_CLK, OUTPUT);
343 
344     // Execute reset sequence
345     PulseClk();
346     PulseClk();
347     digitalWrite(PIN_nCTRL, LOW);
348     PulseClk();
349     PulseClk();
350     PulseClk();
351     digitalWrite(PIN_nCTRL, HIGH);
352     SUPER_SLO_MO();
353     digitalWrite(PIN_ENABLE, LOW);
354     SUPER_SLO_MO();
355 }
356 
357 void FlashLow::DirectWrite(bool enable, bool clk, bool din, bool ctrl)
358 {
359     digitalWrite(PIN_ENABLE, enable ? (HIGH) : (LOW));
360     digitalWrite(PIN_CLK, clk ? (HIGH) : (LOW));
361     digitalWrite(PIN_Din, din ? (HIGH) : (LOW));
362     digitalWrite(PIN_nCTRL, ctrl ? (HIGH) : (LOW));
363 }
364 
365 void FlashLow::DirectRead(bool* enable, bool* clk, bool* din, bool* dout, bool* ctrl)
366 {
367     *enable = digitalRead(PIN_ENABLE) == HIGH;
368     *clk = digitalRead(PIN_CLK) == HIGH;
369     *din = digitalRead(PIN_Din) == HIGH;
370     *dout = digitalRead(PIN_Dout) == HIGH;
371     *ctrl = digitalRead(PIN_nCTRL) == HIGH;
372 }

And just to refresh, here is the code part of the Verilog for the CPLD:

 1 `define ACTIVELOW 1'b0
 2 `define ACTIVEHIGH 1'b1
 3 
 4 module flashProgrammer(
 5     input pin_ENABLE,
 6     input pin_CLK,
 7     input pin_Din,
 8     input pin_nCTRL,
 9     output reg pin_Dout,
10 
11     output [17:0] pins_A,
12     output pin_nWR, 
13     output pin_nRD,
14     output pin_nCS,
15     inout [7:0] pins_D
16     );
17 
18     reg [2:0] ctrlReg;
19     reg [7:0] dataReg;
20     reg [17:0] addrReg;
21     reg [3:0] chipReg;
22     wire nOE;
23 
24     reg nRDint;
25     reg nWRint;
26     reg nCSint;
27     reg nOEint;
28 
29     assign pin_nRD = !pin_ENABLE ? nRDint : 1'bz;
30     assign pin_nWR = !pin_ENABLE ? nWRint : 1'bz;
31     assign pin_nCS = !pin_ENABLE ? nCSint : 1'bz;
32     assign nOE = nOEint | pin_ENABLE;
33 
34     assign pins_D = (nOE==`ACTIVELOW && pin_ENABLE==`ACTIVELOW && pin_nRD==1'b1) ? dataReg : 8'bzzzzzzzz;
35     assign pins_A = (pin_ENABLE == `ACTIVELOW) ? addrReg : 18'bzzzzzzzzzzzzzzzzzz;
36 
37     always @(posedge pin_nCTRL) begin
38         // Strobe out of the chip
39         nRDint <= chipReg[0];
40         nWRint <= chipReg[1];
41         nCSint <= chipReg[2];
42         nOEint <= chipReg[3];
43     end
44 
45     always @(posedge pin_CLK) begin
46 
47         if (pin_nCTRL == `ACTIVELOW) begin
48 
49             // clocking in control
50             pin_Dout <= ctrlReg[0];
51             ctrlReg <= {pin_Din, ctrlReg[2:1]}; 
52 
53             if (pin_ENABLE == 1'b1) begin
54                 chipReg <= 4'b1111;
55             end
56         end
57         else begin
58             case (ctrlReg)
59                 3'b000 : begin
60                     pin_Dout <= dataReg[0];
61                     dataReg <= { pin_Din, dataReg[7:1]};
62                 end
63                 3'b001 : begin
64                     pin_Dout <= addrReg[0];
65                     addrReg[3:0] <= { pin_Din, addrReg[3:1]};
66                 end
67                 3'b010 : begin
68                     pin_Dout <= addrReg[4];
69                     addrReg[7:4] <= { pin_Din, addrReg[7:5]};
70                 end
71                 3'b011 : begin
72                     pin_Dout <= addrReg[8];
73                     addrReg[17:8] <= { pin_Din, addrReg[17:9]};
74                 end
75                 3'b100 : begin
76                 end
77                 3'b101 : begin
78                 end
79                 3'b110 : begin
80                 end
81                 3'b111 : begin
82                     pin_Dout <= chipReg[0];
83                     chipReg <= { pin_Din, chipReg[3:1]};
84                     // If reading, read now
85                     if ((pin_nRD | nOE) == `ACTIVELOW) begin
86                         dataReg <= pins_D;
87                     end
88                 end
89             endcase
90         end
91     end
92 
93 endmodule

BTW, this has the bug fix described in the previous post. The actual CPLD I have doesn’t update Dout properly while shifting ctrlReg.