module RAM( /* MC68HC000 interface */ input CLK, input [21:1] A, input nWE, input nAS, input nLDS, input nUDS, /* AS cycle detection */ input BACT, /* Select and ready signals */ input RAMCS, input ROMCS, output RAM_Ready, /* Refresh Counter Interface */ input RefReqIn, input RefUrgIn, /* DRAM and NOR flash interface */ output [11:0] RA, output nRAS, output reg nCAS, output nLWE, output nUWE, output nOE, output nROMCS, output nROMWE); // Save BACT from last clock reg BACTr; always @(posedge CLK) BACTr <= BACT; /* RAM control state */ reg [2:0] RS = 0; reg RAMEN = 0; reg RAMReady = 0; reg RASEL = 0; // RASEL controls /CAS signal /* Refresh request synchronization */ reg RefReqSync; always @(posedge CLK) RefReqSync <= RefReqIn; reg RegUrgSync; always @(posedge CLK) RegUrgSync <= RefUrgIn; /* Refresh command generation */ reg RefReq, RefUrg; // Refresh commands reg RefDone; // Refresh done "remember" always @(posedge CLK) begin RefReq <= RefReqSync && !RefDone; RefUrg <= RegUrgSync && !RefDone; if (!RefReqSync) RefDone <= 0; else if (RS==2 || RS==3) RefDone <= 1; // RS2 || RS3 to save 1 input end /* Refresh init conditions */ wire RefFromRS0Next = RS==0 && ( // Non-urgent refresh can start during first clock of non-RAM cycle ( BACT && ~BACTr && ~RAMCS && RefReq) || // Urgent refresh can start during bus idle (~BACT && RefUrg) || // Urgent refresh can start during non-ram cycle ( BACT && ~RAMCS && RefUrg)); wire RefFromRS0Pre = RS==0 && // Urgent refresh can start during long RAM cycle after RAM access done. BACT && RAMCS && !RAMEN && RefUrg; wire RefFromRS0 = RefFromRS0Next || RefFromRS0Pre; // Urgent refresh cannot start when BACT and RAMCS and RAMEN, // since /RAS has already been asserted. For this we wait for RS7. wire RefFromRS7 = RS==7 && RefUrg; /* RAM enable (/AS -> /RAS) */ always @(posedge CLK) begin if (RS==0) begin if (RefFromRS0) RAMEN <= 0; else if (!BACT) RAMEN <= 1; end else if (RS==7) begin if (RefFromRS7) RAMEN <= 0; else if (BACT) RAMEN <= 0; else if (!BACT) RAMEN <= 1; end end /* Refresh state */ reg RefRAS = 0; assign nROMCS = !ROMCS; assign nRAS = !((~nAS && RAMCS && RAMEN) || RefRAS); assign nOE = !(~nAS && nWE); assign nLWE = !(~nAS && ~nWE && ~nLDS && RAMEN); assign nUWE = !(~nAS && ~nWE && ~nUDS && RAMEN); assign nROMWE = !(~nAS && ~nWE); /* RAM address mux (and ROM address on RA8) */ assign RA[11] = A[19]; assign RA[10] = A[21]; assign RA[09] = RASEL ? A[20] : A[19]; assign RA[08] = (RASEL && RAMCS) ? A[09] : A[18]; assign RA[07] = RASEL ? A[08] : A[17]; assign RA[06] = RASEL ? A[07] : A[16]; assign RA[05] = RASEL ? A[06] : A[15]; assign RA[04] = RASEL ? A[05] : A[14]; assign RA[03] = RASEL ? A[04] : A[13]; assign RA[02] = RASEL ? A[03] : A[12]; assign RA[01] = RASEL ? A[02] : A[11]; assign RA[00] = RASEL ? A[01] : A[10]; always @(posedge CLK) begin if (RS==0) begin // In RS0, RAM is idle and ready for new command. if (RefFromRS0Next) begin RS <= 2; RAMReady <= 0; RASEL <= 1; end else if (RefFromRS0Pre) begin // Urgent ref can start during long RAM cycle after access. // Must insert one extra precharge state first by going to RS1. RS <= 1; RAMReady <= 0; RASEL <= 0; end else if (BACT && RAMCS && RAMEN) begin // RAM access cycle has priority over urgent refresh if RAM access already begun RS <= 5; RAMReady <= 0; RASEL <= 1; end else if (RefFromRS0Pre) begin RS <= 1; RAMReady <= 0; RASEL <= 0; end else begin // No RAM access/refresh requests pending RS <= 0; RAMReady <= 1; RASEL <= 0; end RefRAS <= 0; end else if (RS==1) begin // RS1 implements extra precharge time before refresh. RS <= 2; RAMReady <= 0; RASEL <= 1; RefRAS <= 0; end else if (RS==2) begin // Refresh RAS pulse asserted ater RS2. RS <= 3; RAMReady <= 0; RASEL <= 1; RefRAS <= 1; end else if (RS==3) begin // RS3 implements requisite RAS pulse width. RS <= 4; RAMReady <= 0; RASEL <= 0; RefRAS <= 1; end else if (RS==4) begin // RS4 implements precharge after RAM refresh. RS <= 7; RAMReady <= 0; RASEL <= 0; RefRAS <= 0; end else if (RS==5) begin // RS5 is first state of R/W operation RS <= 6; RAMReady <= 0; RASEL <= 1; RefRAS <= 0; end else if (RS==6) begin // RS6 is second state of R/W operation RS <= 7; RAMReady <= 0; RASEL <= 0; RefRAS <= 0; end else if (RS==7) begin // RS7 is final state of R/W or refresh operation. if (~BACT && RefUrg) begin // If /AS cycle terminated and urgent refresh request, // we know /RAS has been in precharge so we can go to RS2. RS <= 2; RAMReady <= 0; RASEL <= 1; end else if (BACT && RefUrg) begin // But if /AS cycle hasn't terminated and we need to refresh, // we need to go to RS1 to add additional precharge time. RS <= 1; RAMReady <= 0; RASEL <= 0; end else begin // Otherwise if no urgent refresh request, go to RS0. RS <= 0; RAMReady <= 1; RASEL <= 0; end RefRAS <= 0; end end always @(negedge CLK) begin nCAS <= ~RASEL; end assign RAM_Ready = ~RAMCS || RAMReady; endmodule