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,59 +1,76 @@
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;
/* 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 */
@ -370,462 +412,374 @@ module RAM2E(C14M, PHI1, LED,
end end
end end
end end
/* RAMWorks register control - bank, LED, etc. */
always @(posedge C14M) begin
if (S==4'hC && RWSel) begin
// Latch RAMWorks bank if accessed
if ((CmdSetRWBankFFLED) ||
(CmdSetRWBankFFChip) ||
(CmdLEDGet && LEDEN)) RWBank <= 8'hFF;
else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]};
if (CS==3'h6) begin // Recognize and submit command in CS6
// Board has LED detect command
CmdSetRWBankFFLED <= Din[7:0]==8'hF0;
// Volatile commands
CmdRWMaskSet <= Din[7:0]==8'hE0;
CmdLEDSet <= Din[7:0]==8'hE2;
CmdLEDGet <= Din[7:0]==8'hE3;
end else begin // Reset command triggers
CmdSetRWBankFFLED <= 0;
CmdRWMaskSet <= 0;
CmdLEDSet <= 0;
CmdLEDGet <= 0;
end
end
end
/* RAMWorks register control - Lattice MachXO2 */
always @(posedge C14M) begin
if (S==4'hC && RWSel) begin
if (CS==3'h6) begin // Recognize and submit command in CS6
// Chip detection commands
//CmdSetRWBankFFChip <= Din[7:0]==8'hFF; // MAX
//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 */ /* SDRAM Control */
always @(posedge C14M) begin always @(posedge C14M) case (S)
if (S==4'h0) begin 4'h0: begin
// SDRAM initialization CKE <= 1'b1;
if (FS[15:0]==16'hFFC0) begin if (!FS[15] || FS[0]) begin
// Precharge All
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1; // "all"
end else if (FS[15:4]==16'hFFD && FS[0]==1'b0) begin // Repeat 8x
// Auto-refresh
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b1;
RA[10] <= 1'b0;
end else if (FS[15:0]==16'hFFE8) begin
// Set Mode Register
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b0;
RA[10] <= 1'b0; // Reserved in mode register
end else if (FS[15:4]==12'hFFF && FS[0]==1'b0) begin // Repeat 8x
// Auto-refresh
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b1;
RA[10] <= 1'b0;
end else begin // Otherwise send no-op
// 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])
end 4'h0: begin
// Enable SDRAM clock after 65,280 cycles (~4.56ms) // PC all
CKE <= FS[15:8] == 8'hFF; nRAS <= 1'b0;
nCAS <= 1'b1;
// Mode register contents nRWE <= 1'b0;
BA[1:0] <= 2'b00; // Reserved end 4'h1: begin
RA[11] <= 1'b0; // Reserved // LDM
// RA[10] set above ^ nRAS <= 1'b0;
RA[9] <= 1'b1; // "1" for single write mode nCAS <= 1'b0;
RA[8] <= 1'b0; // Reserved nRWE <= 1'b0;
RA[7] <= 1'b0; // "0" for not test mode end 4'h2: begin
RA[6:4] <= 3'b010; // "2" for CAS latency 2 // NOP
RA[3] <= 1'b0; // "0" for sequential burst (not used) nRAS <= 1'b1;
RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst) nCAS <= 1'b1;
nRWE <= 1'b1;
// Mask everything end 4'h3, 4'h4, 4'h5, 4'h6,
DQML <= 1'b1; 4'h7, 4'h8, 4'h9, 4'hA: begin
DQMH <= 1'b1; // AREF
nRAS <= 1'b0;
// Inhibit data bus output nCAS <= 1'b0;
DOEEN <= 1'b0; nRWE <= 1'b1;
end 4'hB: begin
// Begin normal operation after 128k init cycles (~9.15ms) // ACT
if (FS == 16'hFFFF) Ready <= 1'b1; nRAS <= 1'b0;
end else if (S==4'h1) begin nCAS <= 1'b1;
// Enable clock 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
endcase
case (FS[4:3])
2'b00, 2'b01: begin
// Mode register contents
BA[1:0] <= 2'b00; // Reserved
RA[11] <= 1'b0; // Reserved
RA[10] <= !FS[1]; // reserved / "all"
RA[9] <= 1'b1; // "1" for single write mode
RA[8] <= 1'b0; // Reserved
RA[7] <= 1'b0; // "0" for not test mode
RA[6:4] <= 3'b010; // "2" for CAS latency 2
RA[3] <= 1'b0; // "0" for sequential burst (not used)
RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst)
end 2'b10: begin
BA[1:0] <= 2'b00;
RA[11:8] <= 4'h0;
RA[7:0] <= FS[14:7];
end 2'b11: begin
BA[1:0] <= 2'b00;
RA[11:3] <= 9'h000;
RA[2:1] <= FS[6:5];
RA[0] <= FS[1];
end
endcase
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'b0;
DQML <= 1'b1;
DQMH <= 1'b1; DQMH <= 1'b1;
end 4'h2: begin
// Inhibit data bus output // ACT CKE
DOEEN <= 1'b0;
end else if (S==4'h2) begin
// Enable clock
CKE <= 1'b1; CKE <= 1'b1;
// Activate
nCS <= 1'b0;
nRAS <= 1'b0; nRAS <= 1'b0;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// SDRAM bank 0, high-order row address is 0 // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h3: begin
// Row address is as previously latched // RD CKE
// 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; CKE <= 1'b1;
// Read
nCS <= 1'b0;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b0; nCAS <= 1'b0;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// SDRAM bank 0, RA[11,9:8] don't care // Hold RA[11:8]
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]; RA[7:0] <= Ain[7:0];
// Hold DQMs
// Read low byte (high byte is +4MB in ramworks) end 4'h4: begin
DQML <= 1'b0; // PC all CKE
DQMH <= 1'b1;
// Inhibit data bus output
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'b0;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA[11]
BA[1:0] <= 2'b00; RA[10] <= 1'b1; // "all"
RA[11:8] <= 4'b0000; // Hold RA[9:0]
// Hold DQMs
// Mask everything end 4'h5: begin
DQML <= 1'b1; if (RefReq) begin
DQMH <= 1'b1; // AREF CKE
CKE <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h5) begin
// Enable clock
CKE <= 1'b1;
// 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'h6) begin
// Enable clock
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
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;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Don't care bank, RA[11:8]
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Latch row address for activate command
RA[7:0] <= Ain[7:0];
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h8) begin
// Enable clock if '245 output enabled
CKE <= EN80;
// Activate if '245 output enabled
nCS <= nEN80;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
// SDRAM bank, RA[11:8] determine by RamWorks bank
BA[1:0] <= RWBank[5:4];
RA[11:8] <= RWBank[3:0];
// 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'h9) begin
// Enable clock if '245 output enabled
CKE <= EN80;
// Read/Write if '245 output enabled
nCS <= nEN80;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= nWE80;
// SDRAM bank still determined by RamWorks, RA[11,9:8] don't care
BA[1:0] <= RWBank[5:4];
RA[11] <= 1'b0;
RA[10] <= 1'b1; // (A10 set to auto-precharge)
RA[9] <= 1'b0;
RA[8] <= RWBank[7];
// Latch column address for R/W command
RA[7:0] <= Ain[7:0];
// Latch RAMWorks low nybble write select using old row address
RWSel <= RA[0] && !RA[3] && !nWE && !nC07X;
// Mask according to RAMWorks bank (high byte is +4MB)
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 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
// Can't check EN80 at this time
// Mask everything if (nWE) begin // Read / idle
DQML <= 1'b1; // NOP CKE
DQMH <= 1'b1; CKE <= 1'b1;
nRAS <= 1'b1;
// Enable data bus output nCAS <= 1'b1;
DOEEN <= 1'b1; nRWE <= 1'b1;
end else if (S==4'hC) begin end else begin // Write / idle
// Disable clock // NOP CKD
CKE <= 1'b0; CKE <= 1'b0;
nRAS <= 1'b1;
// NOP nCAS <= 1'b1;
nCS <= 1'b1; nRWE <= 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;
// 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
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
end else if (S==4'hD) begin BA[1:0] <= RWBank[6:5];
// Disable clock RA[11:8] <= RWBank[4:1];
CKE <= 1'b0;
// 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;
// Enable data bus output
DOEEN <= 1'b1;
end else if (S==4'hE) begin
// Disable clock
CKE <= 1'b0;
// 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;
// Latch row address for next video read
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;
// Enable data bus output nRAS <= 1'b1;
DOEEN <= 1'b1; nCAS <= 1'b1;
end else if (S==4'hF) begin nRWE <= 1'b1;
// Disable clock end else if (nWE) begin // Read
// ACT CKE
CKE <= 1'b1;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else begin // Write
// NOP CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
// Hold BA
// Hold RA
// Hold DQMs
end 4'h9: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else if (nWE) begin // Read
// RD CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b1;
end else begin // Write
// ACT CKE
CKE <= 1'b1;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
// Hold BA
RA[11:9] <= 3'b000; // no auto-precharge
RA[8] <= RWBank[7];
RA[7:0] <= Ain[7:0];
DQMH <= !RWBank[0];
DQMH <= RWBank[0];
end 4'hA: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold RA[10]
end else if (nWE) begin // Read
// PC all CKD
CKE <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1;
end else begin // Write
// WR CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b0;
RA[10] <= 1'b0;
end
// Hold BA
// Hold RA[11,9:0]
// Hold DQMs
end 4'hB: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else if (nWE) begin // Read
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else begin // Write
// NOP CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
// Hold BA
// Hold RA[11:0]
// Hold DQMs
end 4'hC: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold RA[10]
end else if (nWE) begin // Read
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold RA[10]
end else begin // Write
// PC all CKD
CKE <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1; // "all"
end
// Hold BA
// Hold RA[11,9:0]
// Hold RA[7:0]
// Hold DQMs
end 4'hD: begin
// NOP CKD
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 BA
// Don't care bank, RA[11:8] // Hold RA[11:0]
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'hE, 4'hF: begin
// Latch row address for next video read // NOP CKD
RA[7:0] <= Ain[7:0]; CKE <= 1'b0;
nRAS <= 1'b1;
// Mask everything nCAS <= 1'b1;
DQML <= 1'b1; nRWE <= 1'b1;
DQMH <= 1'b1; // Hold BA
// Hold RA[11:8]
// Enable data bus output RA[7:0] <= Ain[7:0]; // Latch row address for next video read
DOEEN <= 1'b1; // Hold DQMs
end end
end endcase
always @(negedge C14M) begin
// 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,59 +1,76 @@
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;
/* 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
@ -226,464 +268,373 @@ module RAM2E(C14M, PHI1, LED,
end end
end end
end end
/* RAMWorks register control - bank, LED, etc. */
always @(posedge C14M) begin
if (S==4'hC && RWSel) begin
// Latch RAMWorks bank if accessed
if ((CmdSetRWBankFFLED) ||
(CmdSetRWBankFFChip) ||
(CmdLEDGet && LEDEN)) RWBank <= 8'hFF;
else RWBank <= Din[7:0] & {RWMask[7], ~RWMask[6:0]};
if (CS==3'h6) begin // Recognize and submit command in CS6
// Board has LED detect command
CmdSetRWBankFFLED <= Din[7:0]==8'hF0;
// Volatile commands
CmdRWMaskSet <= Din[7:0]==8'hE0;
CmdLEDSet <= Din[7:0]==8'hE2;
CmdLEDGet <= Din[7:0]==8'hE3;
end else begin // Reset command triggers
CmdSetRWBankFFLED <= 0;
CmdRWMaskSet <= 0;
CmdLEDSet <= 0;
CmdLEDGet <= 0;
end
end
end
/* RAMWorks register control - Altera MAX */
always @(posedge C14M) begin
if (S==4'hC && RWSel) begin
if (CS==3'h6) begin // Recognize and submit command in CS6
// Chip detection commands
CmdSetRWBankFFChip <= Din[7:0]==8'hFF; // MAX
//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 */ /* SDRAM Control */
always @(posedge C14M) begin always @(posedge C14M) case (S)
if (S==4'h0) begin 4'h0: begin
// SDRAM initialization CKE <= 1'b1;
if (FS[15:0]==16'hFFC0) begin if (!FS[15] || FS[0]) begin
// Precharge All
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1; // "all"
end else if (FS[15:4]==16'hFFD && FS[0]==1'b0) begin // Repeat 8x
// Auto-refresh
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b1;
RA[10] <= 1'b0;
end else if (FS[15:0]==16'hFFE8) begin
// Set Mode Register
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b0;
RA[10] <= 1'b0; // Reserved in mode register
end else if (FS[15:4]==12'hFFF && FS[0]==1'b0) begin // Repeat 8x
// Auto-refresh
nCS <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b0;
nRWE <= 1'b1;
RA[10] <= 1'b0;
end else begin // Otherwise send no-op
// 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])
end 4'h0: begin
// Enable SDRAM clock after 65,280 cycles (~4.56ms) // PC all
CKE <= FS[15:8] == 8'hFF; nRAS <= 1'b0;
nCAS <= 1'b1;
// Mode register contents nRWE <= 1'b0;
BA[1:0] <= 2'b00; // Reserved end 4'h1: begin
RA[11] <= 1'b0; // Reserved // LDM
// RA[10] set above ^ nRAS <= 1'b0;
RA[9] <= 1'b1; // "1" for single write mode nCAS <= 1'b0;
RA[8] <= 1'b0; // Reserved nRWE <= 1'b0;
RA[7] <= 1'b0; // "0" for not test mode end 4'h2: begin
RA[6:4] <= 3'b010; // "2" for CAS latency 2 // NOP
RA[3] <= 1'b0; // "0" for sequential burst (not used) nRAS <= 1'b1;
RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst) nCAS <= 1'b1;
nRWE <= 1'b1;
// Mask everything end 4'h3, 4'h4, 4'h5, 4'h6,
DQML <= 1'b1; 4'h7, 4'h8, 4'h9, 4'hA: begin
DQMH <= 1'b1; // AREF
nRAS <= 1'b0;
// Inhibit data bus output nCAS <= 1'b0;
DOEEN <= 1'b0; nRWE <= 1'b1;
end 4'hB: begin
// Begin normal operation after 128k init cycles (~9.15ms) // ACT
if (FS == 16'hFFFF) Ready <= 1'b1; nRAS <= 1'b0;
end else if (S==4'h1) begin nCAS <= 1'b1;
// Enable clock 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
endcase
case (FS[4:3])
2'b00, 2'b01: begin
// Mode register contents
BA[1:0] <= 2'b00; // Reserved
RA[11] <= 1'b0; // Reserved
RA[10] <= !FS[1]; // reserved / "all"
RA[9] <= 1'b1; // "1" for single write mode
RA[8] <= 1'b0; // Reserved
RA[7] <= 1'b0; // "0" for not test mode
RA[6:4] <= 3'b010; // "2" for CAS latency 2
RA[3] <= 1'b0; // "0" for sequential burst (not used)
RA[2:0] <= 3'b000; // "0" for burst length 1 (no burst)
end 2'b10: begin
BA[1:0] <= 2'b00;
RA[11:8] <= 4'h0;
RA[7:0] <= FS[14:7];
end 2'b11: begin
BA[1:0] <= 2'b00;
RA[11:3] <= 9'h000;
RA[2:1] <= FS[6:5];
RA[0] <= FS[1];
end
endcase
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'b0;
DQML <= 1'b1;
DQMH <= 1'b1; DQMH <= 1'b1;
end 4'h2: begin
// Inhibit data bus output // ACT CKE
DOEEN <= 1'b0;
end else if (S==4'h2) begin
// Enable clock
CKE <= 1'b1; CKE <= 1'b1;
// Activate
nCS <= 1'b0;
nRAS <= 1'b0; nRAS <= 1'b0;
nCAS <= 1'b1; nCAS <= 1'b1;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// SDRAM bank 0, high-order row address is 0 // Hold RA
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'h3: begin
// Row address is as previously latched // RD CKE
// 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; CKE <= 1'b1;
// Read
nCS <= 1'b0;
nRAS <= 1'b1; nRAS <= 1'b1;
nCAS <= 1'b0; nCAS <= 1'b0;
nRWE <= 1'b1; nRWE <= 1'b1;
// Hold BA
// SDRAM bank 0, RA[11,9:8] don't care // Hold RA[11:8]
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]; RA[7:0] <= Ain[7:0];
// Hold DQMs
// Read low byte (high byte is +4MB in ramworks) end 4'h4: begin
DQML <= 1'b0; // PC all CKE
DQMH <= 1'b1;
// Inhibit data bus output
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'b0;
// Hold BA
// Don't care bank, RA[11:8] // Hold RA[11]
BA[1:0] <= 2'b00; RA[10] <= 1'b1; // "all"
RA[11:8] <= 4'b0000; // Hold RA[9:0]
// Hold DQMs
// Mask everything end 4'h5: begin
DQML <= 1'b1; if (RefReq) begin
DQMH <= 1'b1; // AREF CKE
CKE <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h5) begin
// Enable clock
CKE <= 1'b1;
// 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'h6) begin
// Enable clock
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
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;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Don't care bank, RA[11:8]
BA[1:0] <= 2'b00;
RA[11:8] <= 4'b0000;
// Latch row address for activate command
RA[7:0] <= Ain[7:0];
// Mask everything
DQML <= 1'b1;
DQMH <= 1'b1;
// Inhibit data bus output
DOEEN <= 1'b0;
end else if (S==4'h8) begin
// Enable clock if '245 output enabled
CKE <= EN80;
// Activate if '245 output enabled
nCS <= nEN80;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
// SDRAM bank, RA[11:8] determine by RamWorks bank
BA[1:0] <= RWBank[5:4];
RA[11:8] <= RWBank[3:0];
// 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'h9) begin
// Enable clock if '245 output enabled
CKE <= EN80;
// Read/Write if '245 output enabled
nCS <= nEN80;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= nWE80;
// SDRAM bank still determined by RamWorks, RA[11,9:8] don't care
BA[1:0] <= RWBank[5:4];
RA[11] <= 1'b0;
RA[10] <= 1'b1; // (A10 set to auto-precharge)
RA[9] <= 1'b0;
RA[8] <= RWBank[7];
// Latch column address for R/W command
RA[7:0] <= Ain[7:0];
// Latch RAMWorks low nybble write select using old row address
RWSel <= RA[0] && !RA[3] && !nWE && !nC07X;
// Mask according to RAMWorks bank (high byte is +4MB)
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 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
// Can't check EN80 at this time
// Mask everything if (nWE) begin // Read / idle
DQML <= 1'b1; // NOP CKE
DQMH <= 1'b1; CKE <= 1'b1;
nRAS <= 1'b1;
// Enable data bus output nCAS <= 1'b1;
DOEEN <= 1'b1; nRWE <= 1'b1;
end else if (S==4'hC) begin end else begin // Write / idle
// Disable clock // NOP CKD
CKE <= 1'b0; CKE <= 1'b0;
nRAS <= 1'b1;
// NOP nCAS <= 1'b1;
nCS <= 1'b1; nRWE <= 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;
// 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 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
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
end else if (S==4'hD) begin BA[1:0] <= RWBank[6:5];
// Disable clock RA[11:8] <= RWBank[4:1];
CKE <= 1'b0;
// 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;
// Enable data bus output
DOEEN <= 1'b1;
end else if (S==4'hE) begin
// Disable clock
CKE <= 1'b0;
// 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;
// Latch row address for next video read
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;
// Enable data bus output nRAS <= 1'b1;
DOEEN <= 1'b1; nCAS <= 1'b1;
end else if (S==4'hF) begin nRWE <= 1'b1;
// Disable clock end else if (nWE) begin // Read
// ACT CKE
CKE <= 1'b1;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else begin // Write
// NOP CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
// Hold BA
// Hold RA
// Hold DQMs
end 4'h9: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else if (nWE) begin // Read
// RD CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b1;
end else begin // Write
// ACT CKE
CKE <= 1'b1;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
// Hold BA
RA[11:9] <= 3'b000; // no auto-precharge
RA[8] <= RWBank[7];
RA[7:0] <= Ain[7:0];
DQMH <= !RWBank[0];
DQMH <= RWBank[0];
end 4'hA: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold RA[10]
end else if (nWE) begin // Read
// PC all CKD
CKE <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1;
end else begin // Write
// WR CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b0;
nRWE <= 1'b0;
RA[10] <= 1'b0;
end
// Hold BA
// Hold RA[11,9:0]
// Hold DQMs
end 4'hB: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else if (nWE) begin // Read
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end else begin // Write
// NOP CKE
CKE <= 1'b1;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
end
// Hold BA
// Hold RA[11:0]
// Hold DQMs
end 4'hC: begin
if (nEN80) begin // Idle
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold RA[10]
end else if (nWE) begin // Read
// NOP CKD
CKE <= 1'b0;
nRAS <= 1'b1;
nCAS <= 1'b1;
nRWE <= 1'b1;
// Hold RA[10]
end else begin // Write
// PC all CKD
CKE <= 1'b0;
nRAS <= 1'b0;
nCAS <= 1'b1;
nRWE <= 1'b0;
RA[10] <= 1'b1; // "all"
end
// Hold BA
// Hold RA[11,9:0]
// Hold RA[7:0]
// Hold DQMs
end 4'hD: begin
// NOP CKD
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 BA
// Don't care bank, RA[11:8] // Hold RA[11:0]
BA[1:0] <= 2'b00; // Hold DQMs
RA[11:8] <= 4'b0000; end 4'hE, 4'hF: begin
// Latch row address for next video read // NOP CKD
RA[7:0] <= Ain[7:0]; CKE <= 1'b0;
nRAS <= 1'b1;
// Mask everything nCAS <= 1'b1;
DQML <= 1'b1; nRWE <= 1'b1;
DQMH <= 1'b1; // Hold BA
// Hold RA[11:8]
// Enable data bus output RA[7:0] <= Ain[7:0]; // Latch row address for next video read
DOEEN <= 1'b1; // Hold DQMs
end end
end endcase
always @(negedge C14M) begin
// 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