Much better RAM and FSB controller draft

This commit is contained in:
Zane Kaminski 2023-04-06 23:11:11 -04:00
parent 06960d6369
commit a60c54fb6c
7 changed files with 358 additions and 427 deletions

View File

@ -193,8 +193,12 @@ The Ready signals are always high during ROM access so all ROM accesses complete
{name: 'DTACK', wave: '1.0..10..1', phase:-0.20, period: 2},
{name: 'D (RD)', wave: 'z....x2.z....x2.z...', phase:-0.30},
{name: 'D (WR)', wave: 'z......x.2......z......x.2......z......', phase:-0.30, period:0.5},
{name: 'RS', wave: '2222222222', phase:-0.20, period: 2, data:[0,0,5,6,7,0,5,6,7,0]},
{name: 'RAS', wave: '1...x.0.......x.1...x.0.......x.1......', phase:-0.35, period: 0.5},
{name: 'RS', wave: '2222222222', phase:-0.20, period: 2, data:[0,0,1,2,7,0,1,2,7,0]},
{name: 'RASEN', wave: '1..0.1.0.1', phase: 0.00, period: 2.0},
{name: 'RASrr', wave: '1.01..01..', phase: 0.00, period: 2.0},
{name: 'RASrf', wave: '1..01..01.', phase: 1.00, period: 2.0},
{name: 'RS', wave: '2222222222', phase:-0.20, period: 2.0},
{name: 'RAS', wave: '1...x.0......x1.....x.0......x1........', phase:-0.35, period: 0.5},
{name: 'RASEL', wave: '0.1.0.1.0.', phase:-0.20, period: 2},
{name: 'RA', wave: 'x...x2..x2......x....2..x2......x......', phase:-0.20, period:0.5, data:['row','col','row','col']},
{name: 'CAS', wave: '1..0.1.0.1', phase: 0.80, period: 2},
@ -248,8 +252,11 @@ Since /OE is held high during write cycles, the order of the /WE signals and /CA
{name: 'DTACK', wave: '1.....0..1', phase:-0.20, period: 2},
{name: 'D (RD)', wave: 'z....x2..z..........', phase:-0.30},
{name: 'D (WR)', wave: 'z..x2...........z...', phase: 0.00},
{name: 'RS', wave: '2222222222', phase:-0.20, period: 2, data:[0,0,5,6,7,0,0,0,0,0]},
{name: 'RAS', wave: '1...x.0.......................x.1......', phase:-0.25, period: 0.5},
{name: 'RS', wave: '2222222222', phase:-0.20, period: 2, data:[0,0,1,2,3,0,0,0,0,0]},
{name: 'RASEN', wave: '1..0.....1', phase: 0.00, period: 2, data:[0,0,1,2,3,0,1,2,3,0]},
{name: 'RASrr', wave: '1.01......', phase: 0.00, period: 2, data:[0,0,1,2,3,0,1,2,3,0]},
{name: 'RASrf', wave: '1..01.....', phase: 1.00, period: 2, data:[0,0,1,2,3,0,1,2,3,0]},
{name: 'RAS', wave: '1...x.0......x1...........................', phase:-0.25, period: 0.5},
{name: 'RASEL', wave: '0.1.0.....', phase:-0.20, period: 2},
{name: 'RA', wave: 'x...x2..x2......2...............x........', phase:-0.20, period:0.5, data:['row','col','row']},
{name: 'CAS', wave: '1..0.1....', phase: 0.80, period: 2},
@ -277,14 +284,14 @@ DRAM controller conform to the DRAM "hidden refresh" protocol but it is not nece
<h3 id="t7">7. Refresh During Idle</h3><script type="WaveDrom">{signal: [
{name: 'MCLK', wave: 'p......', phase: 0.00, period: 2},
{name: 'AS', wave: '1............', phase:-0.75},
{name: 'RS', wave: '2222222', phase:-0.2, period: 2, data:[0,0,2,3,4,7,0,0,0]},
{name: 'RefReq', wave: '01..0..', phase:-0.2, period: 2},
{name: 'RASEN', wave: '1.0...1', phase:-0.2, period: 2},
{name: 'RRAS', wave: '1.....0...1...', phase:-0.20},
{name: 'RAS', wave: '1.....0...1...', phase:-0.40},
{name: 'CAS', wave: '1..0.1.', phase: 0.80, period: 2},
{name: 'MCLK', wave: 'p.......', phase: 0.00, period: 2},
{name: 'RS', wave: '22222222', phase:-0.2, period: 2, data:[0,0,3,4,5,6,7,0]},
{name: 'RASEN', wave: '1.0....1', phase: 0.00, period: 2},
{name: 'RASrr', wave: '1..0.1..', phase: 0.00, period: 2},
{name: 'RASrf', wave: '1.......', phase: 1.00, period: 2},
{name: 'RAS', wave: '1..........x0......x1......x....', phase:-0.40, period:0.5},
{name: 'CAS', wave: '1..0..1.', phase: 0.80, period: 2},
{name: 'RASEL', wave: '1.0..1..', phase: 0.00, period: 2},
]}</script><br/><p>
This diagram shows the timing of a refresh occurring after the bus and DRAM are and have been idle for at least one clock cycle.
</p><p>
@ -309,17 +316,50 @@ there may be a tRAS timing violation. This constrains the timing of a refresh.
</p>
<h3 id="t8">8. Refresh Immediately Following DRAM Access - Bus Transaction Terminated Immediately</h3>
<h3 id="t8">8A. Refresh Immediately Following DRAM Access - Bus Transaction Terminated Immediately</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p...', phase: 0.00, period: 2},
{name: 'AS', wave: '0.x1....x.......', phase:-0.25, period:0.5},
{name: 'RS', wave: '2222', phase:-0.20, period: 2, data:[6,7,2,3,4]},
{name: 'RefReq', wave: '21..', phase:-0.20, period: 2},
{name: 'RASEN', wave: '1.0.', phase:-0.20, period: 2},
{name: 'RRAS', wave: '1..0', phase:-0.20, period:2},
{name: 'RAS', wave: '0.x.1.......0..', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0.10', phase: 0.80, period: 2},
{name: 'MCLK', wave: 'p......', phase: 0.00, period: 2},
{name: 'AS', wave: '0.x1........................', phase:-0.25, period:0.5},
{name: 'RS', wave: '2222222', phase:-0.20, period: 2, data:[2,3,4,5,6,7,0]},
{name: 'RASEN', wave: '0.....1', phase: 0.00, period: 2},
{name: 'RASrr', wave: '1.0.1..', phase: 0.00, period: 2},
{name: 'RASrf', wave: '01.....', phase: 1.00, period: 2},
{name: 'RAS', wave: '0x1....x0......x1...........', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0....1.', phase: 0.80, period: 2},
{name: 'RASEL', wave: '0...1..', phase: 0.00, period: 2},
]}
</script><br/>
<h3 id="t8">9. Refresh Immediately Following DRAM Access - Bus Transaction Terminated Immediately</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p......', phase: 0.00, period: 2},
{name: 'AS', wave: '0.x1....................x0..', phase:-0.25, period:0.5},
{name: 'RS', wave: '2222222', phase:-0.20, period: 2, data:[2,3,4,5,6,7,0]},
{name: 'RASEN', wave: '0.....1', phase: 0.00, period: 2},
{name: 'RASrr', wave: '1.0.1..', phase: 0.00, period: 2},
{name: 'RASrf', wave: '01.....', phase: 1.00, period: 2},
{name: 'RAS', wave: '0x1....x0......x1.......x0..', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0....1.', phase: 0.80, period: 2},
{name: 'RASEL', wave: '0...1..', phase: 0.00, period: 2},
]}
</script><br/>
<h3 id="t8">10. Refresh Immediately Following DRAM Access - Bus Transaction Terminated Immediately</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p......', phase: 0.00, period: 2},
{name: 'AS', wave: '0.x1....x0..................', phase:-0.25, period:0.5},
{name: 'RS', wave: '2222222', phase:-0.20, period: 2, data:[2,3,4,5,6,7,0]},
{name: 'RASEN', wave: '0.....1', phase: 0.00, period: 2},
{name: 'RASrr', wave: '1.0.1..', phase: 0.00, period: 2},
{name: 'RASrf', wave: '01.....', phase: 1.00, period: 2},
{name: 'RAS', wave: '0x1....x0......x1......x.0..', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0....1.', phase: 0.80, period: 2},
{name: 'RASEL', wave: '0...1..', phase: 0.00, period: 2},
]}
</script><br/><p>
This diagram shows the timing of a refresh occurring immediately after a RAM access cycle.
@ -335,113 +375,6 @@ The purpose of this diagram is mainly to demonstrate that adequate /RAS and /CAS
after the previous DRAM access is terminated before /RAS is pulsed for refresh.
</p>
<h3 id="t9">9. Refresh Immediately Following DRAM Access - Bus Transaction Terminated While Refresh In-Progress</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p......', phase: 0.00, period: 2},
{name: 'AS', wave: '0.............x1....x......', phase:-0.25, period:0.5},
{name: 'RS', wave: '2222222', phase:-0.20, period: 2, data:[6,7,2,3,4,7,0,0,0,0]},
{name: 'RefReq', wave: '21..0..', phase:-0.20, period: 2},
{name: 'RASEN', wave: '1.0...1', phase:-0.20, period: 2},
{name: 'RRAS', wave: '1..0.1.', phase:-0.20, period:2},
{name: 'RAS', wave: '0.......1...0.......1...x..', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0.10.1.', phase: 0.80, period: 2},
]}
</script><br/><p>
This diagram shows the case where a refresh request occurs during a long-running DRAM access
and the /AS cycle terminates before the refresh ends.
</p><p>
It is possible for a DRAM access cycle to be extended for a long time, during which the DRAM may be deprived of refresh. <br/>
Therefore we must provide for the case where a DRAM access completes and a refresh begins but before /AS ever goes high. <br/>
In this case, the rising edge of RASEN causes /RAS to go inactive, as opposed to the rising edge of /AS. <br/>
Therefore, the /RAS precharge pulse width in this case is much shorter than
a refresh occurring during idle or immediately following a DRAM access. <br/>
At 25 MHz, the /RAS precharge width is only 40ns. This is the minimum tRP for 60ns DRAM and is the tightest timing parameter in the Warp-SE. <br/>
We could purpose RS1 to add additional precharge time if necessary.
</p>
<h3 id="t10">10. Refresh Immediately Following DRAM Access - Bus Transaction Terminated After Refresh Completes</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p........', phase: 0.00, period: 2},
{name: 'AS', wave: '0.........................x1....x...', phase:-0.25, period:0.5},
{name: 'RS', wave: '222222222', phase:-0.20, period: 2, data:[6,7,2,3,4,7,0,0,0]},
{name: 'RefReq', wave: '21..0....', phase:-0.20, period: 2},
{name: 'RASEN', wave: '1.0.....1', phase:-0.20, period: 2},
{name: 'RRAS', wave: '1..0.1...', phase:-0.20, period:2},
{name: 'RAS', wave: '0.......1...0.......1...........x...', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0.10.1...', phase: 0.80, period: 2},
]}
</script><br/><p>
This diagram shows the case where a refresh request occurs during a long-running DRAM access
and the /AS cycle does not terminate before the refresh ends.
</p><p>
This case is similar to the previous but there is a key difference.
/AS does not rise until after the refresh cycle completes. <br/>
Therefore if RASEN were brought high upon exit from RS7 into RS0, there may be an improperly-short /RAS pulse
terminated by the rising edge of the /AS. <br/>
Consequently RASEN enablement is held off the first rising edge during which BACT is low.
</p>
<h3 id="t11">11. Refresh in the "Middle" of DRAM Access</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p......', phase: 0.00, period: 2},
{name: 'AS', wave: '0...........................', phase:-0.25, period:0.5},
{name: 'RS', wave: '2222222', phase:-0.20, period: 2, data:[6,7,0,0,0,2,3]},
{name: 'RefReq', wave: '0...1..', phase:-0.20, period: 2},
{name: 'RASEN', wave: '1....0.', phase:-0.20, period: 2},
{name: 'RRAS', wave: '1.....0', phase:-0.20, period:2},
{name: 'RAS', wave: '0...................1...0...', phase:-0.40, period:0.5},
{name: 'CAS', wave: '0.1...0', phase: 0.80, period: 2},
]}
</script><br/><p>
This diagram shows the case where a refresh request occurs in the "middle" of a long-running DRAM access. <br/>
The remainder of the timing is given by diagrams 9 or 10.
</p>
<h3 id="t12">12. Concurrent DRAM Access and Refresh Requests</h3>
<script type="WaveDrom">
{signal: [
{name: 'MCLK', wave: 'p.........', phase: 0.00, period: 2},
{name: 'A', wave: 'x2......x.', phase: 0.25, period: 2, data:['000000-4FFFFF']},
{name: '/AS', wave: '1..x0........................x1........', phase:-0.75, period: 0.5},
{name: 'DTACK', wave: '1.....0..1', phase:-0.30, period: 2},
{name: 'DS (RD)', wave: '1..x0........................x1.......', phase:-0.75, period: 0.5},
{name: 'OE (RD)', wave: '1...x.0......................x.1.....', phase:-0.75, period: 0.5},
{name: 'DS (WR)', wave: '1......x0....................x1.......', phase:-0.75, period: 0.5},
{name: 'WE (WR)', wave: '1.......................0....x.1......', phase:-0.75, period: 0.5},
{name: 'RS', wave: '2222222222', phase:-0.20, period: 2, data:[0,2,3,4,7,0,5,6,7,0]},
{name: 'Ready0', wave: 'x0...10.x.', phase:-0.20, period: 2},
{name: 'RefReq', wave: '1..0......', phase:-0.20, period: 2},
{name: 'RASEN', wave: '10...1....', phase:-0.20, period: 2},
{name: 'RRAS', wave: '1...0...1...........', phase:-0.20},
{name: '/RAS', wave: '1.......0.......1...0.........x.1......', phase:-0.45, period: 0.5},
{name: '/CAS', wave: '1.0.1..0.1', phase: 0.70, period: 2},
]}
</script><br/><p>
This diagram shows the timing of a refresh starting concurrently with the beginning of a RAM access cycle.
</p><p>
Here we see the timing of refresh being entered concurrently with the start of a RAM access.
In this case, there is a little bit of a race condition. <br/>
RASEN and /AS both fall following the rising edge of FCLK. /AS causes /RAS activation asynchronously,
but RASEN gates this from occurring. <br/>
Therefore the internal RASEN feedback in the CPLD must occur sooner than /AS transitions,
otherwise an erroneous /RAS pulse will be generated. <br/>
Fortunately the CPLDs intended to be used (ispMACH4000, XC9500XL) are some 10 years newer than MC68HC000,
so their speed advantage mitigates the problem. <br/>
The negation of Ready0 causes /DTACK generation and termination of the bus cycle
to be delayed until completion of the refresh. <br/>
</p>
<p>
Before showing the timing for the I/O bus slave port on the FSB,
it's instructive to understand the timing of the I/O bus master controller.
</p>
<h3 id="t13">13. I/O Bus E State, VMA, "ETACK"</h3>
<script type="WaveDrom">
{signal: [
@ -483,7 +416,7 @@ terminate the /AS cycle in synchronization with the E clock going low.
<h3 id="t14">14. I/O Bus Access (Even Phase)</h3>
<script type="WaveDrom">
{signal: [
{name: 'IOS', wave:'22222222222222222222|222222', period: 1,data:[0,0,0,0,0,0,1,2,3,4,5,6,7,0,1,2,3,4,5,5,5,6,7,0,0,0,0]},
{name: 'IOS', wave:'22222222222222222222|222222', period: 1,data:[0,0,0,0,0,0,0,2,3,4,5,6,7,0,1,2,3,4,5,5,5,6,7,0,0,0,0]},
{name: 'C16M', wave:'p...................|......', period: 1},
{name: 'C8M', wave:'10101010101010101010|101010', phase:-0.25, period: 1},
{name: 'C8Mr', wave:'01010101010101010101|010101', phase:-0.10, period: 1},

View File

@ -4,22 +4,29 @@ module CS(
/* AS cycle detection */
input BACT,
/* Device select outputs */
output IOCS, output IOPWCS, output IACS, output ROMCS, output RAMCS, output SndRAMCSWR);
output IOCS, output IOPWCS, output IACS,
output ROMCS, output ROMCS4X,
output RAMCS, output RAMCS0X, output SndRAMCSWR);
/* Overlay control */
reg nOverlay = 0; wire Overlay = !nOverlay;
reg ODCSr;
always @(posedge CLK) begin
ODCSr <= (A[23:20]==4'h4) && BACT;
ODCSr <= ROMCS4X && BACT;
if (!BACT) begin
if (!nRES) nOverlay <= 0;
else if (ODCSr) nOverlay <= 1;
end
end
/* Select signals - FSB domain */
assign RAMCS = (A[23:22]==2'b00) && !Overlay; // 000000-3FFFFF when overlay disabled
wire VidRAMCSWR64k = RAMCS && !nWE && (A[21:20]==2'h3) && (A[19:16]==4'hF); // 3F0000-3FFFFF / 7F0000-7FFFFF
/* ROM select signals */
assign ROMCS4X = A[23:20]==4'h4;
assign ROMCS = ((A[23:20]==4'h0) && Overlay) || ROMCS4X;
/* RAM select signals */
assign RAMCS0X = A[23:22]==2'b00;
assign RAMCS = 0;// RAMCS0X && !Overlay;
wire VidRAMCSWR64k = RAMCS && !nWE && (A[23:20]==4'h3) && (A[19:16]==4'hF); // 3F0000-3FFFFF
wire VidRAMCSWR = VidRAMCSWR64k && (
(A[15:12]==4'h2) || // 1792 bytes RAM, 2304 bytes video
(A[15:12]==4'h3) || // 4096 bytes video
@ -37,23 +44,20 @@ module CS(
((A[15:12]==4'hF) && ((A[11:8]==4'hD) || (A[11:8]==4'hE) || (A[11:8]==4'hF))) ||
((A[15:12]==4'hA) && ((A[11:8]==4'h1) || (A[11:8]==4'h2) || (A[11:8]==4'h3))));
assign ROMCS = ((A[23:20]==4'h0) && Overlay) || (A[23:20]==4'h4);
/* Select signals - IOB domain */
assign IACS = (A[23:08]==16'hFFFF); // IACK
assign IOCS = ((A[23:20]==4'h4) && Overlay) || // ROM once
(A[23:20]==4'h5) || // SCSI
(A[23:20]==4'h6) || // empty
(A[23:20]==4'h7) || // empty
(A[23:20]==4'h8) || // empty
(A[23:20]==4'h9) || // SCC read/reset
(A[23:20]==4'hA) || // empty
(A[23:20]==4'hB) || // SCC write
(A[23:20]==4'hC) || // empty / fast ROM
(A[23:20]==4'hD) || // IWM
assign IACS = (A[23:20]==4'hF); // IACK
assign IOCS = (A[23:20]==4'hF) || // IACK
(A[23:20]==4'hE) || // VIA
(A[23:20]==4'hF) || // IACK
VidRAMCSWR;// || (A[23:22]==2'b00);
assign IOPWCS = (A[23:22]==2'b00) && IOCS && !nWE;
(A[23:20]==4'hD) || // IWM
(A[23:20]==4'hC) || // empty / fast ROM
(A[23:20]==4'hB) || // SCC write
(A[23:20]==4'hA) || // empty
(A[23:20]==4'h9) || // SCC read/reset
(A[23:20]==4'h8) || // empty
(A[23:20]==4'h7) || // empty
(A[23:20]==4'h6) || // empty
(A[23:20]==4'h5) || // SCSI
((A[23:20]==4'h4) && Overlay) || // ROM once
(A[23:22]==2'b00); // IORAM
assign IOPWCS = (A[23:22]==2'b00) && !nWE;
endmodule

View File

@ -1,46 +1,31 @@
module FSB(
/* MC68HC000 interface */
input FCLK, input nAS, output reg nDTACK, output nVPA,
input FCLK, input nAS, output reg nDTACK, output reg nVPA,
/* AS cycle detection */
output BACT,
/* Ready inputs */
input Ready0, input Ready1, input Ready2,
input ROMCS,
input RAMCS, input RAMReady,
input IOPWCS, input IOPWReady, input IONPReady,
input QoSCS, input QoSReady,
/* Interrupt acknowledge select */
input IACS);
/* AS cycle detection */
reg ASrf = 0;
always @(negedge FCLK) begin ASrf <= ~nAS; end
assign BACT = ~nAS || ASrf; // BACT - bus active
/* Ready generation and bypass */
reg Ready0r, Ready1r, Ready2r;
wire Ready = (Ready0 || Ready0r) &&
(Ready1 || Ready1r) &&
(Ready2 || Ready2r);
always @(posedge FCLK) begin
if (~BACT) begin
Ready0r <= 0;
Ready1r <= 0;
Ready2r <= 0;
end else begin
if (Ready0) Ready0r <= 1;
if (Ready1) Ready1r <= 1;
if (Ready2) Ready2r <= 1;
end
end
always @(negedge FCLK) begin ASrf <= !nAS; end
assign BACT = !nAS || ASrf; // BACT - bus active
/* DTACK/VPA control */
reg VPA;
assign nVPA = ~(~nAS && VPA);
always @(posedge FCLK) begin
if (~BACT) begin
nDTACK <= 1;
VPA <= 0;
end else if (Ready) begin
nDTACK <= IACS;
VPA <= IACS;
end
wire Ready = /*(RAMCS && RAMReady && !IOPWCS) ||*/
(/*RAMCS && RAMReady &&*/ IOPWCS && IOPWReady /*&& !QoSCS*/) ||
/*(RAMCS && RAMReady && IOPWCS && IOPWReady && QoSCS && QoSReady)*/ ||
(ROMCS) || (IONPReady);
always @(posedge FCLK) nDTACK <= !(Ready && BACT && !IACS);
always @(posedge FCLK, posedge nAS) begin
if (nAS) nVPA <= 1;
else nVPA <= !(Ready && BACT && IACS);
end
endmodule

View File

@ -6,27 +6,34 @@ module IOBM(
/* PDS address and data latch control */
input AoutOE, output nDoutOE, output reg ALE0, output reg nDinLE,
/* IO bus slave port interface */
output reg IOACT,
input IOREQ, input IOLDS, input IOUDS, input IOWE);
input IORDREQ, input IOWRREQ, input IOLDS, input IOUDS,
output reg IOACT, output reg IODONE, output reg IOBERR);
/* I/O bus slave port input synchronization */
reg IOREQr = 0;
always @(negedge C16M) begin IOREQr <= IOREQ; end
/* C8M clock registration */
reg C8Mr; always @(posedge C16M) C8Mr <= C8M;
/* I/O request input synchronization */
reg IORDREQr; always @(posedge C16M) IORDREQr <= IORDREQ;
reg IOWRREQr; always @(posedge C16M) IOWRREQr <= IOWRREQ;
wire IOREQr = IORDREQr || IOWRREQr;
/* DTACK, BERR, RESET synchronization */
reg DTACKrf, BERRrf, RESrf;
always @(negedge C8M) begin
DTACKrf <= !nDTACK;
BERRrf <= !nBERR;
RESrf <= !nRES;
/* DTACK and BERR synchronization */
always @(negedge C8M, posedge nASout) begin
if (nASout) begin
IODONE <= 0;
IOBERR <= 0;
end else begin
IODONE <= (!nDTACK || ETACK || !nRES);
IOBERR <= !nIOBERR;
end
end
/* VPA synchronization */
reg VPAr;
always @(negedge C16M) VPAr <= !nVPA;
/* VPA and RESET synchronization */
reg RESr; always @(posedge C16M) RESr <= !nRES;
reg VPAr; always @(posedge C16M) VPAr <= !nVPA;
/* E clock synchronization */
reg Er; always @(negedge C8M) begin Er <= E; end
reg Er; always @(negedge C8M) begin Er <= E; end
reg Er2; always @(posedge C16M) begin Er2 <= Er; end
/* E clock state */
@ -47,44 +54,51 @@ module IOBM(
/* I/O bus state */
reg [2:0] IOS = 0;
reg IOS0;
always @(posedge C16M) begin
if (IOS==0) begin
if (~C8M && IOREQr && AoutOE) IOS <= 1;
else IOS <= 0;
IOACT <= IOREQr;
ALE0 <= IOREQr;
end else if (IOS==1) begin
IOS <= 2;
IOACT <= 1;
ALE0 <= 1;
if (IOREQr && !C8Mr && AoutOE) begin // "IOS1"
IOS <= 2;
IOS0 <= 0;
end else begin // "regular" IOS0
IOS <= 0;
IOS0 <= 1;
end
IOACT <= IOREQr && AoutOE;
ALE0 <= IOREQr && AoutOE;
end else if (IOS==2) begin
IOS <= 3;
IOS0 <= 0;
IOACT <= 1;
ALE0 <= 1;
end else if (IOS==3) begin
IOS <= 4;
IOS0 <= 0;
IOACT <= 1;
ALE0 <= 1;
end else if (IOS==4) begin
IOS <= 5;
IOS0 <= 0;
IOACT <= 1;
ALE0 <= 1;
if (DTACKrf) IOACT <= 0;
else IOACT <= 1;
end else if (IOS==5) begin
if (C8M && (DTACKrf || ETACK || BERRrf || RESrf)) begin
if (!C8Mr && (IODONE || IOBERR)) begin
IOS <= 6;
IOACT <= 0;
end else begin
IOS <= 5;
IOACT <= 1;
end
IOS0 <= 0;
ALE0 <= 1;
end else if (IOS==6) begin
IOS <= 7;
IOS0 <= 0;
IOACT <= 0;
ALE0 <= 0;
end else if (IOS==7) begin
IOS <= 0;
IOS0 <= 1;
IOACT <= 0;
ALE0 <= 0;
end
@ -92,17 +106,18 @@ module IOBM(
/* PDS address and data latch control */
always @(negedge C16M) begin nDinLE = IOS==4 || IOS==5; end
reg DoutOE = 0; assign nDoutOE = !(AoutOE && DoutOE);
reg DoutOE = 0;
always @(posedge C16M) begin
DoutOE <= ( IOWE && (IOS==1 || IOS==2 || IOS==3 || IOS==4 || IOS==5 || IOS==6)) ||
(!IOREQr && IOS==0 && AoutOE);
DoutOE <= (IOS==0 && IOWRREQr && !C8Mr) ||
(DoutOE && (IOS==2 || IOS==3 || IOS==4 || IOS==5));
end
assign nDoutOE = !(AoutOE && (DoutOE || (IOS==0 && !IOREQr)));
/* AS, DS control */
always @(negedge C16M) begin
nASout <= ~(IOS==1 || IOS==2 || IOS==3 || IOS==4 || IOS==5);
nLDS <= ~(IOLDS && (((IOS==1 || IOS==2) && ~IOWE) || IOS==3 || IOS==4 || IOS==5));
nUDS <= ~(IOUDS && (((IOS==1 || IOS==2) && ~IOWE) || IOS==3 || IOS==4 || IOS==5));
nASout <= ~((IOS==0 && IOREQr && !C8Mr) || IOS==2 || IOS==3 || IOS==4 || IOS==5);
nLDS <= ~(IOLDS && ((IOS==0 && IORDREQr && !C8Mr) || (IOS==2 && IORDREQr) || IOS==3 || IOS==4 || IOS==5));
nUDS <= ~(IOUDS && ((IOS==0 && IORDREQr && !C8Mr) || (IOS==2 && IORDREQr) || IOS==3 || IOS==4 || IOS==5));
end
endmodule

View File

@ -6,21 +6,25 @@ module IOBS(
/* Select signals */
input IOCS, input IOPWCS, input ROMCS,
/* FSB cycle termination outputs */
output IOBS_Ready, output nBERR_FSB,
output reg IONPReady, output reg IOPWReady, output reg nBERR_FSB,
/* Read data OE control */
output nDinOE,
/* IOB Master Controller Interface */
output reg IOREQ, input IOACT, input nIOBERR, input nIODTACK,
/* IOB master controller interface */
output reg IORDREQ, output reg IOWRREQ,
input IOACT, input IODONEin, input IOBERR,
/* FIFO primary level control */
output reg ALE0, output reg IORW0, output reg IOL0, output reg IOU0,
output reg ALE0, output reg IOL0, output reg IOU0,
/* FIFO secondary level control */
output reg ALE1);
/* IOACT input synchronization */
reg IOACTr = 0; always @(posedge CLK) begin IOACTr <= IOACT; end
/* /IODTACK input synchronization */
reg IODTACKr = 0; always @(posedge CLK) begin IODTACKr <= !nIODTACK; end
reg IOACTr = 0; always @(posedge CLK) IOACTr <= IOACT;
/* IODTACK input synchronization */
reg [1:0] IODONErr; reg [1:0] IODONErf;
always @(posedge CLK) IODONErr[1:0] <= { IODONErr[0], IODONEin };
always @(posedge CLK) IODONErf[1:0] <= { IODONErf[0], IODONEin };
wire IODONE = IODONErr[1];
/* Read data OE control */
assign nDinOE = !(!nAS && IOCS && nWE && !ROMCS);
@ -38,99 +42,106 @@ module IOBS(
* transitions to TS1 when IOACT false */
reg [1:0] TS = 0;
reg Sent = 0;
reg PostSent = 0;
/* FIFO second level control */
/* FIFO secondary level control */
reg Load1;
reg Clear1;
reg IORW1;
reg IOL1;
reg IOU1;
always @(posedge CLK) begin
always @(posedge CLK) begin // ALE and R/W load control
// If write currently posting (TS!=0),
// I/O selected, and FIFO secondary level empty
if (TS!=0 && BACT && IOCS && !ALE1 && !Sent && IOPWCS) begin
if (BACT && IOCS && !ALE1 && !Sent && IOPWCS && TS!=0) begin
// Latch R/W now but latch address and LDS/UDS next cycle
IORW1 <= nWE;
Load1 <= 1;
end else Load1 <= 0;
end
always @(posedge CLK) begin
always @(posedge CLK) begin // ALE clear control
// Make address latch transparent in cycle after TS3
// (i.e. first TS2 cycle that's not part of current write)
if (TS==3) Clear1 <= 1;
else Clear1 <= 0;
end
always @(posedge CLK) begin
if (Load1) begin
// Latch address, LDS, UDS when Load1 true
always @(posedge CLK) begin // LDS, UDS, ALE control
if (Load1) begin // Latch address, LDS, UDS when Load1 true
ALE1 <= 1;
IOL1 <= ~nLDS;
IOU1 <= ~nUDS;
IOL1 <= !nLDS;
IOU1 <= !nUDS;
end else if (Clear1) ALE1 <= 0;
end
/* FIFO Primary Level Control */
/* FIFO primary level control */
always @(posedge CLK) begin
if (TS==0) begin
if (ALE1) begin // If FIFO secondary level occupied
// Request transfer from IOBM and latch R/W from FIFO
TS <= 3;
IOREQ <= 1;
IORW0 <= IORW1;
end else if (BACT && IOCS && !ALE1 && !Sent) begin // If I/O selected and FIFO empty
IORDREQ <= IORW1;
IOWRREQ <= !IORW1;
end else if (BACT && IOCS && !ALE1 && !Sent) begin // FSB request
// Request transfer from IOBM and latch R/W from FSB
TS <= 3;
IOREQ <= 1;
IORW0 <= nWE;
IORDREQ <= nWE;
IOWRREQ <= !nWE;
end else begin // Otherwise stay in idle
TS <= 0;
IOREQ <= 0;
IORDREQ <= 0;
IOWRREQ <= 0;
end
ALE0 <= 0;
end else if (TS==3) begin
// Always go to TS2. Keep IOREQ active
TS <= 2;
IOREQ <= 1;
// Latch address (and data)
ALE0 <= 1;
TS <= 2; // Always go to TS2. Keep IORDREQ/IOWRREQ active
ALE0 <= 1; // Latch address (and data)
// Latch data strobes from FIFO or FSB as appropriate
if (ALE1) begin
IOL0 <= IOL1;
IOU0 <= IOU1;
end else begin
IOL0 <= ~nLDS;
IOU0 <= ~nUDS;
IOL0 <= !nLDS;
IOU0 <= !nUDS;
end
end else if (TS==2) begin
// Wait for IOACT then withdraw IOREQ and enter TS1
if (IOACTr) begin
TS <= 1;
IOREQ <= 0;
end else begin
TS <= 2;
IOREQ <= 1;
end
ALE0 <= 1;
IORDREQ <= 0;
IOWRREQ <= 0;
end else TS <= 2;
ALE0 <= 1; // Keep address latched
end else if (TS==1) begin
// Wait for IOACT low (transfer over) before going back to idle
if (~IOACTr) TS <= 0;
if (!IOACTr) TS <= 0;
else TS <= 1;
IOREQ <= 0;
// Address latch released since it's controlled by IOBM now
ALE0 <= 0;
IORDREQ <= 0;
IOWRREQ <= 0;
ALE0 <= 0; // Release addr latch since it's controlled by IOBM now
end
end
/* Sent, ready, BERR control */
reg DTACKEN = 0;
/* Sent control */
always @(posedge CLK) begin
if (~BACT) Sent <= 0;
else if (BACT && IOCS && !ALE1 && !Sent && (TS==0 || IOPWCS)) Sent <= 1;
if (!BACT) Sent <= 0;
else if (BACT && IOCS && !ALE1 && (IOPWCS || TS==0)) Sent <= 1;
end
/* Nonposted ready */
always @(posedge CLK) begin
if (~BACT) DTACKEN <= 0;
else if (IOCS && !IOPWCS && !ALE1 && Sent && IOACTr) DTACKEN <= 1;
if (!BACT) IONPReady <= 0;
else if (Sent && !IOPWCS && IODONE) IONPReady <= 1;
end
/* Posted ready */
always @(posedge CLK) begin
if (!BACT) IOPWReady <= 0;
else if (Clear1 || !ALE1) IOPWReady <= 1;
end
/* BERR control */
always @(posedge CLK) begin
if (!BACT) nBERR_FSB <= 1;
else if (Sent && IOBERR) nBERR_FSB <= 0;
end
assign IOBS_Ready = !IOCS || (IOPWCS && !ALE1) || (DTACKEN && (!IOACT || IODTACKr));
assign nBERR_FSB = !(DTACKEN && !nIOBERR);
endmodule

View File

@ -4,179 +4,153 @@ module RAM(
/* AS cycle detection */
input BACT,
/* Select and ready signals */
input RAMCS, input ROMCS, output RAM_Ready,
input RAMCS, input ROMCS, output reg RAMReady,
/* 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
/* BACT saved from last cycle */
reg BACTr; always @(posedge CLK) BACTr <= BACT;
/* Refresh command generation */
reg RefDone; // Refresh done "remember"
always @(posedge CLK) begin
if (!RefReqIn && !RefUrgIn) RefDone <= 0;
else if (RS==4 || RS==5) RefDone <= 1;
end
wire RefReq = RefReqIn && !RefDone;
wire RefUrg = RefUrgIn && !RefDone;
/* RAM control state */
reg [2:0] RS = 0;
reg RAMEN = 0;
reg RAMReady = 0;
reg RASEL = 0; // RASEL controls /CAS signal
reg Once = 0;
reg RASEL = 0;
reg CAS = 0;
reg RASrr = 0;
reg RASrf = 0;
/* 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 RAMEN <= 1;
end
end
/* Refresh state */
reg RefRAS = 0;
/* RAM control signals */
assign nRAS = !((!nAS && RAMCS && RAMEN) || RASrr || RASrf);
assign nOE = !((!nAS && nWE)); // Shared with ROM
assign nLWE = !((!nAS && !nWE && !nLDS && RAMEN));
assign nUWE = !((!nAS && !nWE && !nUDS && RAMEN));
/* ROM control signals */
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);
assign nROMWE = !((!nAS && !nWE));
/* RAM address mux (and ROM address on RA8) */
assign RA[11] = ROMCS ? A[19] : !RASEL ? A[21] : A[20];
assign RA[03] = !RASEL ? A[21] : A[20];
assign RA[10] = !RASEL ? A[19] : A[17];
assign RA[02] = !RASEL ? A[18] : A[17];
assign RA[09] = !RASEL ? A[16] : A[08];
assign RA[08] = ROMCS ? A[18] : !RASEL ? A[15] : A[07];
assign RA[07] = !RASEL ? A[14] : A[06];
assign RA[06] = !RASEL ? A[13] : A[05];
assign RA[05] = !RASEL ? A[12] : A[04];
assign RA[04] = !RASEL ? A[11] : A[03];
assign RA[01] = !RASEL ? A[10] : A[02];
assign RA[00] = !RASEL ? A[09] : A[01];
// RA11 doesn't do anything so both should be identical.
assign RA[11] = !RASEL ? A[19] : A[20]; // ROM address 19
assign RA[03] = !RASEL ? A[19] : A[20];
// RA10 has only row so different rows but same column.
assign RA[10] = !RASEL ? A[17] : A[07];
assign RA[02] = !RASEL ? A[16] : A[07];
// Remainder of RA bus is unpaired
assign RA[09] = !RASEL ? A[15] : A[08];
assign RA[08] = !RASEL ? A[18] : A[21]; // ROM address 18
assign RA[07] = !RASEL ? A[14] : A[06];
assign RA[06] = !RASEL ? A[13] : A[05];
assign RA[05] = !RASEL ? A[12] : A[04];
assign RA[04] = !RASEL ? A[11] : A[03];
assign RA[01] = !RASEL ? A[10] : A[02];
assign RA[00] = !RASEL ? A[09] : A[01];
wire RefFromRS0 = ((RefReq && BACT && !BACTr && !RAMCS) ||
(RefUrg && !BACT) ||
(RefUrg && BACT && !RAMEN));
wire RefFromRS2 = RefUrg;
wire RAMStart = BACT && RAMCS && RAMEN;
always @(posedge CLK) begin
if (RS==0) begin
// In RS0, RAM is idle and ready for new command.
if (RefFromRS0Next) begin
case (RS[3:0])
0: begin
if (RAMStart) begin
RS <= 1;
RASEL <= 1;
CAS <= 1;
RASrr <= 1;
end else if (RefFromRS0) begin
RS <= 3;
RASEL <= 0;
CAS <= 1;
RASrr <= 0;
end else begin
RS <= 0;
RASEL <= 0;
CAS <= 0;
RASrr <= 0;
end
end 1: 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;
CAS <= 1;
RASrr <= 0;
end 2: begin
if (RefFromRS2) begin
RS <= 3;
RASEL <= 0;
CAS <= 1;
RASrr <= 0;
end else begin
RS <= 7;
RASEL <= 0;
CAS <= 0;
RASrr <= 0;
end
end 3: begin
RS <= 4;
RASEL <= 0;
end else if (BACT && RAMCS && RAMEN) begin
// RAM access cycle has priority over urgent refresh if RAM access already begun
CAS <= 1;
RASrr <= 1;
end 4: begin
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
CAS <= 0;
RASrr <= 1;
end 5: begin
RS <= 6;
RASEL <= 0;
CAS <= 0;
RASrr <= 0;
end 6: begin
RS <= 7;
RASEL <= 0;
CAS <= 0;
RASrr <= 0;
end 7: begin
RS <= 0;
RAMReady <= 1;
RASEL <= 0;
CAS <= 0;
RASrr <= 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
endcase
end
always @(negedge CLK) begin nCAS <= ~RASEL; end
always @(negedge CLK) RASrf <= RS==1;
always @(negedge CLK) nCAS <= !CAS;
assign RAM_Ready = ~RAMCS || RAMReady;
/* RAM state control */
always @(posedge CLK) begin
if (RS==0 && RefFromRS0) RAMEN <= 0;
else if (RS==1) RAMEN <= 0;
else if (!BACT && RS==7) RAMEN <= 1;
else if (!BACT && RS==0) RAMEN <= 1;
else if (!Once && RS==7) RAMEN <= 1;
else if (!Once && RS==0) RAMEN <= 1; // not needed?
end
always @(posedge CLK) begin
if (!BACT) Once <= 0;
else if (RS==0 && RAMStart) Once <= 1;
end
/* RAM ready signal */
always @(posedge CLK) begin
if (RS==7) RAMReady <= 1;
if (RS==0 && !RefFromRS0) RAMReady <= 1;
if (BACT && RAMReady) RAMReady <= 1;
else RAMReady <= 0;
end
endmodule

View File

@ -42,7 +42,7 @@ module WarpSE(
/* FSB clock oscillator enables */
// Enable both oscillators... only mount one
assign C20MEN = 1;
assign C20MEN = 0;
assign C25MEN = 1;
/* Reset input and open-drain output */
@ -57,50 +57,56 @@ module WarpSE(
wire RefReq, RefUrg;
/* FSB chip select signals */
wire IOCS, IOPWCS, IACS, ROMCS, RAMCS, SndRAMCSWR;
wire IOCS, IOPWCS, IACS;
wire ROMCS, ROMCS4X;
wire RAMCS, RAMCS0X, SndRAMCSWR;
CS cs(
/* MC68HC000 interface */
A_FSB[23:08], FCLK, nRESin, nWE_FSB,
/* AS cycle detection */
BACT,
/* Device select outputs */
IOCS, IOPWCS, IACS, ROMCS, RAMCS, SndRAMCSWR);
IOCS, IOPWCS, IACS,
ROMCS, ROMCS4X,
RAMCS, RAMCS0X, SndRAMCSWR);
wire RAM_Ready;
wire RAMReady;
RAM ram(
/* MC68HC000 interface */
FCLK, A_FSB[21:1], nWE_FSB, nAS_FSB, nLDS_FSB, nUDS_FSB,
/* AS cycle detection */
/* AS cycle detection */
BACT,
/* Select and ready signals */
RAMCS, ROMCS, RAM_Ready,
RAMCS, ROMCS, RAMReady,
/* Refresh Counter Interface */
RefReq, RefUrg,
/* DRAM and NOR flash interface */
RA[11:0], nRAS, nCAS,
nRAMLWE, nRAMUWE, nOE, nROMCS, nROMWE);
wire IOBS_Ready;
wire IOREQ, IOACT;
wire IONPReady, IOPWReady;
wire IORDREQ, IOWRREQ;
wire IOL0, IOU0;
wire ALE0S, ALE0M, ALE1;
assign nADoutLE0 = ~(ALE0S || ALE0M);
assign nADoutLE1 = ~ALE1;
wire IORW0, IOL0, IOU0;
wire IOACT, IODONE, IOBERR;
IOBS iobs(
/* MC68HC000 interface */
FCLK, nWE_FSB, nAS_FSB, nLDS_FSB, nUDS_FSB,
/* AS cycle detection, FSB BERR */
/* AS cycle detection */
BACT,
/* Select signals */
IOCS, IOPWCS, ROMCS,
/* FSB cycle termination outputs */
IOBS_Ready, nBERR_FSB,
IONPReady, IOPWReady, nBERR_FSB,
/* Read data OE control */
nDinOE,
/* IOB Master Controller Interface */
IOREQ, IOACT, nBERR_IOB, nDTACK_IOB,
IORDREQ, IOWRREQ,
IOACT, IODONE, IOBERR,
/* FIFO primary level control */
ALE0S, IORW0, IOL0, IOU0,
ALE0S, IOL0, IOU0,
/* FIFO secondary level control */
ALE1);
@ -119,8 +125,8 @@ module WarpSE(
/* PDS address and data latch control */
AoutOE, nDoutOE, ALE0M, nDinLE,
/* IO bus slave port interface */
IOACT,
IOREQ, IOL0, IOU0, !IORW0);
IORDREQ, IOWRREQ, IOL0, IOU0,
IOACT, IODONE, IOBERR);
CNT cnt(
/* FSB clock and E clock inputs */
@ -138,7 +144,10 @@ module WarpSE(
/* FSB cycle detection */
BACT,
/* Ready inputs */
RAM_Ready, IOBS_Ready, 1,
ROMCS4X,
RAMCS0X, RAMReady,
IOPWCS, IOPWReady, IONPReady,
SndRAMCSWR, 1,
/* Interrupt acknowledge select */
IACS);