mirror of
https://github.com/garrettsworkshop/RAM2E.git
synced 2024-06-11 15:29:29 +00:00
7ff514a26c
Previous commit had "snow" in 80-col mode when updating display. Put back command timing to fix problem. Kept PHI0 read gating depending on EN80 and data output gating
637 lines
16 KiB
Verilog
637 lines
16 KiB
Verilog
module RAM2E(C14M, PHI1,
|
|
nWE, nWE80, nEN80, nC07X,
|
|
Ain, Din, Dout, nDOE, Vout, nVOE,
|
|
CKE, nCS, nRAS, nCAS, nRWE,
|
|
BA, RA, RD, DQML, DQMH);
|
|
|
|
/* Clocks */
|
|
input C14M, PHI1;
|
|
|
|
/* Control inputs */
|
|
input nWE, nWE80, nEN80, nC07X;
|
|
|
|
/* Delay for EN80 signal */
|
|
//output DelayOut = 1'b0;
|
|
//input DelayIn;
|
|
wire EN80 = ~nEN80;
|
|
|
|
/* Address Bus */
|
|
input [7:0] Ain; // Multiplexed DRAM address input
|
|
|
|
/* 6502 Data Bus */
|
|
input [7:0] Din; // 6502 data bus inputs
|
|
reg DOEEN = 0; // 6502 data bus output enable from state machine
|
|
output nDOE = ~(EN80 & nWE & DOEEN); // 6502 data bus output enable
|
|
output reg [7:0] Dout; // 6502 data Bus output
|
|
|
|
/* Video Data Bus */
|
|
output nVOE = ~(~PHI1); /// Video data bus output enable
|
|
output reg [7:0] Vout; // Video data bus
|
|
|
|
/* SDRAM */
|
|
output reg CKE = 0;
|
|
output reg nCS = 1, nRAS = 1, nCAS = 1, nRWE = 1;
|
|
output reg [1:0] BA;
|
|
output reg [11:0] RA;
|
|
output reg DQML = 1, DQMH = 1;
|
|
wire RDOE = EN80 & ~nWE80;
|
|
inout [7:0] RD = RDOE ? Din[7:0] : 8'bZ;
|
|
|
|
/* RAMWorks Bank Register and Capacity Mask */
|
|
reg [7:0] RWBank = 0; // RAMWorks bank register
|
|
reg [7:0] RWMask = 0; // RAMWorks bank reg. capacity mask
|
|
reg RWSel = 0; // RAMWorks bank register select
|
|
reg RWMaskSet = 0; // RAMWorks Mask register set flag
|
|
reg SetRWBankFF = 0; // Causes RWBank to be zeroed next RWSel access
|
|
|
|
/* Command Sequence Detector */
|
|
reg [2:0] CS = 0; // Command sequence state
|
|
reg [2:0] CmdTout = 0; // Command sequence timeout
|
|
|
|
/* UFM Interface */
|
|
reg [15:8] UFMD = 0; // *Parallel* UFM data register
|
|
reg ARCLK = 0; // UFM address register clock
|
|
// UFM address register data input tied to 0
|
|
reg ARShift = 0; // 1 to Shift UFM address in, 0 to increment
|
|
reg DRCLK = 0; // UFM data register clock
|
|
reg DRDIn = 0; // UFM data register input
|
|
reg DRShift = 0; // 1 to shift UFM out, 0 to load from current address
|
|
reg UFMErase = 0; // Rising edge starts erase. UFM+RTP must not be busy
|
|
reg UFMProgram = 0; // Rising edge starts program. UFM+RTP must not be busy
|
|
wire UFMBusy; // 1 if UFM is doing user operation. Asynchronous
|
|
wire RTPBusy; // 1 if real-time programming in progress. Asynchronous
|
|
wire DRDOut; // UFM data output
|
|
// UFM oscillator always enabled
|
|
wire UFMOsc; // UFM oscillator output (3.3-5.5 MHz)
|
|
UFM UFM_inst ( // UFM IP block (for Altera MAX II and MAX V)
|
|
.arclk (ARCLK),
|
|
.ardin (1'b0),
|
|
.arshft (ARShift),
|
|
.drclk (DRCLK),
|
|
.drdin (DRDIn),
|
|
.drshft (DRShift),
|
|
.erase (UFMErase),
|
|
.oscena (1'b1),
|
|
.program (UFMProgram),
|
|
.busy (UFMBusy),
|
|
.drdout (DRDOut),
|
|
.osc (UFMOsc),
|
|
.rtpbusy (RTPBusy));
|
|
reg UFMBusyReg = 0; // UFMBusy registered to sync with C14M
|
|
reg RTPBusyReg = 0; // RTPBusy registered to sync with C14M
|
|
|
|
/* UFM State & User Command Triggers */
|
|
reg UFMInitDone = 0; // 1 if UFM initialization finished
|
|
reg UFMReqErase = 0; // 1 if UFM requires erase
|
|
reg UFMBitbang = 0; // Set by user command. Loads UFM outputs next RWSel
|
|
reg UFMPrgmEN = 0; // Set by user command. Programs UFM
|
|
reg UFMEraseEN = 0; // Set by user command. Erases UFM
|
|
reg DRCLKPulse = 0; // Set by user command. Causes DRCLK pulse next C14M
|
|
|
|
/* State Counters */
|
|
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 [15:0] FS = 0; // Fast state counter
|
|
reg [3:0] S = 0; // IIe State counter
|
|
|
|
/* State Counters */
|
|
always @(posedge C14M) begin
|
|
// Increment fast state counter
|
|
FS <= FS+1;
|
|
// Synchronize Apple state counter to S1 when just entering PHI1
|
|
PHI1reg <= PHI1; // Save old PHI1
|
|
S <= (PHI1 & ~PHI1reg & Ready) ? 4'h1 :
|
|
S==4'h0 ? 4'h0 :
|
|
S==4'hF ? 4'hF : S+1;
|
|
end
|
|
|
|
/* UFM Control */
|
|
always @(posedge C14M) begin
|
|
// Synchronize asynchronous UFM signals
|
|
UFMBusyReg <= UFMBusy;
|
|
RTPBusyReg <= RTPBusy;
|
|
|
|
if (S==4'h0) begin
|
|
if ((FS[15:13]==3'b101) | (FS[15:13]==3'b111 & UFMReqErase)) begin
|
|
// In states AXXX-BXXX and also EXXX-FXXX if erase/wrap req'd
|
|
// shift in 0's to address register
|
|
ARCLK <= FS[0]; // Clock address register
|
|
DRCLK <= 1'b0; // Don't clock data register
|
|
ARShift <= 1'b1; // Shift address registers
|
|
DRDIn <= 1'b0; // Don't care DRDIn
|
|
DRShift <= 1'b0; // Don't care DRDShift
|
|
end else if (~UFMInitDone & FS[15:13]==3'b110 & FS[4:1]==4'h4) begin
|
|
// In states CXXX-DXXX (substep 4)
|
|
// Xfer to data reg (repeat 256x 1x)
|
|
ARCLK <= 1'b0; // Don't clock address register
|
|
DRCLK <= FS[0]; // Clock data register
|
|
ARShift <= 1'b0; // Don't care ARShift
|
|
DRDIn <= 1'b0; // Don't care DRDIn
|
|
DRShift <= 1'b0; // Don't care DRShift
|
|
end else if (~UFMInitDone & FS[15:13]==3'b110 & FS[4]==1'b1) begin
|
|
// In states CXXX-DXXX (substeps 8-F)
|
|
// Save UFM D15-8, shift out D14-7 (repeat 256x 8x)
|
|
DRCLK <= FS[0]; // Clock data register
|
|
ARShift <= 1'b0; // ARShift is 0 because we want to increment
|
|
DRDIn <= 1'b0; // Don't care what to shift into data register
|
|
DRShift <= 1'b1; // Shift data register
|
|
// Shift into UFMD
|
|
if (FS[0]) UFMD[15:8] <= {UFMD[14:8], DRDOut};
|
|
|
|
// Compare and store mask
|
|
if (FS[4:1]==4'hF) begin
|
|
ARCLK <= FS[0]; // Clock address register to increment
|
|
// If byte is erased (0xFF, i.e. all 1's, is erased)...
|
|
if (UFMD[14:8]==7'b1111111 & DRDOut==1'b1) begin
|
|
// Current UFM address is where we want to store
|
|
UFMInitDone <= 1'b1; // Quit iterating
|
|
// Otherwise byte is valid setting (i.e. some bit is 0)...
|
|
end else begin
|
|
// Set RWMask, but if saved mask is 0x80, store ~0xFF
|
|
if (UFMD[14:8]==7'b1000000 & DRDOut==1'b0) begin
|
|
RWMask[7:0] <= {1'b1, ~7'h7F};
|
|
end else RWMask[7:0] <= {UFMD[14], ~UFMD[13:8], ~DRDOut};
|
|
// If last byte in sector...
|
|
if (FS[12:5]==8'hFF) begin
|
|
UFMReqErase <= 1'b1; // Mark need to erase
|
|
end
|
|
end
|
|
end else ARCLK <= 1'b0; // Don't clock address register
|
|
end else begin
|
|
ARCLK <= 1'b0;
|
|
DRCLK <= 1'b0;
|
|
ARShift <= 1'b0;
|
|
DRDIn <= 1'b0;
|
|
DRShift <= 1'b0;
|
|
end
|
|
|
|
// Don't erase or program UFM during initialization
|
|
UFMErase <= 1'b0;
|
|
UFMProgram <= 1'b0;
|
|
// Keep DRCLK pulse control disabled during init
|
|
DRCLKPulse <= 1'b0;
|
|
end else begin
|
|
// Can only shift UFM data register now
|
|
ARCLK <= 1'b0;
|
|
ARShift <= 1'b0;
|
|
DRShift <= 1'b1;
|
|
|
|
// UFM bitbang control
|
|
if (UFMBitbang & CS==3'h7 & RWSel & S==4'hC) begin
|
|
DRDIn <= Din[6];
|
|
DRCLKPulse <= Din[7];
|
|
DRCLK <= 1'b0;
|
|
end else begin
|
|
DRCLKPulse <= 1'b0;
|
|
DRCLK <= DRCLKPulse;
|
|
end
|
|
|
|
// Set capacity mask
|
|
if (RWMaskSet & RWSel & S==4'hC) RWMask[7:0] <= {Din[7], ~Din[6:0]};
|
|
|
|
// UFM programming sequence
|
|
if (UFMPrgmEN | UFMEraseEN) begin
|
|
if (~UFMBusyReg & ~RTPBusyReg) begin
|
|
if (UFMReqErase | UFMEraseEN) UFMErase <= 1'b1;
|
|
else if (UFMPrgmEN) UFMProgram <= 1'b1;
|
|
end else if (UFMBusyReg) UFMReqErase <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
/* SDRAM Control */
|
|
always @(posedge C14M) begin
|
|
if (S==4'h0) begin
|
|
// SDRAM initialization
|
|
if (FS[15:0]==16'hFFC0) 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
|
|
nCS <= 1'b1;
|
|
nRAS <= 1'b1;
|
|
nCAS <= 1'b1;
|
|
nRWE <= 1'b1;
|
|
RA[10] <= 1'b0;
|
|
end
|
|
// Enable SDRAM clock after 65,280 cycles (~4.56ms)
|
|
CKE <= FS[15:8] == 8'hFF;
|
|
|
|
// Mode register contents
|
|
BA[1:0] <= 2'b00; // Reserved
|
|
RA[11] <= 1'b0; // Reserved
|
|
// RA[10] set above ^
|
|
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)
|
|
|
|
// Mask everything
|
|
DQML <= 1'b1;
|
|
DQMH <= 1'b1;
|
|
|
|
// Inhibit data bus output
|
|
DOEEN <= 1'b0;
|
|
|
|
// Begin normal operation after 128k init cycles (~9.15ms)
|
|
if (FS == 16'hFFFF) Ready <= 1'b1;
|
|
end else if (S==4'h1) 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 <= 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'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 <= 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 <= 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;
|
|
DQMH <= 1'b1;
|
|
|
|
// Inhibit data bus output
|
|
DOEEN <= 1'b0;
|
|
end else if (S==4'h4) 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 <= 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'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 <= 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[6:4]==0) begin
|
|
// Auto-refresh
|
|
nCS <= 1'b0;
|
|
nRAS <= 1'b0;
|
|
nCAS <= 1'b0;
|
|
nRWE <= 1'b1;
|
|
end else begin
|
|
// NOP
|
|
nCS <= 1'b1;
|
|
nRAS <= 1'b1;
|
|
nCAS <= 1'b1;
|
|
nRWE <= 1'b1;
|
|
end
|
|
|
|
// Don't care bank, RA[11:8]
|
|
BA <= 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'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 <= 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 <= 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 <= 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 <= 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;
|
|
|
|
// NOP
|
|
nCS <= 1'b1;
|
|
nRAS <= 1'b1;
|
|
nCAS <= 1'b1;
|
|
nRWE <= 1'b1;
|
|
|
|
// Don't care bank, RA[11:8]
|
|
BA <= 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'hC) 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 <= 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 (SetRWBankFF) 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+1;
|
|
else CS <= 0; // Back to beginning if it's not right
|
|
|
|
if (CS==3'h6) begin // Recognize and submit command in CS6
|
|
SetRWBankFF <= Din[7:0]==8'hFF;
|
|
if (Din[7:0]==8'hEF) UFMPrgmEN <= 1'b1;
|
|
if (Din[7:0]==8'hEE) UFMEraseEN <= 1'b1;
|
|
UFMBitbang <= Din[7:0]==8'hEA;
|
|
RWMaskSet <= Din[7:0]==8'hE0;
|
|
end else begin // Reset command triggers
|
|
SetRWBankFF <= 1'b0;
|
|
UFMBitbang <= 1'b0;
|
|
RWMaskSet <= 1'b0;
|
|
end
|
|
|
|
CmdTout <= 0; // Reset command timeout if RWSel accessed
|
|
end else begin
|
|
CmdTout <= CmdTout+1; // 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;
|
|
|
|
// NOP
|
|
nCS <= 1'b1;
|
|
nRAS <= 1'b1;
|
|
nCAS <= 1'b1;
|
|
nRWE <= 1'b1;
|
|
|
|
// Don't care bank, RA[11:8]
|
|
BA <= 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 <= 2'b00;
|
|
RA[11:8] <= 4'b0000;
|
|
// Latch row address for next video read
|
|
RA[7:0] <= Ain[7:0];
|
|
|
|
// Mask everything
|
|
DQML <= 1'b1;
|
|
DQMH <= 1'b1;
|
|
|
|
// Enable data bus output
|
|
DOEEN <= 1'b1;
|
|
end else if (S==4'hF) 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 <= 2'b00;
|
|
RA[11:8] <= 4'b0000;
|
|
// Latch row address for next video read
|
|
RA[7:0] <= Ain[7:0];
|
|
|
|
// Mask everything
|
|
DQML <= 1'b1;
|
|
DQMH <= 1'b1;
|
|
|
|
// Enable data bus output
|
|
DOEEN <= 1'b1;
|
|
end
|
|
end
|
|
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
|