Warp-SE/cpld/RAM.v
2021-10-29 06:04:59 -04:00

142 lines
3.5 KiB
Verilog

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 Ready,
/* Refresh Counter Interface */
input RefReq, input RefUrgent, output RefAck,
/* DRAM and NOR flash interface */
output [11:0] RA, output nRAS, output reg nCAS,
output nLWE, output nUWE, output nOE, output nROMCS, output nROMWE);
/* RAM control state */
reg [2:0] RS = 0;
reg Once = 0;
reg RAMReady = 0;
reg RASEL = 0; // RASEL controls /CAS signal
/* Refresh state */
reg RAMDIS1 = 0;
reg RAMDIS2 = 0;
wire RAMDIS = RAMDIS1 || RAMDIS2;
wire RAMEN = ~RAMDIS;
reg RefRAS = 0;
assign nROMCS = ~ROMCS;
assign nRAS = ~((~nAS && RAMCS && RAMEN && ~RefRAS /* does this add loading to these P-terms? */) || RefRAS);
assign nOE = ~(~nAS && nWE);
assign nLWE = ~(~nAS && ~nWE && ~nLDS && RAMEN);
assign nUWE = ~(~nAS && ~nWE && ~nUDS && RAMEN);
assign nROMWE = ~(~nAS && ~nWE);
assign RA[11] = A[19];
assign RA[10] = A[21];
assign RA[9:0] = RASEL ? {A[20], A[09:01]} : {A[19], A[18:10]};
always @(posedge CLK) begin
if (~BACT) Once <= 0;
else if (RS==0 && BACT && RAMCS) Once <= 1;
end
always @(posedge CLK) begin
if (~BACT) RAMDIS2 <= 0;
else if ((RS==0 && BACT && RefUrgent && Once && RAMCS) ||
(RS==7 && BACT && RefUrgent && Once)) RAMDIS2 <= 1;
end
reg BACTr;
always @(posedge CLK) begin BACTr <= BACT; end
always @(posedge CLK) begin
if (RS==0) begin
if (( BACT && RefReq && ~RAMCS && ~BACTr) || // Non-urgent refresh can start during first clock of non-RAM cycle
(~BACT && RefUrgent) || // Urgent refresh can start during bus idle
( BACT && RefUrgent && ~RAMCS)) begin // Urgent refresh can start during non-ram cycle
RS <= 2;
RAMReady <= 0;
RASEL <= 1;
RAMDIS1 <= 1;
end else if (BACT && RAMCS && ~Once) begin
// RAM access cycle has priority over urgent refresh if RAM access already begun
RS <= 5;
RAMReady <= 0;
RASEL <= 1;
RAMDIS1 <= 0;
end else if (BACT && RAMCS && RefUrgent) begin
// Urgent refresh can start during prolonged RAM access cycle
// But we must insert one extra precharge state first.
RS <= 1;
RAMReady <= 0;
RASEL <= 0;
RAMDIS1 <= 1;
end else begin
// No RAM access/refresh requests pending
RS <= 0;
RAMReady <= 1;
RASEL <= 0;
RAMDIS1 <= 0;
end
RefRAS <= 0;
end else if (RS==1) begin
RS <= 2;
RAMReady <= 0;
RASEL <= 1;
RAMDIS1 <= 1;
RefRAS <= 0;
end else if (RS==2) begin
RS <= 3;
RAMReady <= 0;
RASEL <= 1;
RAMDIS1 <= 1;
RefRAS <= 1;
end else if (RS==3) begin
RS <= 4;
RAMReady <= 0;
RASEL <= 0;
RAMDIS1 <= 1;
RefRAS <= 1;
end else if (RS==4) begin
RS <= 7;
RAMReady <= 0;
RASEL <= 0;
RAMDIS1 <= 1;
RefRAS <= 0;
end else if (RS==5) begin
RS <= 6;
RAMReady <= 0;
RASEL <= 1;
RAMDIS1 <= 0;
RefRAS <= 0;
end else if (RS==6) begin
RS <= 7;
RAMReady <= 0;
RASEL <= 0;
RAMDIS1 <= 0;
RefRAS <= 0;
end else if (RS==7) begin
if (~BACT && RefUrgent) begin
RS <= 2;
RAMReady <= 0;
RAMDIS1 <= 1;
RASEL <= 1;
end else if (BACT && RefUrgent) begin
RS <= 1;
RAMReady <= 0;
RASEL <= 0;
RAMDIS1 <= 1;
end else begin
RS <= 0;
RAMReady <= 1;
RASEL <= 0;
RAMDIS1 <= 0;
end
RefRAS <= 0;
end
end
always @(negedge CLK) begin nCAS <= ~RASEL; end
assign RefAck = RefRAS;
assign Ready = ~RAMCS || RAMReady;
endmodule