Here is the verilog for the 4th CPLD that I figured out I need. It’s a 1ms timer. It will pull the interrupt pin low and return to Hi-Z mode when the interrupt is cleared by reading the tick counter. The tick counter is 3 bits and can be used to ensure some degree of consistency when late servicing the tick interrupt or when using shared interrupts (which I will do). It has a very small pin footprint. Just clock, read-only SPI, chip select, and the interrupt line. This one fits into the smaller M4A5-32/32 so I’ll use that.

  1 // This CPLD is a timer circuit that generates a 500Hz tick. It takes a 2MHz
  2 // clock in. Scales that down to 125MHz with a 4 bit counter.
  3 // Then it counts 125 of those in a 7 bit counter that resets on 7c.
  4 // When the reset occurs, the pin_nINT line goes from Hi-Z to low.
  5 //
  6 // The falling edge of pin_nCS pin brings pin_nINT back to Hi-Z.
  7 //
  8 // SCK and Dout are used to read the 3 bit tick counter. This is used
  9 // to ensure that the count is kept synched. Dout is updated on the
 10 // falling edge of SCK and the MSB is shifted first. 
 11 //
 12 
 13 
 14 module timer (
 15     input pin_CLK,
 16     input pin_nCS,
 17     input pin_SCK,
 18     output pin_Dout,
 19     output pin_nINT
 20     /*
 21     output [3:0] test_prescaler,
 22     output [6:0] test_counter,
 23     output [2:0] test_ticks,
 24     output [2:0] test_tickShift,
 25     output test_nCount,
 26     output test_nTick,
 27     output test_nInt,
 28     output test_nCS0,
 29     output test_nCS1
 30     */
 31     );
 32 
 33     /*
 34     assign test_prescaler = prescaler;
 35     assign test_counter = counter;
 36     assign test_ticks = ticks;
 37     assign test_tickShift = tickShift;
 38     assign test_nCount = nCount;
 39     assign test_nTick = nTick;
 40     assign test_nInt = nInt;
 41     assign test_nCS0 = nCS0;
 42     assign test_nCS1 = nCS1;
 43     */
 44 
 45     reg [3:0] prescaler;
 46     reg [6:0] counter;
 47     reg [2:0] ticks;
 48     reg [2:0] tickShift;
 49     reg nCount;
 50     reg nTick;
 51     reg nInt;
 52     reg nCS0;
 53     reg nCS1;
 54     reg SCK0;
 55     reg SCK1;
 56 
 57     initial begin
 58         prescaler = 0;
 59         counter = 0;
 60         ticks = 0;
 61     end
 62 
 63     assign pin_nINT = (nInt == 1'b1) ? 1'bz : 1'b0;
 64 
 65     always @(posedge pin_CLK) begin
 66         prescaler <= prescaler + 1;
 67         nCount <= ~(&prescaler); // 0 once every 16 pin_CLK
 68         nTick <= ~(counter == 7'b1111100); // 124 caused 125->0
 69         if (nCount == 1'b0) begin
 70             if (nTick == 1'b0) begin
 71                 counter <= 0;
 72                 ticks <= ticks+1;
 73             end
 74             else begin
 75                 counter <= counter+1;
 76             end
 77         end
 78 
 79         nCS0 <= pin_nCS;
 80         nCS1 <= nCS0;
 81 
 82         // Set interrupt on the CLK. Reset it on the falling edge of
 83         // pin_nCS+2 clocks
 84         if ((nTick | nCount) == 1'b0) begin
 85             nInt <= 1'b0; 
 86         end
 87         else if ((nCS1 & (~nCS0)) == 1'b1) begin
 88             nInt <= 1'b1; 
 89         end
 90 
 91         SCK0 <= pin_SCK;
 92         SCK1 <= SCK0;
 93         if (~pin_nCS) begin
 94             //if (SCK1 & ~SCK0) begin
 95             if (SCK0 & ~pin_SCK) begin
 96                 tickShift[2:0] <= { tickShift[1:0], 1'b0 };
 97             end
 98         end
 99         else begin
100             tickShift[2:0] <= ticks[2:0];
101         end
102 
103     end
104     assign pin_Dout = pin_nCS ? 1'bz : tickShift[2];
105 
106 endmodule