MCU Design Refinements
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