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:
// This CPLD meant for the Lattice M4A5 64/32 is a simple bank switching
// memory control unit. It has 8 registers:
// 00 - bank 0
// 01 - bank 1
// 02 - bank 2
// 03 - bank 3
// 04 - update 0
// 05 - update 1
// 06 - update 2
// 07 - update 3
//
// The banks are meant to substitute starting address line 14.
// The update registers can only be written to from bank 00 i.e. the lowest
// 16kb.
//
// The banks are updated from the update registers when HALT is called
// from bank 0. NMI immediately follows HALT in this circumstance
//
`define BANKTOP 4
`define IO_RANGE 7:3
`define IO_VALUE 5'b00000
`define ACTIVELOW 1'b0
module mcu (
input pin_CLK,
input [15:0] pins_A,
input pin_nRESET, pin_nWR, pin_nRD, pin_nMREQ, pin_nIORQ, pin_nM1, pin_nHALT,
output reg pin_nNMI,
output [`BANKTOP-1:0] pins_Aout,
output pin_nCS0, pin_nCS1,
inout [7:0] pins_D
);
reg [`BANKTOP:0] bankReg0;
reg [`BANKTOP:0] bankReg1;
reg [`BANKTOP:0] bankReg2;
reg [`BANKTOP:0] bankReg3;
reg [`BANKTOP:0] updateReg0;
reg [`BANKTOP:0] updateReg1;
reg [`BANKTOP:0] updateReg2;
reg [`BANKTOP:0] updateReg3;
reg nKernel;
wire nInRange;
reg [7:0] Dint;
wire [`BANKTOP:0] selBank;
// Determine if the address bus is talking to us
assign nInRange = ((pins_A[`IO_RANGE] == `IO_VALUE) ? 1'b0 : 1'b1) | pin_nIORQ;
// Get selected output
assign selBank = pins_A[15] ? (pins_A[14] ? bankReg3 : bankReg2) : (pins_A[14] ? bankReg1 : bankReg0);
// assign Aout -- Hi-Z on reset
assign pins_Aout = pin_nRESET ? selBank[`BANKTOP-1:0] : 8'bzzzzzzzz;
// CS's for top bit of bank
assign pin_nCS0 = pin_nRESET ? (selBank[`BANKTOP] | pin_nMREQ) : 1'bz;
assign pin_nCS1 = pin_nRESET ? ((~selBank[`BANKTOP]) | pin_nMREQ) : 1'bz;
assign pins_D = ((pin_nRD | nInRange) == 1'b0) ? Dint : 8'bzzzzzzzz;
always @(*) begin
case (pins_A[2:0])
3'b000:
Dint = bankReg0;
3'b001:
Dint = bankReg1;
3'b010:
Dint = bankReg2;
3'b011:
Dint = bankReg3;
3'b100:
Dint = updateReg0;
3'b101:
Dint = updateReg1;
3'b110:
Dint = updateReg2;
3'b111:
Dint = updateReg3;
endcase
end
always @(posedge pin_CLK) begin
if (pin_nRESET == `ACTIVELOW) begin
bankReg0 <= 0;
bankReg1 <= 1;
bankReg2 <= (1 << `BANKTOP);
bankReg3 <= (1 << `BANKTOP) | 1;
pin_nNMI <= 1'b1;
end
else begin
if ((pin_nHALT | nKernel) == `ACTIVELOW) begin
bankReg0 <= updateReg0;
bankReg1 <= updateReg1;
bankReg2 <= updateReg2;
bankReg3 <= updateReg3;
end
pin_nNMI <= pin_nHALT;
if ((pin_nM1 | pin_nMREQ) == `ACTIVELOW) begin
nKernel <= pins_A[15] | pins_A[14];
end
end
end
always @(posedge pin_nWR) begin
if (((pin_nIORQ | nInRange) == `ACTIVELOW) && (pins_A[2] == 1'b1)) begin
case (pins_A[1:0])
2'b00: begin
updateReg0 <= pins_D;
end
2'b01: begin
updateReg1 <= pins_D;
end
2'b10: begin
updateReg2 <= pins_D;
end
2'b11: begin
updateReg3 <= pins_D;
end
endcase
end
end
endmodule
No comments:
Post a Comment