I changed the MCU CPLD verilog.

The MCU is just a simple bank switcher. I had 4 5 bit banks. The top two bits of the 16 bit address bus: 15 and 14, select a map. Then this map result is used for address bits 17-14.

Originally, I was thinking I would the top bit (essentially A[18]) as the chip select for the SRAM or the flash. But Duh!  Ab address line does not a chip select make. So I removed the top address line and added two pin_nCS lines. These will select. And they tristate in reset. Also, the mapping tristates in reset also. This will allow me to use my in-circuit flash programmer. The Arduino will assert RESET to….   I need that needle scratching across the record sound effect… I just realized a problem.

I went to see if the bus control signals tristate on the Z-80 in reset. They don’t. They go high. I DO need to use BUSREQ because they do tri-state in that mode. And I can’t see what happens if I just tie BUSREQ to RESET. Which takes priority? Most likely RESET.

Well, crap! Back to the CPLD design…

[UPDATE: OK, I’ve decided to use 2 switches on the DIP switch instead. So the CPLD pin_nRESET line will connect to the board RESET or CPU BUSREQ line. So all is well with the CPLD…for now.]

Here is the latest MCU code before I realized that I need to use BUSREQ or BUSACK to tristate the bus lines:

  1 // This CPLD meant for the Lattice M4A5 64/32 is a simple bank switching
  2 // memory control unit. It has 8 registers:
  3 //  00 - bank 0
  4 //  01 - bank 1
  5 //  02 - bank 2
  6 //  03 - bank 3
  7 //  04 - update 0
  8 //  05 - update 1
  9 //  06 - update 2
 10 //  07 - update 3
 11 //
 12 //  The banks are meant to substitute starting address line 14.
 13 //  The update registers can only be written to from bank 00 i.e. the lowest
 14 //  16kb.
 15 //
 16 //  The banks are updated from the update registers when HALT is called
 17 //  from bank 0. NMI immediately follows HALT in this circumstance
 18 //
 19 
 20 `define BANKTOP 4
 21 `define IO_RANGE 7:3
 22 `define IO_VALUE 5'b00000
 23 `define ACTIVELOW 1'b0
 24 
 25 module mcu (
 26     input pin_CLK,
 27     input [15:0] pins_A,
 28     input pin_nRESET, pin_nWR, pin_nRD, pin_nMREQ, pin_nIORQ, pin_nM1, pin_nHALT,
 29     output reg pin_nNMI,
 30     output [`BANKTOP-1:0] pins_Aout,
 31     output pin_nCS0, pin_nCS1,
 32     inout [7:0] pins_D
 33 );
 34 
 35     reg [`BANKTOP:0] bankReg0;
 36     reg [`BANKTOP:0] bankReg1;
 37     reg [`BANKTOP:0] bankReg2;
 38     reg [`BANKTOP:0] bankReg3;
 39     reg [`BANKTOP:0] updateReg0;
 40     reg [`BANKTOP:0] updateReg1;
 41     reg [`BANKTOP:0] updateReg2;
 42     reg [`BANKTOP:0] updateReg3;
 43     reg nKernel;
 44     wire nInRange;
 45     reg [7:0] Dint;
 46     wire [`BANKTOP:0] selBank;
 47 
 48     // Determine if the address bus is talking to us
 49     assign nInRange = ((pins_A[`IO_RANGE] == `IO_VALUE) ? 1'b0 : 1'b1) | pin_nIORQ;
 50 
 51     // Get selected output
 52     assign selBank = pins_A[15] ? (pins_A[14] ? bankReg3 : bankReg2) : (pins_A[14] ? bankReg1 : bankReg0);
 53 
 54     // assign Aout -- Hi-Z on reset
 55     assign pins_Aout = pin_nRESET ? selBank[`BANKTOP-1:0] : 8'bzzzzzzzz;
 56 
 57     // CS's for top bit of bank
 58     assign pin_nCS0 = pin_nRESET ? (selBank[`BANKTOP] | pin_nMREQ) : 1'bz;
 59     assign pin_nCS1 = pin_nRESET ? ((~selBank[`BANKTOP]) | pin_nMREQ) : 1'bz;
 60 
 61     assign pins_D = ((pin_nRD | nInRange) == 1'b0) ? Dint : 8'bzzzzzzzz;
 62 
 63     always @(*) begin
 64         case (pins_A[2:0])
 65             3'b000:
 66                 Dint = bankReg0;
 67             3'b001:
 68                 Dint = bankReg1;
 69             3'b010:
 70                 Dint = bankReg2;
 71             3'b011:
 72                 Dint = bankReg3;
 73             3'b100:
 74                 Dint = updateReg0;
 75             3'b101:
 76                 Dint = updateReg1;
 77             3'b110:
 78                 Dint = updateReg2;
 79             3'b111:
 80                 Dint = updateReg3;
 81         endcase
 82     end
 83 
 84     always @(posedge pin_CLK) begin
 85         if (pin_nRESET == `ACTIVELOW) begin
 86             bankReg0 <= 0;
 87             bankReg1 <= 1;
 88             bankReg2 <= (1 << `BANKTOP);
 89             bankReg3 <= (1 << `BANKTOP) | 1;
 90             pin_nNMI <= 1'b1;
 91         end
 92         else begin
 93             if ((pin_nHALT | nKernel) == `ACTIVELOW) begin
 94                 bankReg0 <= updateReg0;
 95                 bankReg1 <= updateReg1;
 96                 bankReg2 <= updateReg2;
 97                 bankReg3 <= updateReg3;
 98             end
 99 
100             pin_nNMI <= pin_nHALT;
101             
102             if ((pin_nM1 | pin_nMREQ) == `ACTIVELOW) begin
103                 nKernel <= pins_A[15] | pins_A[14];
104             end
105         end
106     end
107     
108     always @(posedge pin_nWR) begin
109         if (((pin_nIORQ | nInRange) == `ACTIVELOW) && (pins_A[2] == 1'b1)) begin
110             case (pins_A[1:0])
111                 2'b00: begin
112                     updateReg0 <= pins_D;
113                 end
114                 2'b01: begin
115                     updateReg1 <= pins_D;
116                 end
117                 2'b10: begin
118                     updateReg2 <= pins_D;
119                 end
120                 2'b11: begin
121                     updateReg3 <= pins_D;
122                 end
123             endcase
124         end
125     end
126 
127 endmodule