GR8RAM/cpld/GR8RAM.v
Zane Kaminski d8a5dc069d idk
2021-04-11 15:39:19 -04:00

550 lines
14 KiB
Verilog

module GR8RAM(C25M, PHI0, nRES, nRESout,
nIOSEL, nDEVSEL, nIOSTRB,
SetFW,
RA, nWE, RD, RDdir,
SBA, SA, nRCS, nRAS, nCAS, nSWE, DQML, DQMH, RCKE, SD,
nFCS, FCK, MISO, MOSI);
/* Clock signals */
input C25M, PHI0;
reg PHI0r1, PHI0r2;
always @(posedge C25M) begin PHI0r1 <= PHI0; PHI0r2 <= PHI0r1; end
/* Reset/brown-out detect synchronized inputs */
input nRES;
reg nRESr0, nRESr;
always @(posedge C25M) begin nRESr0 <= nRES; nRESr <= nRESr0; end
/* Long state counter: counts from 0 to $3FFF */
reg [13:0] LS = 0;
always @(posedge C25M) begin if (PS==15) LS <= LS+1; end
/* Init state */
output reg nRESout = 0;
reg [2:0] IS = 0;
always @(posedge C25M) begin
if (IS==7) nRESout <= 1;
else if (PS==15) begin
if (LS==14'h1FCE) IS <= 1; // PC all + load mode
else if (LS==14'h1FCF) IS <= 4; // AREF pause, SPI select
else if (LS==14'h1FFA) IS <= 5; // SPI flash command
else if (LS==14'h1FFF) IS <= 6; // Flash load driver
else if (LS==14'h3FFF) IS <= 7; // Operating mode
end
end
/* Apple IO area select signals */
input nIOSEL, nDEVSEL, nIOSTRB;
/* Apple address bus */
input [15:0] RA; input nWE;
/* Apple select signals */
wire ROMSpecSEL = RA[15:12]==4'hC && RA[11:8]!=4'h0;
wire BankSpecSEL = RA[3:0]==4'hF;
wire REGSpecSEL = RA[15:12]==4'hC && RA[11:8]==4'h0 && RA[7] && REGEN;
wire RAMSpecSEL = REGSpecSEL && RA[3:0]==4'h3 && (~SetLim1M || Addr[23:20]==0) && (~SetLim8M || ~Addr[23]);
wire AddrHSpecSEL = REGSpecSEL && RA[3:0]==4'h2;
wire AddrMSpecSEL = REGSpecSEL && RA[3:0]==4'h1;
wire AddrLSpecSEL = REGSpecSEL && RA[3:0]==4'h0;
reg ROMSpecSELr, RAMSpecSELr, nWEr;
wire BankSEL = REGEN && ~nDEVSEL && BankSpecSEL;
wire RAMSEL = ~nDEVSEL && RAMSpecSELr;
wire RAMWR = RAMSEL && ~nWEr;
wire AddrHSEL = REGEN && ~nDEVSEL && AddrHSpecSEL;
wire AddrMSEL = REGEN && ~nDEVSEL && AddrMSpecSEL;
wire AddrLSEL = REGEN && ~nDEVSEL && AddrLSpecSEL;
always @(posedge PHI0) begin
ROMSpecSELr <= ROMSpecSEL;
RAMSpecSELr <= RAMSpecSEL;
nWEr <= nWE;
end
/* IOROMEN and REGEN control */
reg IOROMEN = 0;
reg REGEN = 0;
always @(posedge C25M, negedge nRESr) begin
if (~nRESr) begin
IOROMEN <= 0;
REGEN <= 0;
end else if (PS==8 && ~nIOSTRB && RA[10:0]==11'h7FF) begin
IOROMEN <= 0;
end else if (PS==8 && ~nIOSEL) begin
IOROMEN <= 1;
REGEN <= 1;
end
end
/* Apple data bus */
inout [7:0] RD = RDdir ? 8'bZ : RDD[7:0];
reg [7:0] RDD;
output RDdir = ~(PHI0r2 && nWE && PHI0 &&
(~nDEVSEL || ~nIOSEL || (~nIOSTRB && IOROMEN)));
/* Slinky address registers */
reg [23:0] Addr = 0;
reg AddrIncL = 0;
reg AddrIncM = 0;
reg AddrIncH = 0;
always @(posedge C25M, negedge nRESr) begin
if (~nRESr) begin
Addr[23:0] <= 24'h000000;
AddrIncL <= 0;
AddrIncM <= 0;
AddrIncH <= 0;
end else begin
if (PS==8 && RAMSEL) AddrIncL <= 1;
else AddrIncL <= 0;
if (PS==8 && AddrLSEL && ~nWEr) begin
Addr[7:0] <= RD[7:0];
AddrIncM <= Addr[7] && ~RD[7];
end else if (AddrIncL) begin
Addr[7:0] <= Addr[7:0]+1;
AddrIncM <= Addr[7:0]==8'hFF;
end else AddrIncM <= 0;
if (PS==8 && AddrMSEL && ~nWEr) begin
Addr[15:8] <= RD[7:0];
AddrIncH <= Addr[15] && ~RD[7];
end else if (AddrIncM) begin
Addr[15:8] <= Addr[15:8]+1;
AddrIncH <= Addr[15:8]==8'hFF;
end else AddrIncH <= 0;
if (PS==8 && AddrHSEL && ~nWEr) begin
Addr[23:16] <= RD[7:0];
end else if (AddrIncH) begin
Addr[23:16] <= Addr[23:16]+1;
end
end
end
/* ROM bank register */
reg Bank = 0;
always @(posedge C25M, negedge nRESr) begin
if (~nRESr) Bank <= 0;
else if (PS==8 && BankSEL && ~nWEr) begin
Bank <= RD[0];
end
end
/* SPI flash */
output nFCS = ~FCS;
reg FCS = 0;
output reg FCK = 0;
inout MOSI = MOSIOE ? MOSIout : 1'bZ;
reg MOSIOE = 0;
reg MOSIout;
input MISO;
always @(posedge C25M) begin
case (PS[3:0])
0: begin // NOP CKE
FCK <= 1'b1;
end 1: begin // ACT
FCK <= ~(IS==5 || IS==6);
end 2: begin // RD
FCK <= 1'b1;
end 3: begin // NOP CKE
FCK <= ~(IS==5 || IS==6);
end 4: begin // NOP CKE
FCK <= 1'b1;
end 5: begin // NOP CKE
FCK <= ~(IS==5 || IS==6);
end 6: begin // NOP CKE
FCK <= 1'b1;
end 7: begin // NOP CKE
FCK <= ~(IS==5 || IS==6);
end 8: begin // WR AP
FCK <= 1'b1;
end 9: begin // NOP CKE
FCK <= ~(IS==5);
end 10: begin // PC all
FCK <= 1'b1;
end 11: begin // AREF
FCK <= ~(IS==5);
end 12: begin // NOP CKE
FCK <= 1'b1;
end 13: begin // NOP CKE
FCK <= ~(IS==5);
end 14: begin // NOP CKE
FCK <= 1'b1;
end 15: begin // NOP CKE
FCK <= ~(IS==5);
end
endcase
FCS <= IS==4 || IS==5 || IS==6;
MOSIOE <= IS==5;
end
always @(posedge C25M) begin
case (PS[3:0])
1, 2: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b0; // Command bit 7
3'h4: MOSIout <= 1'b0; // Address bit 23
3'h5: MOSIout <= 1'b0; // Address bit 15
3'h6: MOSIout <= 1'b0; // Address bit 7
default MOSIout <= 1'b0;
endcase
end 3, 4: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b0; // Command bit 6
3'h4: MOSIout <= 1'b0; // Address bit 22
3'h5: MOSIout <= SetFW[1]; // Address bit 14
3'h6: MOSIout <= 1'b0; // Address bit 6
default MOSIout <= 1'b0;
endcase
end 5, 6: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b1; // Command bit 5
3'h4: MOSIout <= 1'b0; // Address bit 21
3'h5: MOSIout <= SetFW[0]; // Address bit 13
3'h6: MOSIout <= 1'b0; // Address bit 5
default MOSIout <= 1'b0;
endcase
end 7, 8: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b1; // Command bit 4
3'h4: MOSIout <= 1'b0; // Address bit 20
3'h5: MOSIout <= 1'b0; // Address bit 12
3'h6: MOSIout <= 1'b0; // Address bit 4
default MOSIout <= 1'b0;
endcase
end 9, 10: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b1; // Command bit 3
3'h4: MOSIout <= 1'b0; // Address bit 19
3'h5: MOSIout <= 1'b0; // Address bit 11
3'h6: MOSIout <= 1'b0; // Address bit 3
default MOSIout <= 1'b0;
endcase
end 11, 12: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b0; // Command bit 2
3'h4: MOSIout <= 1'b0; // Address bit 18
3'h5: MOSIout <= 1'b0; // Address bit 10
3'h6: MOSIout <= 1'b0; // Address bit 2
default MOSIout <= 1'b0;
endcase
end 13, 14: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b1; // Command bit 1
3'h4: MOSIout <= 1'b0; // Address bit 16
3'h5: MOSIout <= 1'b0; // Address bit 9
3'h6: MOSIout <= 1'b0; // Address bit 1
default MOSIout <= 1'b0;
endcase
end 15, 0: begin
case (LS[2:0])
3'h3: MOSIout <= 1'b1; // Command bit 0
3'h4: MOSIout <= 1'b0; // Address bit 15
3'h5: MOSIout <= 1'b0; // Address bit 7
3'h6: MOSIout <= 1'b0; // Address bit 0
default MOSIout <= 1'b0;
endcase
end
endcase
end
input [1:0] SetFW;
wire SetRF = SetFW[1:0] != 2'b11;
wire SetLim1M = SetFW[1];
wire SetLim8M = SetFW[1:0] != 2'b00;
/* SDRAM data bus */
inout [7:0] SD = SDOE ? WRD[7:0] : 8'bZ;
reg [7:0] WRD;
reg SDOE = 0;
always @(posedge C25M) begin
case (PS[3:0])
0: begin // NOP CKE
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 1: begin // ACT
end 2: begin // RD
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 3: begin // NOP CKE
end 4: begin // NOP CKE
if (AddrLSpecSEL) RDD[7:0] <= Addr[7:0];
else if (AddrMSpecSEL) RDD[7:0] <= Addr[15:8];
else if (AddrHSpecSEL && SetRF) RDD[7:0] <= Addr[23:16];
else if (AddrHSpecSEL && ~SetRF) RDD[7:0] <= {4'hF, Addr[19:16]};
else RDD[7:0] <= SD[7:0];
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 5: begin // NOP CKE
end 6: begin // NOP CKE
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 7: begin // NOP CKE
end 8: begin // WR AP
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 9: begin // NOP CKE
end 10: begin // PC all
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 11: begin // AREF
end 12: begin // NOP CKE
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 13: begin // NOP CKE
end 14: begin // NOP CKE
if (IS==6) WRD[7:0] <= { MISO, MOSI, WRD[5:0] };
else WRD[7:0] <= RD[7:0];
end 15: begin // NOP CKE
end
endcase
end
reg [3:0] PS = 0;
wire PSStart = PS==0 && PHI0r1 && ~PHI0r2;
always @(posedge C25M) begin
if (PSStart) PS <= 1;
else if (PS==0) PS <= 0;
else PS <= PS+1;
end
/* SDRAM address/command */
output reg RCKE = 1;
output reg nRCS = 1;
output reg nRAS = 1;
output reg nCAS = 1;
output reg nSWE = 1;
wire RefReqd = LS[1:0] == 2'b11;
always @(posedge C25M) begin
case (PS[3:0])
0: begin // NOP CKE / CKD
RCKE <= PSStart;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 1: begin // ACT CKE / NOP CKD
RCKE <= IS==6 || (((ROMSpecSELr && nWEr) || RAMSpecSELr) && IS==7);
nRCS <= ~(IS==6 || (((ROMSpecSELr && nWEr) || RAMSpecSELr) && IS==7));
nRAS <= 1'b0;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 2: begin // RD CKE / NOP CKD
RCKE <= (ROMSpecSELr || RAMSpecSELr) && nWEr && IS==7;
nRCS <= ~((ROMSpecSELr || RAMSpecSELr) && nWEr && IS==7);
nRAS <= 1'b1;
nCAS <= 1'b0;
nSWE <= 1'b1;
SDOE <= 0;
end 3: begin // NOP CKE / CKD
RCKE <= (ROMSpecSELr || RAMSpecSELr) && nWEr && IS==7;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 4: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 5: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 6: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 7: begin // NOP CKE / CKD
RCKE <= IS==6 || (RAMWR && IS==7);
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 8: begin // WR AP / NOP CKE (WR AP)
// NOP CKD / WR AP
RCKE <= IS==6 || (RAMWR && IS==7);
nRCS <= ~(IS==6 || (RAMWR && IS==7));
nRAS <= 1'b1;
nCAS <= 1'b0;
nSWE <= 1'b0;
SDOE <= IS==6 || (RAMWR && IS==7);
end 9: begin // NOP CKE / NOP CKD
RCKE <= (IS==6) || ((ROMSpecSELr || RAMSpecSELr) && IS==7) ||
(RefReqd && (IS==4 || IS==5 || IS==6 || IS==7));
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 10: begin // PC all / NOP CKD (PC all)
RCKE <= (IS==6) || ((ROMSpecSELr || RAMSpecSELr) && IS==7) ||
(RefReqd && (IS==4 || IS==5 || IS==6 || IS==7));
nRCS <= ~((IS==6) || ((ROMSpecSELr || RAMSpecSELr) && IS==7) ||
(RefReqd && (IS==4 || IS==5 || IS==6 || IS==7)));
nRAS <= 1'b0;
nCAS <= 1'b1;
nSWE <= 1'b0;
SDOE <= 0;
end 11: begin // AREF / NOP CKD (AREF)
RCKE <= RefReqd && (IS==4 || IS==5 || IS==6 || IS==7);
nRCS <= ~(RefReqd && (IS==4 || IS==5 || IS==6 || IS==7));
nRAS <= 1'b0;
nCAS <= 1'b0;
nSWE <= 1'b1;
SDOE <= 0;
end 12: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 13: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 14: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end 15: begin // NOP CKD
RCKE <= 1'b0;
nRCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nSWE <= 1'b1;
SDOE <= 0;
end
endcase
end
output reg DQML = 1;
output reg DQMH = 1;
output reg [1:0] SBA;
output reg [12:0] SA;
always @(posedge C25M) begin
case (PS[3:0])
0: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 1: begin // ACT
DQML <= 1'b1;
DQMH <= 1'b1;
if (IS==6) begin
SBA[1:0] <= { 2'b10 };
SA[12:0] <= { 10'b0011000100, LS[12:10] };
end else if (RAMSpecSELr) begin
SBA[1:0] <= { 1'b0, Addr[23] && SetRF };
SA[12:0] <= { SetRF ? Addr [22:20] : 3'b000, Addr[19:10]};
end else begin
SBA[1:0] <= 2'b10;
SA[12:0] <= { 10'b0011000100, Bank, RA[11:10] };
end
end 2: begin // RD
if (RAMSpecSELr) begin
SBA[1:0] <= { 1'b0, Addr[23] && SetRF };
SA[12:0] <= { 4'b0011, Addr[9:1] };
DQML <= Addr[0];
DQMH <= ~Addr[0];
end else begin
SBA[1:0] <= 2'b10;
SA[12:0] <= { 4'b0011, RA[9:1]};
DQML <= RA[0];
DQMH <= ~RA[0];
end
end 3: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 4: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 5: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 6: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 7: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 8: begin // WR AP
if (IS==6) begin
SBA[1:0] <= 2'b10;
SA[12:0] <= { 4'b0011, LS[9:1] };
DQML <= LS[0];
DQMH <= ~LS[0];
end else begin
SBA[1:0] <= { 1'b0, Addr[23] && SetLim8M && SetRF };
SA[12:0] <= { 4'b0011, Addr[9:1] };
DQML <= Addr[0];
DQMH <= ~Addr[0];
end
end 9: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 10: begin // PC all
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 11: begin // AREF / load mode
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0001000100000;
end 12: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 13: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 14: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end 15: begin // NOP CKE
DQML <= 1'b1;
DQMH <= 1'b1;
SBA[1:0] <= 2'b00;
SA[12:0] <= 13'b0011000100000;
end
endcase
end
endmodule