Init sequence clears first 2048 bytes of first two RAMWorks banks

This commit is contained in:
Zane Kaminski 2023-12-27 00:33:23 -05:00
parent 8e9d1233be
commit 1de3608efa
2 changed files with 795 additions and 890 deletions

View File

@ -1,8 +1,8 @@
module RAM2E(C14M, PHI1, LED, module RAM2E(C14M, PHI1, LED,
nWE, nWE80, nEN80, nC07X, nWE, nWE80, nEN80, nC07X,
Ain, Din, Dout, nDOE, Vout, nVOE, Ain, Din, Dout, nDOE, Vout, nVOE,
CKE, nCS, nRAS, nCAS, nRWE, CKEout, nCSout, nRASout, nCASout, nRWEout,
BA, RA, RD, DQML, DQMH); BA, RAout, DQML, DQMH, RD);
/* Clocks */ /* Clocks */
input C14M, PHI1; input C14M, PHI1;
@ -10,50 +10,67 @@ module RAM2E(C14M, PHI1, LED,
/* Control inputs */ /* Control inputs */
input nWE, nWE80, nEN80, nC07X; input nWE, nWE80, nEN80, nC07X;
/* Delay for EN80 signal */
//output DelayOut = 1'b0;
//input DelayIn;
wire EN80 = !nEN80;
/* Activity LED */ /* Activity LED */
reg LEDEN = 0; reg LEDEN = 0;
output LED; output LED; assign LED = !(!nEN80 && LEDEN && Ready);
assign LED = !(!nEN80 && LEDEN);
/* Address Bus */ /* Address Bus */
input [7:0] Ain; // Multiplexed DRAM address input input [7:0] Ain; // Multiplexed DRAM address input
/* 6502 Data Bus */ /* 6502 Data Bus */
input [7:0] Din; // 6502 data bus inputs input [7:0] Din; // 6502 data bus inputs
reg DOEEN = 0; // 6502 data bus output enable from state machine reg DOEEN;
output nDOE; always @(posedge C14M) begin
assign nDOE = !(EN80 && nWE && DOEEN); // 6502 data bus output enable DOEEN <= /*(S==4'h8) || (S==4'h9) || (S==4'hA) ||*/ (S==4'hB) ||
output reg [7:0] Dout; // 6502 data Bus output (S==4'hC) || (S==4'hD) || (S==4'hE) || (S==4'hF);
end
output nDOE; assign nDOE = !(!nEN80 && nWE && DOEEN);
output [7:0] Dout; assign Dout[7:0] = RD[7:0];
/* Video Data Bus */ /* Video Data Bus */
output nVOE; reg VOEEN;
assign nVOE = !(!PHI1); /// Video data bus output enable always @(posedge C14M) begin
VOEEN <= (S==4'h7) ||
(S==4'h8) || (S==4'h9) || (S==4'hA) || (S==4'hB) ||
(S==4'hC) || (S==4'hD) || (S==4'hE) || (S==4'hF);
end
output nVOE; assign nVOE = !(!PHI1 && VOEEN);
output reg [7:0] Vout; // Video data bus output reg [7:0] Vout; // Video data bus
always @(posedge C14M) if (S==4'h6) Vout[7:0] <= RD[7:0];
/* SDRAM */ /* SDRAM */
output reg CKE = 0; reg CKE = 1;
output reg nCS = 1, nRAS = 1, nCAS = 1, nRWE = 1; //reg nCS = 1;
reg nRAS = 1, nCAS = 1, nRWE = 1;
output reg [1:0] BA; output reg [1:0] BA;
output reg [11:0] RA; reg [11:0] RA;
output reg DQML = 1, DQMH = 1; output reg DQML = 1, DQMH = 1;
wire RDOE = EN80 && !nWE80;
inout [7:0] RD; inout [7:0] RD;
assign RD[7:0] = RDOE ? Din[7:0] : 8'bZ; assign RD[7:0] = Ready ? (!nWE80 ? Din[7:0] : 8'bZ) : 8'h00;
/* SDRAM falling edge outputs */
output reg CKEout;
output nCSout; assign nCSout = 0;
output reg nRASout = 1, nCASout = 1, nRWEout = 1;
output reg [11:0] RAout;
always @(negedge C14M) begin
CKEout <= CKE;
nRASout <= nRAS;
nCASout <= nCAS;
nRWEout <= nRWE;
RAout <= RA;
end
/* RAMWorks Bank Register and Capacity Mask */ /* RAMWorks Bank Register and Capacity Mask */
reg [7:0] RWBank = 0; // RAMWorks bank register reg [7:0] RWBank = 0; // RAMWorks bank register
reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask
reg RWSel = 0; // RAMWorks bank register select reg RWSel = 0; // RAMWorks bank register select
always @(posedge C14M) begin
if (S==4'h9) RWSel <= RA[0] && !RA[3] && !nWE && !nC07X;
end
reg CmdRWMaskSet = 0; // RAMWorks Mask register set flag reg CmdRWMaskSet = 0; // RAMWorks Mask register set flag
// Causes RWBank to be zeroed next RWSel access // Causes RWBank to be zeroed next RWSel access
//reg CmdSetRWBankFFMAX = 0; reg CmdSetRWBankFFChip = 0;
//reg CmdSetRWBankFFSPI = 0;
reg CmdSetRWBankFFMXO2 = 0;
reg CmdSetRWBankFFLED = 0; reg CmdSetRWBankFFLED = 0;
reg CmdLEDSet = 0; reg CmdLEDSet = 0;
reg CmdLEDGet = 0; reg CmdLEDGet = 0;
@ -84,7 +101,7 @@ module RAM2E(C14M, PHI1, LED,
.wb_ack_o(wb_ack), .wb_ack_o(wb_ack),
.wbc_ufm_irq(ufm_irq)); .wbc_ufm_irq(ufm_irq));
/* UFM State and User Command Triggers */ /* User Command Triggers */
//reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel //reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel
//reg CmdBitbangSPI = 0; //reg CmdBitbangSPI = 0;
reg CmdBitbangMXO2 = 0; reg CmdBitbangMXO2 = 0;
@ -96,6 +113,7 @@ module RAM2E(C14M, PHI1, LED,
reg PHI1reg = 0; // Saved PHI1 at last rising clock edge reg PHI1reg = 0; // Saved PHI1 at last rising clock edge
reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15 reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15
reg [15:0] FS = 0; // Fast state counter reg [15:0] FS = 0; // Fast state counter
wire RefReq = FS[5:4]==0; // Refresh request based on fast state counter
reg [3:0] S = 0; // IIe State counter reg [3:0] S = 0; // IIe State counter
/* State Counters */ /* State Counters */
@ -105,8 +123,32 @@ module RAM2E(C14M, PHI1, LED,
// Synchronize Apple state counter to S1 when just entering PHI1 // Synchronize Apple state counter to S1 when just entering PHI1
PHI1reg <= PHI1; // Save old PHI1 PHI1reg <= PHI1; // Save old PHI1
S <= (PHI1 && !PHI1reg && Ready) ? 4'h1 : S <= (PHI1 && !PHI1reg && Ready) ? 4'h1 :
S==4'h0 ? 4'h0 : (S==4'h0) ? 4'h0 :
S==4'hF ? 4'hF : S+4'h1; (S==4'hF) ? 4'hF : S+4'h1;
// Begin normal operation after 64k init cycles (~4.59ms)
if (FS[15:0]==16'hFFFF) Ready <= 1'b1;
end
/* Command sequence control */
always @(posedge C14M) begin
if (S==4'hC) begin
if (RWSel) begin
CmdTout <= 0; // Reset command timeout if RWSel accessed
// Recognize command sequence and advance CS state
if ((CS==3'h0 && Din[7:0]==8'hFF) ||
(CS==3'h1 && Din[7:0]==8'h00) ||
(CS==3'h2 && Din[7:0]==8'h55) ||
(CS==3'h3 && Din[7:0]==8'hAA) ||
(CS==3'h4 && Din[7:0]==8'hC1) ||
(CS==3'h5 && Din[7:0]==8'hAD) ||
CS==3'h6 || CS==3'h7) CS <= CS+3'h1;
else CS <= 0; // Back to beginning if it's not right
end else begin
CmdTout <= CmdTout+3'h1; // Increment command timeout
// If command sequence times out, reset sequence state
if (CmdTout==3'h7) CS <= 0;
end
end
end end
/* UFM Control */ /* UFM Control */
@ -371,461 +413,373 @@ module RAM2E(C14M, PHI1, LED,
end end
end end
/* SDRAM Control */ /* RAMWorks register control - bank, LED, etc. */
always @(posedge C14M) begin always @(posedge C14M) begin
if (S==4'h0) begin if (S==4'hC && RWSel) begin
// SDRAM initialization // Latch RAMWorks bank if accessed
if (FS[15:0]==16'hFFC0) begin if ((CmdSetRWBankFFLED) ||
// Precharge All (CmdSetRWBankFFChip) ||
nCS <= 1'b0; (CmdLEDGet && LEDEN)) RWBank <= 8'hFF;
nRAS <= 1'b0; else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]};
nCAS <= 1'b1;
nRWE <= 1'b0; if (CS==3'h6) begin // Recognize and submit command in CS6
RA[10] <= 1'b1; // "all" // Board has LED detect command
end else if (FS[15:4]==16'hFFD && FS[0]==1'b0) begin // Repeat 8x CmdSetRWBankFFLED <= Din[7:0]==8'hF0;
// Auto-refresh
nCS <= 1'b0; // Volatile commands
nRAS <= 1'b0; CmdRWMaskSet <= Din[7:0]==8'hE0;
nCAS <= 1'b0; CmdLEDSet <= Din[7:0]==8'hE2;
nRWE <= 1'b1; CmdLEDGet <= Din[7:0]==8'hE3;
RA[10] <= 1'b0; end else begin // Reset command triggers
end else if (FS[15:0]==16'hFFE8) begin CmdSetRWBankFFLED <= 0;
// Set Mode Register CmdRWMaskSet <= 0;
nCS <= 1'b0; CmdLEDSet <= 0;
nRAS <= 1'b0; CmdLEDGet <= 0;
nCAS <= 1'b0; end
nRWE <= 1'b0; end
RA[10] <= 1'b0; // Reserved in mode register end
end else if (FS[15:4]==12'hFFF && FS[0]==1'b0) begin // Repeat 8x
// Auto-refresh /* RAMWorks register control - Lattice MachXO2 */
nCS <= 1'b0; always @(posedge C14M) begin
nRAS <= 1'b0; if (S==4'hC && RWSel) begin
nCAS <= 1'b0; if (CS==3'h6) begin // Recognize and submit command in CS6
nRWE <= 1'b1; // Chip detection commands
RA[10] <= 1'b0; //CmdSetRWBankFFChip <= Din[7:0]==8'hFF; // MAX
end else begin // Otherwise send no-op //CmdSetRWBankFFChip <= Din[7:0]==8'hFE; // SPI
CmdSetRWBankFFChip <= Din[7:0]==8'hFD; // MachXO2
// Altera MAX II/V commands
//CmdBitbangMAX <= Din[7:0]==8'hEA;
//if (!CmdEraseMAX && !CmdPrgmMAX) begin
// if (Din[7:0]==8'hEE) CmdEraseMAX <= 1;
// if (Din[7:0]==8'hEF) CmdPrgmMAX <= 1;
//end
// SPI commands
//CmdBitbangSPI <= Din[7:0]==8'hEB;
// MachXO2 commands
CmdBitbangMXO2 <= Din[7:0]==8'hEC;
CmdExecMXO2 <= Din[7:0]==8'hED;
end else begin // Reset command triggers
CmdSetRWBankFFChip <= 0;
//CmdBitbangMAX <= 0;
//CmdBitbangSPI <= 0;
CmdBitbangMXO2 <= 0;
CmdExecMXO2 <= 0;
end
end
end
/* SDRAM Control */
always @(posedge C14M) case (S)
4'h0: begin
CKE <= 1'b1;
if (!FS[15] || FS[0]) begin
// NOP // NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
RA[10] <= 1'b0; end else case (FS[4:1])
4'h0: begin
// PC all
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
end 4'h1: begin
// LDM
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b0;
end 4'h2: begin
// NOP
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end 4'h3, 4'h4, 4'h5, 4'h6,
4'h7, 4'h8, 4'h9, 4'hA: begin
// AREF
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b1;
end 4'hB: begin
// ACT
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
end 4'hC, 4'hD: begin
// WR
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b0;
end 4'hE: begin
// NOP
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end 4'hF: begin
// PC all
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
end end
// Enable SDRAM clock after 65,280 cycles (~4.56ms) endcase
CKE <= FS[15:8] == 8'hFF; case (FS[4:3])
2'b00, 2'b01: begin
// Mode register contents // Mode register contents
BA[1:0] <= 2'b00; // Reserved BA[1:0] <= 2'b00; // Reserved
RA[11] <= 1'b0; // Reserved RA[11] <= 1'b0; // Reserved
// RA[10] set above ^ RA[10] <= !FS[1]; // reserved / "all"
RA[9] <= 1'b1; // "1" for single write mode RA[9] <= 1'b1; // "1" for single write mode
RA[8] <= 1'b0; // Reserved RA[8] <= 1'b0; // Reserved
RA[7] <= 1'b0; // "0" for not test mode RA[7] <= 1'b0; // "0" for not test mode
RA[6:4] <= 3'b010; // "2" for CAS latency 2 RA[6:4] <= 3'b010; // "2" for CAS latency 2
RA[3] <= 1'b0; // "0" for sequential burst (not used) RA[3] <= 1'b0; // "0" for sequential burst (not used)
RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst) RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst)
end 2'b10: begin
// Mask everything BA[1:0] <= 2'b00;
DQML <= 1'b1; RA[11:8] <= 4'h0;
DQMH <= 1'b1; RA[7:0] <= FS[14:7];
end 2'b11: begin
// Inhibit data bus output BA[1:0] <= 2'b00;
DOEEN <= 1'b0; RA[11:3] <= 9'h000;
RA[2:1] <= FS[6:5];
// Begin normal operation after 128k init cycles (~9.15ms) RA[0] <= FS[1];
if (FS == 16'hFFFF) Ready <= 1'b1; end
end else if (S==4'h1) begin endcase
// Enable clock DQML <= !FS[15];
DQMH <= !FS[15];
end 4'h1: begin
// NOP CKE
CKE <= 1'b1; CKE <= 1'b1;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Don't care bank, RA[11:8]
BA[1:0] <= 2'b00; BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000; RA[11:8] <= 4'b0000;
// Hold RA[7:0]
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h2) begin
// Enable clock
CKE <= 1'b1;
// Activate
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
// SDRAM bank 0, high-order row address is 0
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Row address is as previously latched
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h3) begin
// Enable clock
CKE <= 1'b1;
// Read
nCS <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b1;
// SDRAM bank 0, RA[11,9:8] don't care
BA[1:0] <= 2'b00;
RA[11] <= 1'b0;
RA[10] <= 1'b1; // (A10 set to auto-precharge)
RA[9] <= 1'b0;
RA[8] <= 1'b0;
// Latch column address for read command
RA[7:0] <= Ain[7:0];
// Read low byte (high byte is +4MB in ramworks)
DQML <= 1'b0; DQML <= 1'b0;
DQMH <= 1'b1; DQMH <= 1'b1;
end 4'h2: begin
// Inhibit data bus output // ACT CKE
DOEEN <= 1'b0;
end else if (S==4'h4) begin
// Enable clock
CKE <= 1'b1; CKE <= 1'b1;
nRAS <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h3: begin
// RD CKE
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h5) begin
// Enable clock
CKE <= 1'b1; CKE <= 1'b1;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b0;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA[11:8]
BA[1:0] <= 2'b00; RA[7:0] <= Ain[7:0];
RA[11:8] <= 4'b0000; // Hold DQMs
end 4'h4: begin
// Mask everything // PC all CKE
DQML <= 1'b1; CKE <= 1'b1;
DQMH <= 1'b1; nRAS <= 1'b0;
nCAS <= 1'b1;
// Inhibit data bus output nRWE <= 1'b0;
DOEEN <= 1'b0; // Hold BA
end else if (S==4'h6) begin // Hold RA[11]
// Enable clock RA[10] <= 1'b1; // "all"
// Hold RA[9:0]
// Hold DQMs
end 4'h5: begin
if (RefReq) begin
// AREF CKE
CKE <= 1'b1; CKE <= 1'b1;
if (FS[5:4]==0) begin
// Auto-refresh
nCS <= 1'b0;
nRAS <= 1'b0; nRAS <= 1'b0;
nCAS <= 1'b0; nCAS <= 1'b0;
nRWE <= 1'b1; nRWE <= 1'b1;
end else begin end else begin
// NOP // NOP CKD
nCS <= 1'b1; CKE <= 1'b0;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end end
// Hold BA
// Don't care bank, RA[11:8] // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h6: begin
// NOP CKD
// Mask everything CKE <= 1'b0;
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h7) begin
// Enable clock
CKE <= 1'b1;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h7: begin
// Latch row address for activate command // Can't check EN80 at this time
if (nWE) begin // Read / idle
// NOP CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else begin // Write / idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
BA[1:0] <= RWBank[6:5];
RA[11:8] <= RWBank[4:1];
RA[7:0] <= Ain[7:0]; RA[7:0] <= Ain[7:0];
// Hold DQMs
// Mask everything end 4'h8: begin
DQML <= 1'b1; if (nEN80) begin // Idle
DQMH <= 1'b1; // NOP CKD
CKE <= 1'b0;
// Inhibit data bus output nRAS <= 1'b1;
DOEEN <= 1'b0; nCAS <= 1'b1;
end else if (S==4'h8) begin nRWE <= 1'b1;
// Enable clock if '245 output enabled end else if (nWE) begin // Read
CKE <= EN80; // ACT CKE
CKE <= 1'b1;
// Activate if '245 output enabled
nCS <= nEN80;
nRAS <= 1'b0; nRAS <= 1'b0;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end else begin // Write
// SDRAM bank, RA[11:8] determine by RamWorks bank // NOP CKE
BA[1:0] <= RWBank[5:4]; CKE <= 1'b1;
RA[11:8] <= RWBank[3:0]; nRAS <= 1'b1;
// Row address is as previously latched nCAS <= 1'b1;
nRWE <= 1'b1;
// Mask everything end
DQML <= 1'b1; // Hold BA
DQMH <= 1'b1; // Hold RA
// Hold DQMs
// Inhibit data bus output end 4'h9: begin
DOEEN <= 1'b0; if (nEN80) begin // Idle
end else if (S==4'h9) begin // NOP CKD
// Enable clock if '245 output enabled CKE <= 1'b0;
CKE <= EN80; nRAS <= 1'b1;
nCAS <= 1'b1;
// Read/Write if '245 output enabled nRWE <= 1'b1;
nCS <= nEN80; end else if (nWE) begin // Read
// RD CKE
CKE <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b0; nCAS <= 1'b0;
nRWE <= nWE80; nRWE <= 1'b1;
end else begin // Write
// SDRAM bank still determined by RamWorks, RA[11,9:8] don't care // ACT CKE
BA[1:0] <= RWBank[5:4]; CKE <= 1'b1;
RA[11] <= 1'b0; nRAS <= 1'b0;
RA[10] <= 1'b1; // (A10 set to auto-precharge) nCAS <= 1'b1;
RA[9] <= 1'b0; nRWE <= 1'b1;
end
// Hold BA
RA[11:9] <= 3'b000; // no auto-precharge
RA[8] <= RWBank[7]; RA[8] <= RWBank[7];
// Latch column address for R/W command
RA[7:0] <= Ain[7:0]; RA[7:0] <= Ain[7:0];
DQMH <= !RWBank[0];
// Latch RAMWorks low nybble write select using old row address DQMH <= RWBank[0];
RWSel <= RA[0] && !RA[3] && !nWE && !nC07X; end 4'hA: begin
if (nEN80) begin // Idle
// Mask according to RAMWorks bank (high byte is +4MB) // NOP CKD
DQML <= RWBank[6];
DQMH <= !RWBank[6];
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'hA) begin
// Enable clock if '245 output enabled
CKE <= EN80;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Don't care bank, RA[11:8]
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'hB) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold RA[10]
// Don't care bank, RA[11:8] end else if (nWE) begin // Read
BA[1:0] <= 2'b00; // PC all CKD
RA[11:8] <= 4'b0000;
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Enable data bus output
DOEEN <= 1'b1;
end else if (S==4'hC) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
nRAS <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b0;
RA[10] <= 1'b1;
// Don't care bank, RA[11:8] end else begin // Write
BA[1:0] <= 2'b00; // WR CKE
RA[11:8] <= 4'b0000; CKE <= 1'b1;
nRAS <= 1'b1;
// Mask everything nCAS <= 1'b0;
DQML <= 1'b1; nRWE <= 1'b0;
DQMH <= 1'b1; RA[10] <= 1'b0;
// Enable data bus output
DOEEN <= 1'b1;
// RAMWorks Bank Register Select
if (RWSel) begin
// Latch RAMWorks bank if accessed
if (CmdSetRWBankFFLED ||
//CmdSetRWBankFFMAX ||
//CmdSetRWBankFFSPI ||
CmdSetRWBankFFMXO2 ||
(CmdLEDGet && LEDEN)) RWBank <= 8'hFF;
else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]};
// Recognize command sequence and advance CS state
if ((CS==3'h0 && Din[7:0]==8'hFF) ||
(CS==3'h1 && Din[7:0]==8'h00) ||
(CS==3'h2 && Din[7:0]==8'h55) ||
(CS==3'h3 && Din[7:0]==8'hAA) ||
(CS==3'h4 && Din[7:0]==8'hC1) ||
(CS==3'h5 && Din[7:0]==8'hAD) ||
CS==3'h6 || CS==3'h7) CS <= CS+3'h1;
else CS <= 0; // Back to beginning if it's not right
if (CS==3'h6) begin // Recognize and submit command in CS6
//CmdSetRWBankFFMAX <= Din[7:0]==8'hFF;
//CmdSetRWBankFFSPI <= Din[7:0]==8'hFE;
CmdSetRWBankFFMXO2 <= Din[7:0]==8'hFD;
CmdSetRWBankFFLED <= Din[7:0]==8'hF0;
CmdRWMaskSet <= Din[7:0]==8'hE0;
CmdLEDSet <= Din[7:0]==8'hE2;
CmdLEDGet <= Din[7:0]==8'hE3;
//CmdBitbangMAX <= Din[7:0]==8'hEA;
//CmdBitbangSPI <= Din[7:0]==8'hEB;
CmdBitbangMXO2 <= Din[7:0]==8'hEC;
CmdExecMXO2 <= Din[7:0]==8'hED;
//if (Din[7:0]==8'hEE) CmdEraseMAX <= 1;
//if (Din[7:0]==8'hEF) CmdPrgmMAX <= 1;
end else begin // Reset command triggers
//CmdSetRWBankFFMAX <= 0;
//CmdSetRWBankFFSPI <= 0;
CmdSetRWBankFFMXO2 <= 0;
CmdSetRWBankFFLED <= 0;
CmdRWMaskSet <= 0;
CmdLEDSet <= 0;
CmdLEDGet <= 0;
//CmdBitbangMAX <= 0;
//CmdBitbangSPI <= 0;
CmdBitbangMXO2 <= 0;
CmdExecMXO2 <= 0;
end end
// Hold BA
CmdTout <= 0; // Reset command timeout if RWSel accessed // Hold RA[11,9:0]
end else begin // Hold DQMs
CmdTout <= CmdTout+3'h1; // Increment command timeout end 4'hB: begin
// If command sequence times out, reset sequence state if (nEN80) begin // Idle
if (CmdTout==3'h7) CS <= 0; // NOP CKD
end
end else if (S==4'hD) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end else if (nWE) begin // Read
// Don't care bank, RA[11:8] // NOP CKD
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Enable data bus output
DOEEN <= 1'b1;
end else if (S==4'hE) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end else begin // Write
// Don't care bank, RA[11:8] // NOP CKE
BA[1:0] <= 2'b00; CKE <= 1'b1;
RA[11:8] <= 4'b0000; nRAS <= 1'b1;
// Latch row address for next video read nCAS <= 1'b1;
RA[7:0] <= Ain[7:0]; nRWE <= 1'b1;
end
// Mask everything // Hold BA
DQML <= 1'b1; // Hold RA[11:0]
DQMH <= 1'b1; // Hold DQMs
end 4'hC: begin
// Enable data bus output if (nEN80) begin // Idle
DOEEN <= 1'b1; // NOP CKD
end else if (S==4'hF) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold RA[10]
// Don't care bank, RA[11:8] end else if (nWE) begin // Read
BA[1:0] <= 2'b00; // NOP CKD
RA[11:8] <= 4'b0000; CKE <= 1'b0;
// Latch row address for next video read nRAS <= 1'b1;
RA[7:0] <= Ain[7:0]; nCAS <= 1'b1;
nRWE <= 1'b1;
// Mask everything // Hold RA[10]
DQML <= 1'b1; end else begin // Write
DQMH <= 1'b1; // PC all CKD
CKE <= 1'b0;
// Enable data bus output nRAS <= 1'b0;
DOEEN <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1; // "all"
end end
// Hold BA
// Hold RA[11,9:0]
// Hold RA[7:0]
// Hold DQMs
end 4'hD: begin
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold BA
// Hold RA[11:0]
// Hold DQMs
end 4'hE, 4'hF: begin
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold BA
// Hold RA[11:8]
RA[7:0] <= Ain[7:0]; // Latch row address for next video read
// Hold DQMs
end end
always @(negedge C14M) begin endcase
// Latch video and read data outputs
if (S==4'h6) Vout[7:0] <= RD[7:0];
if (S==4'hC) Dout[7:0] <= RD[7:0];
end
endmodule endmodule

View File

@ -1,8 +1,8 @@
module RAM2E(C14M, PHI1, LED, module RAM2E(C14M, PHI1, LED,
nWE, nWE80, nEN80, nC07X, nWE, nWE80, nEN80, nC07X,
Ain, Din, Dout, nDOE, Vout, nVOE, Ain, Din, Dout, nDOE, Vout, nVOE,
CKE, nCS, nRAS, nCAS, nRWE, CKEout, nCSout, nRASout, nCASout, nRWEout,
BA, RA, RD, DQML, DQMH); BA, RAout, DQML, DQMH, RD);
/* Clocks */ /* Clocks */
input C14M, PHI1; input C14M, PHI1;
@ -10,50 +10,67 @@ module RAM2E(C14M, PHI1, LED,
/* Control inputs */ /* Control inputs */
input nWE, nWE80, nEN80, nC07X; input nWE, nWE80, nEN80, nC07X;
/* Delay for EN80 signal */
//output DelayOut = 1'b0;
//input DelayIn;
wire EN80 = !nEN80;
/* Activity LED */ /* Activity LED */
reg LEDEN = 0; reg LEDEN = 0;
output LED; output LED; assign LED = !(!nEN80 && LEDEN && Ready);
assign LED = !(!nEN80 && LEDEN);
/* Address Bus */ /* Address Bus */
input [7:0] Ain; // Multiplexed DRAM address input input [7:0] Ain; // Multiplexed DRAM address input
/* 6502 Data Bus */ /* 6502 Data Bus */
input [7:0] Din; // 6502 data bus inputs input [7:0] Din; // 6502 data bus inputs
reg DOEEN = 0; // 6502 data bus output enable from state machine reg DOEEN;
output nDOE; always @(posedge C14M) begin
assign nDOE = !(EN80 && nWE && DOEEN); // 6502 data bus output enable DOEEN <= /*(S==4'h8) || (S==4'h9) || (S==4'hA) ||*/ (S==4'hB) ||
output reg [7:0] Dout; // 6502 data Bus output (S==4'hC) || (S==4'hD) || (S==4'hE) || (S==4'hF);
end
output nDOE; assign nDOE = !(!nEN80 && nWE && DOEEN);
output [7:0] Dout; assign Dout[7:0] = RD[7:0];
/* Video Data Bus */ /* Video Data Bus */
output nVOE; reg VOEEN;
assign nVOE = !(!PHI1); /// Video data bus output enable always @(posedge C14M) begin
VOEEN <= (S==4'h7) ||
(S==4'h8) || (S==4'h9) || (S==4'hA) || (S==4'hB) ||
(S==4'hC) || (S==4'hD) || (S==4'hE) || (S==4'hF);
end
output nVOE; assign nVOE = !(!PHI1 && VOEEN);
output reg [7:0] Vout; // Video data bus output reg [7:0] Vout; // Video data bus
always @(posedge C14M) if (S==4'h6) Vout[7:0] <= RD[7:0];
/* SDRAM */ /* SDRAM */
output reg CKE = 0; reg CKE = 1;
output reg nCS = 1, nRAS = 1, nCAS = 1, nRWE = 1; //reg nCS = 1;
reg nRAS = 1, nCAS = 1, nRWE = 1;
output reg [1:0] BA; output reg [1:0] BA;
output reg [11:0] RA; reg [11:0] RA;
output reg DQML = 1, DQMH = 1; output reg DQML = 1, DQMH = 1;
wire RDOE = EN80 && !nWE80;
inout [7:0] RD; inout [7:0] RD;
assign RD[7:0] = RDOE ? Din[7:0] : 8'bZ; assign RD[7:0] = Ready ? (!nWE80 ? Din[7:0] : 8'bZ) : 8'h00;
/* SDRAM falling edge outputs */
output reg CKEout;
output nCSout; assign nCSout = 0;
output reg nRASout = 1, nCASout = 1, nRWEout = 1;
output reg [11:0] RAout;
always @(negedge C14M) begin
CKEout <= CKE;
nRASout <= nRAS;
nCASout <= nCAS;
nRWEout <= nRWE;
RAout <= RA;
end
/* RAMWorks Bank Register and Capacity Mask */ /* RAMWorks Bank Register and Capacity Mask */
reg [7:0] RWBank = 0; // RAMWorks bank register reg [7:0] RWBank = 0; // RAMWorks bank register
reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask
reg RWSel = 0; // RAMWorks bank register select reg RWSel = 0; // RAMWorks bank register select
always @(posedge C14M) begin
if (S==4'h9) RWSel <= RA[0] && !RA[3] && !nWE && !nC07X;
end
reg CmdRWMaskSet = 0; // RAMWorks Mask register set flag reg CmdRWMaskSet = 0; // RAMWorks Mask register set flag
// Causes RWBank to be zeroed next RWSel access // Causes RWBank to be zeroed next RWSel access
reg CmdSetRWBankFFMAX = 0; reg CmdSetRWBankFFChip = 0;
//reg CmdSetRWBankFFSPI = 0;
//reg CmdSetRWBankFFMXO2 = 0;
reg CmdSetRWBankFFLED = 0; reg CmdSetRWBankFFLED = 0;
reg CmdLEDSet = 0; reg CmdLEDSet = 0;
reg CmdLEDGet = 0; reg CmdLEDGet = 0;
@ -92,23 +109,24 @@ module RAM2E(C14M, PHI1, LED,
.osc (UFMOsc), .osc (UFMOsc),
.rtpbusy (RTPBusy)); .rtpbusy (RTPBusy));
reg UFMRTPBusy = 0; reg UFMRTPBusy = 0;
always @(posedge C14M) begin UFMRTPBusy <= UFMBusy || RTPBusy; always @(posedge C14M) UFMRTPBusy <= UFMBusy || RTPBusy;
/* UFM State and User Command Triggers */
reg UFMInitDone = 0; // 1 if UFM initialization finished reg UFMInitDone = 0; // 1 if UFM initialization finished
reg UFMReqErase = 0; // 1 if UFM requires erase reg UFMReqErase = 0; // 1 if UFM requires erase
reg DRCLKPulse = 0; // Set by user command. Causes DRCLK pulse next C14M
/* User Command Triggers */
reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel reg CmdBitbangMAX = 0; // Set by user command. Loads UFM outputs next RWSel
//reg CmdBitbangSPI = 0; //reg CmdBitbangSPI = 0;
//reg CmdBitbangMXO2 = 0; //reg CmdBitbangMXO2 = 0;
//reg CmdExecMXO2 = 0; //reg CmdExecMXO2 = 0;
reg CmdPrgmMAX = 0; // Set by user command. Programs UFM reg CmdPrgmMAX = 0; // Set by user command. Programs UFM
reg CmdEraseMAX = 0; // Set by user command. Erases UFM reg CmdEraseMAX = 0; // Set by user command. Erases UFM
reg DRCLKPulse = 0; // Set by user command. Causes DRCLK pulse next C14M
/* State Counters */ /* State Counters */
reg PHI1reg = 0; // Saved PHI1 at last rising clock edge reg PHI1reg = 0; // Saved PHI1 at last rising clock edge
reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15 reg Ready = 0; // 1 if done with init sequence (S0) and enter S1-S15
reg [15:0] FS = 0; // Fast state counter reg [15:0] FS = 0; // Fast state counter
wire RefReq = FS[5:4]==0; // Refresh request based on fast state counter
reg [3:0] S = 0; // IIe State counter reg [3:0] S = 0; // IIe State counter
/* State Counters */ /* State Counters */
@ -118,8 +136,32 @@ module RAM2E(C14M, PHI1, LED,
// Synchronize Apple state counter to S1 when just entering PHI1 // Synchronize Apple state counter to S1 when just entering PHI1
PHI1reg <= PHI1; // Save old PHI1 PHI1reg <= PHI1; // Save old PHI1
S <= (PHI1 && !PHI1reg && Ready) ? 4'h1 : S <= (PHI1 && !PHI1reg && Ready) ? 4'h1 :
S==4'h0 ? 4'h0 : (S==4'h0) ? 4'h0 :
S==4'hF ? 4'hF : S+4'h1; (S==4'hF) ? 4'hF : S+4'h1;
// Begin normal operation after 64k init cycles (~4.59ms)
if (FS[15:0]==16'hFFFF) Ready <= 1'b1;
end
/* Command sequence control */
always @(posedge C14M) begin
if (S==4'hC) begin
if (RWSel) begin
CmdTout <= 0; // Reset command timeout if RWSel accessed
// Recognize command sequence and advance CS state
if ((CS==3'h0 && Din[7:0]==8'hFF) ||
(CS==3'h1 && Din[7:0]==8'h00) ||
(CS==3'h2 && Din[7:0]==8'h55) ||
(CS==3'h3 && Din[7:0]==8'hAA) ||
(CS==3'h4 && Din[7:0]==8'hC1) ||
(CS==3'h5 && Din[7:0]==8'hAD) ||
CS==3'h6 || CS==3'h7) CS <= CS+3'h1;
else CS <= 0; // Back to beginning if it's not right
end else begin
CmdTout <= CmdTout+3'h1; // Increment command timeout
// If command sequence times out, reset sequence state
if (CmdTout==3'h7) CS <= 0;
end
end
end end
/* UFM Control */ /* UFM Control */
@ -204,10 +246,10 @@ module RAM2E(C14M, PHI1, LED,
DRCLK <= DRCLKPulse; DRCLK <= DRCLKPulse;
end end
// Volatile settings command execution
if (RWSel && S==4'hC) begin if (RWSel && S==4'hC) begin
// LED control // LED control
if (CmdLEDSet) LEDEN <= Din[0]; if (CmdLEDSet) LEDEN <= Din[0];
// Set capacity mask // Set capacity mask
if (CmdRWMaskSet) RWMask[7:0] <= {Din[7], ~Din[6:0]}; if (CmdRWMaskSet) RWMask[7:0] <= {Din[7], ~Din[6:0]};
end end
@ -227,463 +269,372 @@ module RAM2E(C14M, PHI1, LED,
end end
end end
/* SDRAM Control */ /* RAMWorks register control - bank, LED, etc. */
always @(posedge C14M) begin always @(posedge C14M) begin
if (S==4'h0) begin if (S==4'hC && RWSel) begin
// SDRAM initialization // Latch RAMWorks bank if accessed
if (FS[15:0]==16'hFFC0) begin if ((CmdSetRWBankFFLED) ||
// Precharge All (CmdSetRWBankFFChip) ||
nCS <= 1'b0; (CmdLEDGet && LEDEN)) RWBank <= 8'hFF;
nRAS <= 1'b0; else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]};
nCAS <= 1'b1;
nRWE <= 1'b0; if (CS==3'h6) begin // Recognize and submit command in CS6
RA[10] <= 1'b1; // "all" // Board has LED detect command
end else if (FS[15:4]==16'hFFD && FS[0]==1'b0) begin // Repeat 8x CmdSetRWBankFFLED <= Din[7:0]==8'hF0;
// Auto-refresh
nCS <= 1'b0; // Volatile commands
nRAS <= 1'b0; CmdRWMaskSet <= Din[7:0]==8'hE0;
nCAS <= 1'b0; CmdLEDSet <= Din[7:0]==8'hE2;
nRWE <= 1'b1; CmdLEDGet <= Din[7:0]==8'hE3;
RA[10] <= 1'b0; end else begin // Reset command triggers
end else if (FS[15:0]==16'hFFE8) begin CmdSetRWBankFFLED <= 0;
// Set Mode Register CmdRWMaskSet <= 0;
nCS <= 1'b0; CmdLEDSet <= 0;
nRAS <= 1'b0; CmdLEDGet <= 0;
nCAS <= 1'b0; end
nRWE <= 1'b0; end
RA[10] <= 1'b0; // Reserved in mode register end
end else if (FS[15:4]==12'hFFF && FS[0]==1'b0) begin // Repeat 8x
// Auto-refresh /* RAMWorks register control - Altera MAX */
nCS <= 1'b0; always @(posedge C14M) begin
nRAS <= 1'b0; if (S==4'hC && RWSel) begin
nCAS <= 1'b0; if (CS==3'h6) begin // Recognize and submit command in CS6
nRWE <= 1'b1; // Chip detection commands
RA[10] <= 1'b0; CmdSetRWBankFFChip <= Din[7:0]==8'hFF; // MAX
end else begin // Otherwise send no-op //CmdSetRWBankFFChip <= Din[7:0]==8'hFE; // SPI
//CmdSetRWBankFFChip <= Din[7:0]==8'hFD; // MachXO2
// Altera MAX II/V commands
CmdBitbangMAX <= Din[7:0]==8'hEA;
if (!CmdEraseMAX && !CmdPrgmMAX) begin
if (Din[7:0]==8'hEE) CmdEraseMAX <= 1;
if (Din[7:0]==8'hEF) CmdPrgmMAX <= 1;
end
// SPI commands
//CmdBitbangSPI <= Din[7:0]==8'hEB;
// MachXO2 commands
//CmdBitbangMXO2 <= Din[7:0]==8'hEC;
//CmdExecMXO2 <= Din[7:0]==8'hED;
end else begin // Reset command triggers
CmdSetRWBankFFChip <= 0;
CmdBitbangMAX <= 0;
//CmdBitbangSPI <= 0;
//CmdBitbangMXO2 <= 0;
//CmdExecMXO2 <= 0;
end
end
end
/* SDRAM Control */
always @(posedge C14M) case (S)
4'h0: begin
CKE <= 1'b1;
if (!FS[15] || FS[0]) begin
// NOP // NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
RA[10] <= 1'b0; end else case (FS[4:1])
4'h0: begin
// PC all
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
end 4'h1: begin
// LDM
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b0;
end 4'h2: begin
// NOP
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end 4'h3, 4'h4, 4'h5, 4'h6,
4'h7, 4'h8, 4'h9, 4'hA: begin
// AREF
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b1;
end 4'hB: begin
// ACT
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
end 4'hC, 4'hD: begin
// WR
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b0;
end 4'hE: begin
// NOP
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end 4'hF: begin
// PC all
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
end end
// Enable SDRAM clock after 65,280 cycles (~4.56ms) endcase
CKE <= FS[15:8] == 8'hFF; case (FS[4:3])
2'b00, 2'b01: begin
// Mode register contents // Mode register contents
BA[1:0] <= 2'b00; // Reserved BA[1:0] <= 2'b00; // Reserved
RA[11] <= 1'b0; // Reserved RA[11] <= 1'b0; // Reserved
// RA[10] set above ^ RA[10] <= !FS[1]; // reserved / "all"
RA[9] <= 1'b1; // "1" for single write mode RA[9] <= 1'b1; // "1" for single write mode
RA[8] <= 1'b0; // Reserved RA[8] <= 1'b0; // Reserved
RA[7] <= 1'b0; // "0" for not test mode RA[7] <= 1'b0; // "0" for not test mode
RA[6:4] <= 3'b010; // "2" for CAS latency 2 RA[6:4] <= 3'b010; // "2" for CAS latency 2
RA[3] <= 1'b0; // "0" for sequential burst (not used) RA[3] <= 1'b0; // "0" for sequential burst (not used)
RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst) RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst)
end 2'b10: begin
// Mask everything BA[1:0] <= 2'b00;
DQML <= 1'b1; RA[11:8] <= 4'h0;
DQMH <= 1'b1; RA[7:0] <= FS[14:7];
end 2'b11: begin
// Inhibit data bus output BA[1:0] <= 2'b00;
DOEEN <= 1'b0; RA[11:3] <= 9'h000;
RA[2:1] <= FS[6:5];
// Begin normal operation after 128k init cycles (~9.15ms) RA[0] <= FS[1];
if (FS == 16'hFFFF) Ready <= 1'b1; end
end else if (S==4'h1) begin endcase
// Enable clock DQML <= !FS[15];
DQMH <= !FS[15];
end 4'h1: begin
// NOP CKE
CKE <= 1'b1; CKE <= 1'b1;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Don't care bank, RA[11:8]
BA[1:0] <= 2'b00; BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000; RA[11:8] <= 4'b0000;
// Hold RA[7:0]
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h2) begin
// Enable clock
CKE <= 1'b1;
// Activate
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
// SDRAM bank 0, high-order row address is 0
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Row address is as previously latched
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h3) begin
// Enable clock
CKE <= 1'b1;
// Read
nCS <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b1;
// SDRAM bank 0, RA[11,9:8] don't care
BA[1:0] <= 2'b00;
RA[11] <= 1'b0;
RA[10] <= 1'b1; // (A10 set to auto-precharge)
RA[9] <= 1'b0;
RA[8] <= 1'b0;
// Latch column address for read command
RA[7:0] <= Ain[7:0];
// Read low byte (high byte is +4MB in ramworks)
DQML <= 1'b0; DQML <= 1'b0;
DQMH <= 1'b1; DQMH <= 1'b1;
end 4'h2: begin
// Inhibit data bus output // ACT CKE
DOEEN <= 1'b0;
end else if (S==4'h4) begin
// Enable clock
CKE <= 1'b1; CKE <= 1'b1;
nRAS <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h3: begin
// RD CKE
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h5) begin
// Enable clock
CKE <= 1'b1; CKE <= 1'b1;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b0;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA[11:8]
BA[1:0] <= 2'b00; RA[7:0] <= Ain[7:0];
RA[11:8] <= 4'b0000; // Hold DQMs
end 4'h4: begin
// Mask everything // PC all CKE
DQML <= 1'b1; CKE <= 1'b1;
DQMH <= 1'b1; nRAS <= 1'b0;
nCAS <= 1'b1;
// Inhibit data bus output nRWE <= 1'b0;
DOEEN <= 1'b0; // Hold BA
end else if (S==4'h6) begin // Hold RA[11]
// Enable clock RA[10] <= 1'b1; // "all"
// Hold RA[9:0]
// Hold DQMs
end 4'h5: begin
if (RefReq) begin
// AREF CKE
CKE <= 1'b1; CKE <= 1'b1;
if (FS[5:4]==0) begin
// Auto-refresh
nCS <= 1'b0;
nRAS <= 1'b0; nRAS <= 1'b0;
nCAS <= 1'b0; nCAS <= 1'b0;
nRWE <= 1'b1; nRWE <= 1'b1;
end else begin end else begin
// NOP // NOP CKD
nCS <= 1'b1; CKE <= 1'b0;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end end
// Hold BA
// Don't care bank, RA[11:8] // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h6: begin
// NOP CKD
// Mask everything CKE <= 1'b0;
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h7) begin
// Enable clock
CKE <= 1'b1;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h7: begin
// Latch row address for activate command // Can't check EN80 at this time
if (nWE) begin // Read / idle
// NOP CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else begin // Write / idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
BA[1:0] <= RWBank[6:5];
RA[11:8] <= RWBank[4:1];
RA[7:0] <= Ain[7:0]; RA[7:0] <= Ain[7:0];
// Hold DQMs
// Mask everything end 4'h8: begin
DQML <= 1'b1; if (nEN80) begin // Idle
DQMH <= 1'b1; // NOP CKD
CKE <= 1'b0;
// Inhibit data bus output nRAS <= 1'b1;
DOEEN <= 1'b0; nCAS <= 1'b1;
end else if (S==4'h8) begin nRWE <= 1'b1;
// Enable clock if '245 output enabled end else if (nWE) begin // Read
CKE <= EN80; // ACT CKE
CKE <= 1'b1;
// Activate if '245 output enabled
nCS <= nEN80;
nRAS <= 1'b0; nRAS <= 1'b0;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end else begin // Write
// SDRAM bank, RA[11:8] determine by RamWorks bank // NOP CKE
BA[1:0] <= RWBank[5:4]; CKE <= 1'b1;
RA[11:8] <= RWBank[3:0]; nRAS <= 1'b1;
// Row address is as previously latched nCAS <= 1'b1;
nRWE <= 1'b1;
// Mask everything end
DQML <= 1'b1; // Hold BA
DQMH <= 1'b1; // Hold RA
// Hold DQMs
// Inhibit data bus output end 4'h9: begin
DOEEN <= 1'b0; if (nEN80) begin // Idle
end else if (S==4'h9) begin // NOP CKD
// Enable clock if '245 output enabled CKE <= 1'b0;
CKE <= EN80; nRAS <= 1'b1;
nCAS <= 1'b1;
// Read/Write if '245 output enabled nRWE <= 1'b1;
nCS <= nEN80; end else if (nWE) begin // Read
// RD CKE
CKE <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b0; nCAS <= 1'b0;
nRWE <= nWE80; nRWE <= 1'b1;
end else begin // Write
// SDRAM bank still determined by RamWorks, RA[11,9:8] don't care // ACT CKE
BA[1:0] <= RWBank[5:4]; CKE <= 1'b1;
RA[11] <= 1'b0; nRAS <= 1'b0;
RA[10] <= 1'b1; // (A10 set to auto-precharge) nCAS <= 1'b1;
RA[9] <= 1'b0; nRWE <= 1'b1;
end
// Hold BA
RA[11:9] <= 3'b000; // no auto-precharge
RA[8] <= RWBank[7]; RA[8] <= RWBank[7];
// Latch column address for R/W command
RA[7:0] <= Ain[7:0]; RA[7:0] <= Ain[7:0];
DQMH <= !RWBank[0];
// Latch RAMWorks low nybble write select using old row address DQMH <= RWBank[0];
RWSel <= RA[0] && !RA[3] && !nWE && !nC07X; end 4'hA: begin
if (nEN80) begin // Idle
// Mask according to RAMWorks bank (high byte is +4MB) // NOP CKD
DQML <= RWBank[6];
DQMH <= !RWBank[6];
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'hA) begin
// Enable clock if '245 output enabled
CKE <= EN80;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Don't care bank, RA[11:8]
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'hB) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold RA[10]
// Don't care bank, RA[11:8] end else if (nWE) begin // Read
BA[1:0] <= 2'b00; // PC all CKD
RA[11:8] <= 4'b0000;
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Enable data bus output
DOEEN <= 1'b1;
end else if (S==4'hC) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
nRAS <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b0;
RA[10] <= 1'b1;
// Don't care bank, RA[11:8] end else begin // Write
BA[1:0] <= 2'b00; // WR CKE
RA[11:8] <= 4'b0000; CKE <= 1'b1;
nRAS <= 1'b1;
// Mask everything nCAS <= 1'b0;
DQML <= 1'b1; nRWE <= 1'b0;
DQMH <= 1'b1; RA[10] <= 1'b0;
// Enable data bus output
DOEEN <= 1'b1;
// RAMWorks Bank Register Select
if (RWSel) begin
// Latch RAMWorks bank if accessed
if (CmdSetRWBankFFLED ||
CmdSetRWBankFFMAX ||
//CmdSetRWBankFFSPI ||
//CmdSetRWBankFFMXO2 ||
(CmdLEDGet && LEDEN)) RWBank <= 8'hFF;
else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]};
// Recognize command sequence and advance CS state
if ((CS==3'h0 && Din[7:0]==8'hFF) ||
(CS==3'h1 && Din[7:0]==8'h00) ||
(CS==3'h2 && Din[7:0]==8'h55) ||
(CS==3'h3 && Din[7:0]==8'hAA) ||
(CS==3'h4 && Din[7:0]==8'hC1) ||
(CS==3'h5 && Din[7:0]==8'hAD) ||
CS==3'h6 || CS==3'h7) CS <= CS+3'h1;
else CS <= 0; // Back to beginning if it's not right
if (CS==3'h6) begin // Recognize and submit command in CS6
CmdSetRWBankFFMAX <= Din[7:0]==8'hFF;
//CmdSetRWBankFFSPI <= Din[7:0]==8'hFE;
//CmdSetRWBankFFMXO2 <= Din[7:0]==8'hFD;
CmdSetRWBankFFLED <= Din[7:0]==8'hF0;
CmdRWMaskSet <= Din[7:0]==8'hE0;
CmdLEDSet <= Din[7:0]==8'hE2;
CmdLEDGet <= Din[7:0]==8'hE3;
CmdBitbangMAX <= Din[7:0]==8'hEA;
//CmdBitbangSPI <= Din[7:0]==8'hEB;
//CmdBitbangMXO2 <= Din[7:0]==8'hEC;
//CmdExecMXO2 <= Din[7:0]==8'hED;
if (!CmdEraseMAX && !CmdPrgmMAX) begin
if (Din[7:0]==8'hEE) CmdEraseMAX <= 1;
if (Din[7:0]==8'hEF) CmdPrgmMAX <= 1;
end end
end else begin // Reset command triggers // Hold BA
CmdSetRWBankFFMAX <= 0; // Hold RA[11,9:0]
//CmdSetRWBankFFSPI <= 0; // Hold DQMs
//CmdSetRWBankFFMXO2 <= 0; end 4'hB: begin
CmdSetRWBankFFLED <= 0; if (nEN80) begin // Idle
CmdRWMaskSet <= 0; // NOP CKD
CmdLEDSet <= 0;
CmdLEDGet <= 0;
CmdBitbangMAX <= 0;
//CmdBitbangSPI <= 0;
//CmdBitbangMXO2 <= 0;
//CmdExecMXO2 <= 0;
end
CmdTout <= 0; // Reset command timeout if RWSel accessed
end else begin
CmdTout <= CmdTout+3'h1; // Increment command timeout
// If command sequence times out, reset sequence state
if (CmdTout==3'h7) CS <= 0;
end
end else if (S==4'hD) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end else if (nWE) begin // Read
// Don't care bank, RA[11:8] // NOP CKD
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Enable data bus output
DOEEN <= 1'b1;
end else if (S==4'hE) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
end else begin // Write
// Don't care bank, RA[11:8] // NOP CKE
BA[1:0] <= 2'b00; CKE <= 1'b1;
RA[11:8] <= 4'b0000; nRAS <= 1'b1;
// Latch row address for next video read nCAS <= 1'b1;
RA[7:0] <= Ain[7:0]; nRWE <= 1'b1;
end
// Mask everything // Hold BA
DQML <= 1'b1; // Hold RA[11:0]
DQMH <= 1'b1; // Hold DQMs
end 4'hC: begin
// Enable data bus output if (nEN80) begin // Idle
DOEEN <= 1'b1; // NOP CKD
end else if (S==4'hF) begin
// Disable clock
CKE <= 1'b0; CKE <= 1'b0;
// NOP
nCS <= 1'b1;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold RA[10]
// Don't care bank, RA[11:8] end else if (nWE) begin // Read
BA[1:0] <= 2'b00; // NOP CKD
RA[11:8] <= 4'b0000; CKE <= 1'b0;
// Latch row address for next video read nRAS <= 1'b1;
RA[7:0] <= Ain[7:0]; nCAS <= 1'b1;
nRWE <= 1'b1;
// Mask everything // Hold RA[10]
DQML <= 1'b1; end else begin // Write
DQMH <= 1'b1; // PC all CKD
CKE <= 1'b0;
// Enable data bus output nRAS <= 1'b0;
DOEEN <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1; // "all"
end end
// Hold BA
// Hold RA[11,9:0]
// Hold RA[7:0]
// Hold DQMs
end 4'hD: begin
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold BA
// Hold RA[11:0]
// Hold DQMs
end 4'hE, 4'hF: begin
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold BA
// Hold RA[11:8]
RA[7:0] <= Ain[7:0]; // Latch row address for next video read
// Hold DQMs
end end
always @(negedge C14M) begin endcase
// Latch video and read data outputs
if (S==4'h6) Vout[7:0] <= RD[7:0];
if (S==4'hC) Dout[7:0] <= RD[7:0];
end
endmodule endmodule