2021-02-18 00:29:24 +00:00
|
|
|
module GR8RAM(C25M, PHI0, nPBOD, nBOD, nRES,
|
|
|
|
nIOSEL, nDEVSEL, nIOSTRB,
|
|
|
|
RA, nWEin, nWEout, Adir,
|
|
|
|
RD, Ddir,
|
2020-10-08 03:32:29 +00:00
|
|
|
DMAin, DMAout, INTin, INTout,
|
2021-02-18 00:29:24 +00:00
|
|
|
nDMA, nRDY, nNMI, nIRQ, nINH, nRESout
|
|
|
|
SBA, SA, nRCS, nRAS, nCAS, nSWE, DQML, DQMH, RCKE, SD,
|
|
|
|
nFCS, FCK, MISO, MOSI);
|
|
|
|
|
|
|
|
/* Clock signals */
|
|
|
|
input C25M, PHI0;
|
|
|
|
reg PHI0r1, PHI0r2, PHI0r3;
|
|
|
|
always @(negedge C25M) begin PHI0r1 <= PHI0; end
|
2020-10-08 03:32:29 +00:00
|
|
|
always @(posedge C25M) begin
|
2021-02-18 00:29:24 +00:00
|
|
|
PHI0r2 <= PHI0r1; PHI0r3 <= PHI0r2;
|
2019-12-21 06:46:05 +00:00
|
|
|
end
|
2020-02-16 05:11:12 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Reset/brown-out detect inputs */
|
|
|
|
input nRES, nPBOD, nBOD;
|
|
|
|
reg PBODr1, PBODr2, BODr1, BODr2, RESr1, RESr2;
|
|
|
|
always @(negedge C25M) begin
|
|
|
|
PBODr1 <= ~nPBOD; BODr1 <= ~nBOD; RESr1 <= ~nRES;
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
|
|
|
always @(posedge C25M) begin
|
2021-02-18 00:29:24 +00:00
|
|
|
PBODr2 <= PBODr1; BODr2 <= BODr1; RESr2 <= RESr1;
|
2020-02-16 04:15:54 +00:00
|
|
|
end
|
2020-02-16 05:11:12 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Apple IO area select signals */
|
|
|
|
input nIOSEL, nDEVSEL, nIOSTRB;
|
|
|
|
reg DEVSELr1, DEVSELr2;
|
|
|
|
always @(negedge C25M) begin DEVSELr1 <= ~nDEVSEL; end
|
|
|
|
always @(posedge C25M) begin DEVSELr2 <= DEVSELr1; end
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* DMA/IRQ daisy chain */
|
|
|
|
input DMAin, INTin;
|
|
|
|
output DMAout = DMAin;
|
|
|
|
output INTout = INTin;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Apple open-drain outputs */
|
|
|
|
output nDMA = 1;
|
|
|
|
output nRDY = 1;
|
|
|
|
output nNMI = 1;
|
|
|
|
output nIRQ = 1;
|
|
|
|
output nINH = 1;
|
|
|
|
output nRESout = 0;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Apple address bus */
|
2020-10-08 03:32:29 +00:00
|
|
|
input [15:0] RA;
|
2021-02-18 00:29:24 +00:00
|
|
|
input nWEin;
|
|
|
|
output RAdir = 1;
|
|
|
|
output nWEout = 1;
|
|
|
|
reg [15:0] RAr1; reg nWEr1;
|
|
|
|
reg [15:0] RAr2; reg nWEr2;
|
|
|
|
reg [15:0] RAcur; reg nWEcur;
|
|
|
|
always @(negedge C25M) begin RAr1 <= RA; nWEr1 <= nWE; end
|
|
|
|
always @(posedge C25M) begin RAr2 <= RAr1; nWEr2 <= nWEr1; end
|
|
|
|
always @(posedge C25M) begin
|
|
|
|
if (S==0 && ~PHI0r2) begin
|
|
|
|
RAcur <= RAr2;
|
|
|
|
nWEcur <= nWER2;
|
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Apple select signals */
|
|
|
|
wire ROMSpecSEL = RAcur[15:12]==4'hC && RAcur[11:8]!=4'h0;
|
|
|
|
wire ROMSpecRD = ROMSpecSEL && nWE;
|
|
|
|
wire RAMSpecSEL = RAcur[15:12]==4'hC && RAcur[11:8]==4'h0 && RAcur[7] && RAcur[7:4]!=4'h8 && RAcur[3:0]==4'h3;
|
|
|
|
wire RAMSpecRD = RAMSpecSEL && nWE;
|
|
|
|
wire RAMSpecWR = RAMSpecSEL && ~nWE;
|
|
|
|
wire SpecRD = ROMSpecRD || RAMSpecRD;
|
|
|
|
reg RAMRD = 0, RAMWR = 0;
|
|
|
|
always @(posedge C25M) begin
|
|
|
|
if (S==5) begin
|
|
|
|
RAMRD <= RAMSpecRD && DEVSELr2;
|
|
|
|
RAMWR <= RAMSpecWR && DEVSELr2;
|
|
|
|
end else if (S==0) begin
|
|
|
|
RAMRD <= 0;
|
|
|
|
RAMWR <= 0;
|
|
|
|
end
|
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Apple data bus */
|
|
|
|
inout [7:0] RD = RDdir ? 8'bZ : RDout[7:0];
|
|
|
|
reg RDdir = 1;
|
|
|
|
reg [7:0] RDout;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* SDRAM data bus */
|
|
|
|
inout [7:0] SD = SDOE ? RD[7:0] : 8'bZ;
|
2020-10-08 03:32:29 +00:00
|
|
|
reg SDOE = 0;
|
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* SDRAM address/command */
|
|
|
|
output reg [1:0] SBA;
|
|
|
|
output reg [12:0] SA;
|
|
|
|
output reg RCKE = 1;
|
|
|
|
output reg nRCS = 1;
|
2020-10-08 03:32:29 +00:00
|
|
|
output reg nRAS = 1;
|
|
|
|
output reg nCAS = 1;
|
|
|
|
output reg nSWE = 1;
|
|
|
|
output reg DQMH = 1;
|
2021-02-18 00:29:24 +00:00
|
|
|
output reg DQML = 1;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* SPI flash */
|
|
|
|
output reg nFCS = 1;
|
|
|
|
output reg FCK = 0;
|
|
|
|
output reg MOSI = MOSIOE ? MOSIout : 1'bZ;
|
|
|
|
reg MOSIOE = 0;
|
|
|
|
reg MOSIout;
|
|
|
|
input MISO;
|
|
|
|
|
|
|
|
/* State counters */
|
|
|
|
reg [24:0] FS = 0;
|
|
|
|
always @(posedge C25M) begin FS <= FS+1; end
|
|
|
|
reg [2:0] S = 0;
|
2020-10-08 03:32:29 +00:00
|
|
|
always @(posedge C25M) begin
|
2021-02-18 00:29:24 +00:00
|
|
|
if (S==0 && PHI0r2 && ~PHI0r3 && ~RESr2 && ~BODr2) S <= 1;
|
|
|
|
else if (S==0) S <= 0;
|
|
|
|
else S <= S+1;
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
2021-02-18 00:29:24 +00:00
|
|
|
|
|
|
|
/* Refresh state */
|
|
|
|
reg RefReady = 0;
|
|
|
|
reg RefDone = 0;
|
|
|
|
always @(posedge C25M) begin RefReady <= S==0; end
|
2020-10-08 03:32:29 +00:00
|
|
|
always @(posedge C25M) begin
|
2021-02-18 00:29:24 +00:00
|
|
|
if (FS[6:0]==7'h00) RefDone <= 0;
|
|
|
|
else (S==0 && RefReady && RCKE && ~(PHI0r2 && ~PHI0r3)) RefDone <= 1;
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
/* Slinky registers */
|
|
|
|
reg [24:0] Addr;
|
|
|
|
wire AddrHSpecSEL = RAcur[3:0]==4'h2;
|
|
|
|
wire AddrMSpecSEL = RAcur[3:0]==4'h1;
|
|
|
|
wire AddrLSpecSEL = RAcur[3:0]==4'h0;
|
|
|
|
always @(posedge C25M) begin
|
|
|
|
if (S==7 && DEVSELr2) begin
|
|
|
|
if (AddrHSpecSEL || AddrMSpecSEL || AddrLSpecSEL) begin
|
|
|
|
Addr[24] <= 1'b0;
|
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
if (AddrHSpecSEL) begin
|
|
|
|
Addr[23:16] <= RD[7:0];
|
|
|
|
end else if (RAMRD || RAMWR ||
|
|
|
|
(AddrMSpecSEL && Addr[15] && ~RD[7]) ||
|
|
|
|
(AddrLSpecSEL && Addr[7] && ~RD[7] && Addr[15:8]==8'hFF)) begin
|
|
|
|
Addr[23:16] <= Addr[23:16]+1;
|
2019-09-01 02:55:04 +00:00
|
|
|
end
|
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
if (AddrMSpecSEL) begin
|
|
|
|
Addr[15:8] <= RD[7:0];
|
|
|
|
end else if (RAMRD || RAMWR ||
|
|
|
|
(AddrLSpecSEL && Addr[7] && ~RD[7])) begin
|
|
|
|
Addr[15:8] <= Addr[15:8]+1;
|
2020-03-10 22:54:44 +00:00
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
if (AddrLSpecSEL) begin
|
|
|
|
Addr[7:0] <= RD[7:0];
|
|
|
|
end else if (RAMRD || RAMWR) begin
|
|
|
|
Addr[7:0] <= Addr[7:0]+1;
|
|
|
|
end
|
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge C25M) begin
|
2021-02-18 00:29:24 +00:00
|
|
|
if (S==0) begin
|
|
|
|
if ((PHI0r2 && ~PHI0r3 && ~RESr2 && ~BODr2 && SpecRD) ||
|
|
|
|
(~RefReady && ~RefDone)) begin
|
|
|
|
// NOP cken
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end else if (RefReady && ~RefDone && RCKE &&
|
|
|
|
~(PHI0r2 && ~PHI0r3)) begin
|
|
|
|
// AREF
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b0;
|
|
|
|
nRAS <= 1'b0;
|
|
|
|
nCAS <= 1'b0;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end
|
|
|
|
end else if (S==4'h1) begin
|
|
|
|
if (SpecRD) begin
|
|
|
|
// ACT
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b0;
|
|
|
|
nRAS <= 1'b0;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
if (RAMSpecRD) begin
|
|
|
|
RBA[1] <= Addr[24];
|
|
|
|
RBA[0] <= Addr[23];
|
|
|
|
RA[12:0] <= Addr[22:10];
|
2020-10-08 03:32:29 +00:00
|
|
|
end else begin
|
2021-02-18 00:29:24 +00:00
|
|
|
RBA[1] <= 1'b1;
|
|
|
|
RBA[0] <= 1'b0;
|
|
|
|
RA[12:10] <= 3'b000;
|
|
|
|
RA[9:2] <= Bank[7:0];
|
|
|
|
RA[1:0] <= RAcur[11:10];
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
2021-02-18 00:29:24 +00:00
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
2021-02-18 00:29:24 +00:00
|
|
|
DQML <= 1'b1;
|
2020-03-10 22:54:44 +00:00
|
|
|
end
|
2021-02-18 00:29:24 +00:00
|
|
|
end else if (S==4'h2) begin
|
|
|
|
if (SpecRD) begin
|
|
|
|
// RD auto-PC
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b0;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b0;
|
|
|
|
nSWE <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
A[12:11] <= 1'b0; // don't care
|
|
|
|
A[10] <= 1'b1; // auto-precharge
|
|
|
|
A[9] <= 1'b0; // don't care
|
|
|
|
if (RAMSpecRD) begin
|
|
|
|
RBA[1] <= Addr[24];
|
|
|
|
RBA[0] <= Addr[23];
|
|
|
|
RA[8:0] <= Addr[9:1];
|
|
|
|
DQMH <= ~Addr[0];
|
|
|
|
DQML <= Addr[0];
|
|
|
|
end else /* ROMSpecRD */ begin
|
|
|
|
RBA[1] <= 1'b1;
|
|
|
|
RBA[0] <= 1'b0;
|
|
|
|
RA[8:0] <= RAcur[9:1];
|
|
|
|
DQMH <= ~RAcur[0];
|
|
|
|
DQML <= RAcur[0];
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
2021-02-18 00:29:24 +00:00
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
2021-02-18 00:29:24 +00:00
|
|
|
DQMH <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
DQML <= 1'b1;
|
2021-02-18 00:29:24 +00:00
|
|
|
end
|
|
|
|
end else if (S==4'h3) begin
|
|
|
|
if (SpecRD) begin
|
|
|
|
// NOP cken
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
DQMH <= 1'b1;
|
2021-02-18 00:29:24 +00:00
|
|
|
DQML <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
2020-03-10 22:54:44 +00:00
|
|
|
end
|
2021-02-18 00:29:24 +00:00
|
|
|
end else if (S==4'h4) begin
|
|
|
|
if (RAMSpecWR) begin
|
|
|
|
// NOP cken
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
2021-02-18 00:29:24 +00:00
|
|
|
end else if (S==4'h5) begin
|
|
|
|
if (RAMSpecWR && DEVSELr2) begin
|
|
|
|
// ACT
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b0;
|
|
|
|
nRAS <= 1'b0;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
2020-10-08 03:32:29 +00:00
|
|
|
|
2021-02-18 00:29:24 +00:00
|
|
|
BA[1] <= Addr[24];
|
|
|
|
BA[0] <= Addr[23];
|
|
|
|
A[12:0] <= Addr[22:10];
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end
|
|
|
|
end else if (s==4'h6) begin
|
|
|
|
if (RAMWR) begin
|
|
|
|
// WR auto-PC
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b0;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b0;
|
|
|
|
nSWE <= 1'b0;
|
|
|
|
|
|
|
|
BA[1] <= Addr[24];
|
|
|
|
BA[0] <= Addr[23];
|
|
|
|
A[12:11] <= 1'b0; // don't care
|
|
|
|
A[10] <= 1'b1; // auto-precharge
|
|
|
|
A[9:0] <= Addr[9:0];
|
|
|
|
DQMH <= ~Addr[10];
|
|
|
|
DQML <= Addr[10];
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end
|
|
|
|
end else if (S==4'h7) begin
|
|
|
|
if (RAMSpecWR) begin
|
|
|
|
// NOP cken
|
|
|
|
RCKE <= 1'b1;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
// NOP ckdis
|
|
|
|
RCKE <= 1'b0;
|
|
|
|
nRCS <= 1'b1;
|
|
|
|
nRAS <= 1'b1;
|
|
|
|
nCAS <= 1'b1;
|
|
|
|
nSWE <= 1'b1;
|
|
|
|
DQMH <= 1'b1;
|
|
|
|
DQML <= 1'b1;
|
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
end
|
2019-09-01 02:55:04 +00:00
|
|
|
end
|
2020-10-08 03:32:29 +00:00
|
|
|
endmodule
|