RAM2E/cpld/RAM2E.v

101 lines
2.9 KiB
Verilog

module RAM2E(C14M, C14M_2, C7M, Q3, PHI0, PHI1,
nPRAS, nPCAS, nWE, nWE80, nEN80,
nRAS, nCAS, nRWE,
VD, MD, RD, nC07X, MA, RA,
Q3_2, C3M58, AN3, nCASEN, C073SEL,
DelayIn, DelayOut);
// Control inputs
input C14M, PHI1, C7M;
input nWE, nWE80, nEN80, nC07X;
// Unused inputs
input C14M_2, Q3_2, C3M58, Q3, PHI0;
input nPRAS, nPCAS, nCASEN, AN3;
// Delay
input [3:0] DelayIn;
output [3:0] DelayOut;
assign DelayOut[0] = 0; // RC delay unused
assign DelayOut[1] = ~nEN80;
assign DelayOut[2] = DelayIn[1];
assign DelayOut[3] = 0; // 3rd delay unused
wire EN80 = DelayIn[2]; // 2 * 15 ns delay max
reg MDBEN = 0;
// DRAM control
output reg nRAS = 1;
output reg nCAS = 1;
output nRWE = nWE80;
// Address bus and bank address registers
input [7:0] MA; // Low-order multiplexed DRAM address (input, output by Apple II)
output reg [11:8] RA = 4'h0;
reg [5:0] BA = 0; // Bank address
wire [4:0] BAS = {BA[4], BA[4] ? BA[5] : BA[3], BA[2:0]};
output reg C073SEL = 0; // Bank register select
// Video data bus
inout [7:0] VD = VDOE ? VDR[7:0] : 8'bZ;
reg [7:0] VDR; // Registered video data
wire VDOE = ~PHI1;
// 6502 data bus
inout [7:0] MD = MDOE ? MDR[7:0] : 8'bZ;
reg [7:0] MDR; // Registered DRAM read data
wire MDOE = EN80 & nWE & MDBEN;
// DRAM data bus
inout [7:0] RD = RDOE ? MD[7:0] : 8'bZ;
wire RDOE = EN80 & ~nWE;
/* State Counters */
reg PHI1reg = 0; // Saved PHI1 at last rising clock edge
reg PHI0seen = 0; // Have we seen PHI0 since reset?
reg [3:0] S = 0; // State counter
reg [3:0] Ref = 0; // Refresh skip counter
always @(posedge C14M) begin
// Refresh counter allows DRAM refresh once every 13 cycles
if (S==4'h1) Ref <= (Ref[3:2]==2'b11) ? 4'h0 : Ref+1;
// Synchronize state counter to S1 when just entering PHI1
PHI1reg <= PHI1; // Save old PHI1
if (~PHI1) PHI0seen <= 1; // PHI0seen set in PHI0
S <= (PHI1 & ~PHI1reg & PHI0seen) ? 4'h1 :
S==4'h0 ? 4'h0 :
S==4'hF ? 4'hF : S+1;
// DRAM RAS
nRAS <= ~((PHI1 & ~PHI1reg & PHI0seen) | S==4'h1 | S==4'h2 |
(S==4'h4 & Ref==0) |
S==4'h7 | S==4'h8 | S==4'h9 | S==4'hA);
// DRAM address multiplexing
RA[11:8] <=
(S==4'h6 | S==4'h7) ? {1'b0, BAS[4], BAS[3], BAS[2]} :
(S==4'h8 | S==4'h9 | S==4'hA | S==4'hB) ? {1'b0, 1'b0, BAS[1], BAS[0]} : 4'b0;
// DRAM CAS
nCAS <= ~(S==4'h2 | S==4'h3 | (S==4'h4 & Ref==0) |
S==4'hA | S==4'hB);
// Memory data bus gating (only active from S11-S15)
MDBEN <= S==4'hB | S==4'hC | S==4'hD | S==4'hE | S==4'hF;
// Latch 80-column video data at end of S3
if (S==4'h3) VDR[7:0] <= RD[7:0];
// Latch bank select at end of S7 and S8
if (S==4'h0 | S==4'h1) C073SEL <= 0;
if (S==4'h7) C073SEL <= (MA[3:0]==4'h1 | MA[3:0]==4'h3 | MA[3:0]==4'h5 | MA[3:0]==4'h7);
if (S==4'h8) C073SEL <= C073SEL & ~nC07X & ~nWE;
// Set bank register at end of S11
if (S==4'hB & C073SEL) BA[5:0] <= MD[5:0];
// Latch DRAM read data at end of S11
if (S==4'hB) MDR[7:0] <= RD[7:0];
end
endmodule