Revisited PAL logic equations, now looking really great!
This commit is contained in:
parent
f039437b21
commit
20c56b0eda
|
@ -64,13 +64,13 @@ module tsm(simclk, n_res,
|
||||||
// Simulate combinatorial logic.
|
// Simulate combinatorial logic.
|
||||||
assign casl
|
assign casl
|
||||||
= ~(~s0 & s1 & sysclk // video
|
= ~(~s0 & s1 & sysclk // video
|
||||||
| ~s0 & ~ramen & ~lds // processor
|
| ~s0 & ~ramen & ~lds & sysclk // processor
|
||||||
| ~s0 & ~casl & sysclk
|
| ~s0 & ~casl
|
||||||
| pclk & ~casl);
|
| pclk & ~casl);
|
||||||
assign cash
|
assign cash
|
||||||
= ~(~s0 & s1 & sysclk // video
|
= ~(~s0 & s1 & sysclk // video
|
||||||
| ~s0 & ~ramen & ~uds // processor
|
| ~s0 & ~ramen & ~uds & sysclk // processor
|
||||||
| ~s0 & ~cash & sysclk
|
| ~s0 & ~cash
|
||||||
| pclk & ~cash);
|
| pclk & ~cash);
|
||||||
assign s0
|
assign s0
|
||||||
= ~(~ras & ~sysclk // 0 for `cas` and 1 for `ras` (counting with the delay of the PAL)
|
= ~(~ras & ~sysclk // 0 for `cas` and 1 for `ras` (counting with the delay of the PAL)
|
||||||
|
@ -139,129 +139,66 @@ module lag(simclk, n_res,
|
||||||
vsync <=
|
vsync <=
|
||||||
~(reslin
|
~(reslin
|
||||||
| ~vsync & ~l28);
|
| ~vsync & ~l28);
|
||||||
// hsync <=
|
|
||||||
// ~(viapb6 & va4 & ~va3 & ~va2 & va1 // begins in 29 (VA5)
|
|
||||||
// | /*~ ???*/resnyb
|
|
||||||
// | ~hsync & viapb6); // ends in 0F
|
|
||||||
// hsync <=
|
|
||||||
// ~(~viapb6 & ~va4 & ~va3 & va2 & va1 // begins in 29 (VA5)
|
|
||||||
// | ~hsync & ~va4
|
|
||||||
// | ~hsync & ~viapb6); // ends in 0F
|
|
||||||
// TODO FIXME: This is incorrect, temporary equations in order
|
|
||||||
// to get at least partial behavior for analysis.
|
|
||||||
// TODO FIXME: We trigger hsync a bit too soon at the end of the
|
|
||||||
// scanline. And, we release it too soon at the beginning.
|
|
||||||
// HACKED ~vclk inserted
|
|
||||||
hsync <=
|
hsync <=
|
||||||
~(viapb6 & ~vclk & va1 & va2 & va3 & va4 /* FIXME & va4 & ~va3 & ~va2 & va1 */
|
~(~viapb6 & ~va4 & ~va3 & va2 & ~va1 // begins in 22 (VA6)
|
||||||
|
| ~hsync & ~viapb6
|
||||||
| ~hsync & ~va4
|
| ~hsync & ~va4
|
||||||
| ~hsync & ~va3
|
| ~hsync & va3
|
||||||
| ~hsync & va2
|
| ~hsync & va2
|
||||||
| ~hsync & va1);
|
| ~hsync & va1); // ends in 07
|
||||||
// TODO TEST NEATER REWRITES:
|
|
||||||
// viapb6 <=
|
|
||||||
// ~(~hsync & ~va4 & ~va3 & va2 & va1
|
|
||||||
// | ~viapb6 & snddma
|
|
||||||
// | ~viapb6 & vclk);
|
|
||||||
// hsync <=
|
|
||||||
// ~(~viapb6 & ~va4 & ~va3 & va2 & ~va1
|
|
||||||
// | ~hsync & ~viapb6
|
|
||||||
// | ~hsync & ~va4);
|
|
||||||
s1 <=
|
s1 <=
|
||||||
~(~p0q2 // 0 for processor and 1 for video
|
~(~p0q2 // 0 for processor and 1 for video
|
||||||
| ~vclk
|
| ~vclk
|
||||||
| ~vsync & hsync
|
| ~vsync & hsync
|
||||||
| ~vsync & viapb6 // vertical retrace only has sound cycles
|
| ~vsync & viapb6 // vertical retrace only has sound cycles
|
||||||
// Next line HACKED, was: ~viapb6 & hsync & ~va4 & ~va3 & ~va2
|
| ~viapb6 & hsync & ~va4 & ~va3 & ~va2
|
||||||
| ~vsync & ~viapb6 & ~hsync & va4 & va3 & va2 & va1
|
|
||||||
| ~viapb6 & ~hsync & ~va4
|
| ~viapb6 & ~hsync & ~va4
|
||||||
| ~viapb6 & ~hsync & va4 & ~va3 & ~va2
|
| ~viapb6 & ~hsync & va4 & ~va3 & ~va2
|
||||||
| ~viapb6 & ~hsync & va4 & ~va3 & va2 & ~va1);
|
| ~viapb6 & ~hsync & va4 & ~va3 & va2 & ~va1);
|
||||||
// viapb6 <=
|
|
||||||
// ~(~hsync & resnyb // 1 indicates horizontal retrace (pseudo VA6)
|
|
||||||
// | va1 & ~viapb6
|
|
||||||
// | va2 & ~viapb6
|
|
||||||
// | ~hsync & ~viapb6
|
|
||||||
// | resnyb & ~viapb6
|
|
||||||
// | vshft & ~viapb6);
|
|
||||||
// viapb6 <=
|
|
||||||
// ~(hsync & ~va4 & ~va3 & va2 & va1 // 1 indicates horizontal retrace (pseudo VA6)
|
|
||||||
// | ~viapb6 & snddma
|
|
||||||
// | ~viapb6 & vclk);
|
|
||||||
// TODO FIXME: This is incorrect, temporary equations in order
|
|
||||||
// to get at least partial behavior for analysis.
|
|
||||||
// TODO FIXME: Why this latches up and is broken, we should not
|
|
||||||
// use memory access to clock this to one sensitivity cycle.
|
|
||||||
|
|
||||||
// TODO FIXME: Okay, this is how to do it. The trick is within
|
|
||||||
// "self-latching" logic equations. When another clock period
|
|
||||||
// remains the same, we use self-latching logic equations, but
|
|
||||||
// they loose effect... okay, I don't know what I'm talking
|
|
||||||
// about.
|
|
||||||
viapb6 <=
|
viapb6 <=
|
||||||
~(~hsync // 1 indicates horizontal retrace (pseudo VA6)
|
~(hsync & ~va4 & ~va3 & va2 & va1 // 1 indicates horizontal retrace (pseudo VA6)
|
||||||
/* | ~viapb6 & p0q2
|
| ~viapb6 & snddma
|
||||||
| ~viapb6 & ~s1 */
|
| ~viapb6 & vclk);
|
||||||
| ~viapb6 & ~vclk
|
|
||||||
| ~viapb6 & ~va1 // TODO FIXME wrong phase
|
|
||||||
| ~viapb6 & ~va2
|
|
||||||
| ~viapb6 & ~va3
|
|
||||||
| ~viapb6 & ~va4);
|
|
||||||
snddma <=
|
snddma <=
|
||||||
~(~viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 in this output
|
~(~viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 in this output
|
||||||
| ~snddma & vclk); // ... indicates sound cycle
|
| ~snddma & vclk); // ... indicates sound cycle
|
||||||
reslin <= // try to generate line 370
|
reslin <= // try to generate line 370
|
||||||
~(l28
|
~(l28
|
||||||
| ~vsync
|
| ~vsync
|
||||||
| ~hsync // HACKED previously hsync, but negated for testing.
|
| hsync
|
||||||
| viapb6 // HACKED previously ~viapb6 but negated for testing.
|
| ~viapb6
|
||||||
| ~vclk);
|
| ~vclk);
|
||||||
// N.B. Primary conceptual equation:
|
|
||||||
// resnyb <=
|
|
||||||
// ((~viapb6 & hsync & ~va4 & ~va3 & ~va2 & ~va1)
|
|
||||||
// | (~viapb6 & ~hsync & va4 & va3 & ~va2 & ~va1));
|
|
||||||
// TODO FIXME HACK: Possibly incorrect interpretation of viapb6
|
|
||||||
// with hsync.
|
|
||||||
resnyb <=
|
resnyb <=
|
||||||
~(vclk // increment VA5:VA14 in 0F and 2B
|
~(vclk // increment VA5:VA14 in 0F and 2B
|
||||||
| // viapb6 // TODO FIXME HACK PHASE
|
| p0q2
|
||||||
| va1
|
| va1
|
||||||
| va2
|
| va2
|
||||||
| hsync & va4
|
| ~viapb6 & va3
|
||||||
| hsync & va3
|
| hsync & ~viapb6
|
||||||
| ~hsync & ~va4
|
| hsync & va3
|
||||||
| ~hsync & ~va3
|
| hsync & va4
|
||||||
| ~va4 & va3
|
| viapb6 & ~va3 & ~hsync
|
||||||
| va4 & ~va3);
|
| ~hsync & va3 & ~va4
|
||||||
// TODO TEST NEATER REWRITES:
|
| ~hsync & ~va3 & va4);
|
||||||
// ??? = /SOM . /VCLK + HS . P6 . /4 . /3 . /2 . /1
|
|
||||||
// /RN = P2 . P6 . /4 . /3 . /2 . /1 + /RN . P2 + /RN . SOM . 4 + /RN . SOM . 3 + /RN . SOM . 2 + /RN . SOM . 1 + /RN . /P6 . HS + VCLK
|
|
||||||
// ??? = P6 . /VCLK . /P2 . /HS . 4 . 3 . /2 . /1 + /VCLK . /P2 . /P6 . <CHOPPED OFF?>/4 . /3 . /2 . /1
|
|
||||||
// N.B. P2 maybe shorthand for P0Q2?
|
|
||||||
// POSSIBLY SIMPLIFIED EQUATIONS?
|
|
||||||
// ??? = HS . 4 + HS . 3 + /HS . /4 + /4 . 3 + /HS . /3 + 4 . /3
|
|
||||||
// ??? = [/P6 VCLK P2 2 1] + (HS + /4 + /3)(/HS + 4 . <CHOPPED OFF>
|
|
||||||
// ??? = /VA4 * /VA3 * /HSYNC * /V <CHOPPED OFF>
|
|
||||||
// ...<CONTINUE> VA4 * VA3 * /HSYNC * V <CHOPPED OFF>
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
/*
|
/* Here's how the LAG works.
|
||||||
This LAG doesn't work correctly, here's how it is supposed to work.
|
|
||||||
|
|
||||||
1. Count video addresses to 32. During this count, generate resnyb
|
1. Count video addresses to 32. During this count, generate resnyb
|
||||||
every time we need a carry.
|
(reset nybble) every time we need a carry.
|
||||||
|
|
||||||
2. Once we reach 32, that's 512 pixels, one scanline. Now, we assert
|
2. Once we reach 32, that's 512 pixels, one scanline. Wait 16 more
|
||||||
the *HSYNC signal. But please note, at this point we do **not**
|
pixels to generate a blank overscan image. Now, we assert the
|
||||||
|
*HSYNC signal. But please note, at this point we do **not**
|
||||||
generate resnyb for the carry at 32, instead we let that counter
|
generate resnyb for the carry at 32, instead we let that counter
|
||||||
wrap around to zero without a carry.
|
wrap around to zero without a carry.
|
||||||
|
|
||||||
3. When the *HSYNC signal is asserted, we only count to 12. That's
|
3. During horizontal blanking, we only count to 12. That's 192 pixels
|
||||||
192 pixels for horizontal blanking. Just when we're about to reach
|
for horizontal blanking. Just when we're about to reach the end,
|
||||||
the end, we assert the *SNDDMA signal. That's when we fetch the
|
we assert the *SNDDMA signal. That's when we fetch the sound
|
||||||
sound sample, at the very end of horizontal blanking, not the very
|
sample, at the very end of horizontal blanking, not the very
|
||||||
beginning.
|
beginning.
|
||||||
|
|
||||||
Finally, we assert resnyb to clear the counter and finally
|
Finally, we assert resnyb to clear the counter and finally
|
||||||
|
@ -275,12 +212,46 @@ But, to implement this... it's tricky because va5 and va6 are not
|
||||||
connected to any PAL. How do we generate the signals then? We can
|
connected to any PAL. How do we generate the signals then? We can
|
||||||
otherwise only count to 16, we need to get to 32.
|
otherwise only count to 16, we need to get to 32.
|
||||||
|
|
||||||
Okay, I think I've got it figured out. VIAPB6 is a little white lie,
|
Okay, I've got it figured out. VIAPB6 is a little white lie, it's not
|
||||||
it's not the actual horizontal blanking signal, it's a prep signal
|
the actual horizontal blanking signal, it's a prep signal before the
|
||||||
before the horizontal blanking actually occurs. But, nevertheless, it
|
horizontal blanking actually occurs. But, nevertheless, it is almost
|
||||||
is almost the same thing, 16 cycles at 16MHz rather than 12 cycles.
|
the same thing, 19 cycles at 1MHz rather than 12 cycles. Here's how
|
||||||
For the 8 MHz CPU, it pretty much looks like the same thing. And
|
the whole interplay works in detail.
|
||||||
that's where we hide the additional bit of memory we need.
|
|
||||||
|
1. Immediately after *SNDDMA is asserted, VIAPB6 is asserted.
|
||||||
|
|
||||||
|
2. Now, here's where the real trickery comes into play. Even though
|
||||||
|
horizontal blanking is supposed to end right now, we delay
|
||||||
|
de-asserting the *HSYNC signal until we reach video address 8, such
|
||||||
|
that we start shifting out visible screen pixels apparently during
|
||||||
|
the horizontal blanking period. Why? Well we need this glitched
|
||||||
|
behavior so we can count to 32 with only 4 video address bits.
|
||||||
|
|
||||||
|
Apparently this is still within the tolerance of the CRT circuitry:
|
||||||
|
the CRT actually completes horizontal blanking and starts the
|
||||||
|
regular visible area sweep before we de-assert *HSYNC, so actually
|
||||||
|
we won't be drawing these pixels during horizontal blanking.
|
||||||
|
|
||||||
|
3. Now, the ultimate conclusion of the glitched counter. When we
|
||||||
|
wrap-around to zero, both *HSYNC and VIAPB6 are still asserted. We
|
||||||
|
check for this condition to generate resnyb in the middle of a
|
||||||
|
scanline.
|
||||||
|
|
||||||
|
4. VIAPB6 is deasserted at video address 19. Therefore, it is
|
||||||
|
asserted for a total of 19 cycles at 1MHz.
|
||||||
|
|
||||||
|
Let's summarize the information pertinent to sound timing and VIAPB6.
|
||||||
|
|
||||||
|
1. *SNDDMA is asserted at the very end of horizontal blanking, just
|
||||||
|
before the beginning of the visible line.
|
||||||
|
2. Immediately after *SNDDMA is asserted, VIAPB6 is asserted (+5V).
|
||||||
|
3. VIAPB6 remains high for 19 cycles @ 1MHz.
|
||||||
|
4. VIAPB6 is deasserted.
|
||||||
|
|
||||||
|
Sound sample #0 is fetched from the Macintosh's sound buffer at the
|
||||||
|
end of the first vertical blanking line, #28 at the end of the first
|
||||||
|
visible video line, and the last sound sample #369 is fetched at the
|
||||||
|
end of the last visible video line.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -327,15 +298,15 @@ module bmu1(simclk, n_res,
|
||||||
= ~(~a23 & ~a22 & ~a21 & ~as & ~ovlay // 000000
|
= ~(~a23 & ~a22 & ~a21 & ~as & ~ovlay // 000000
|
||||||
| ~a23 & a22 & a21 & ~as & ovlay); // (600000 with `ovlay`)
|
| ~a23 & a22 & a21 & ~as & ovlay); // (600000 with `ovlay`)
|
||||||
assign io1
|
assign io1
|
||||||
= ~(~l15 & ~va9 & va8 & ~va7 // reached 368 or we don't pass line 26
|
= ~(~l15 & ~va9 & va8 & ~va7 // reached 368
|
||||||
| ~l28 & ~l15
|
| ~l28 & ~l15 // ... or we don't pass line 26
|
||||||
| ~l28 & ~va9
|
| ~l28 & ~va9
|
||||||
| ~l28 & va8
|
| ~l28 & va8
|
||||||
| ~l28 & ~va7
|
| ~l28 & ~va7
|
||||||
| ~n_res); // SIMULATION ONLY: Else we never settle.
|
| ~n_res); // SIMULATION ONLY: Else we never settle.
|
||||||
assign l28
|
assign l28
|
||||||
= ~(~l15 & ~va9 & ~va8 & va7 // reached 370 or we don't pass line 28
|
= ~(~l15 & ~va9 & ~va8 & va7 // reached 370
|
||||||
| ~l28 & ~l15
|
| ~l28 & ~l15 // ... or we don't pass line 28
|
||||||
| ~l28 & ~va9
|
| ~l28 & ~va9
|
||||||
| ~l28 & ~va8
|
| ~l28 & ~va8
|
||||||
| ~l28 & va7
|
| ~l28 & va7
|
||||||
|
@ -411,10 +382,11 @@ module tsg(simclk, n_res,
|
||||||
|
|
||||||
// Simulate combinatorial logic.
|
// Simulate combinatorial logic.
|
||||||
assign ipl0
|
assign ipl0
|
||||||
= ~intscc | intvia; // CORRECTION
|
= ~intscc | intvia;
|
||||||
// assign ipl0 = ~(0); // ??? /M nanda
|
// N.B.: We tristate D0 so that we don't interfere with unrelated
|
||||||
|
// address bus uses.
|
||||||
assign d0
|
assign d0
|
||||||
= ~(~vpa & ~a19 & e); // F00000 sample the phase with 0 /n e' + usado
|
= (~vpa & ~a19 & e) ? ~(vcc) : 'bz; // F00000 sample the phase with 0 /n e' + usado
|
||||||
|
|
||||||
// Simulate registered logic.
|
// Simulate registered logic.
|
||||||
always @(posedge sysclk) begin
|
always @(posedge sysclk) begin
|
||||||
|
@ -427,7 +399,7 @@ module tsg(simclk, n_res,
|
||||||
| clkscc & ~pclk & vclk
|
| clkscc & ~pclk & vclk
|
||||||
| ~clkscc & pclk
|
| ~clkscc & pclk
|
||||||
| ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
|
| ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
|
||||||
viacb1 <= ~(0); // ??? /M nanda
|
viacb1 <= ~(~keyclk); // buffer the keyboard clock
|
||||||
pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz)
|
pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz)
|
||||||
q3 <= ~(~vclk); // `sysclk` / 16
|
q3 <= ~(~vclk); // `sysclk` / 16
|
||||||
q4 <=
|
q4 <=
|
||||||
|
@ -734,9 +706,6 @@ module palcl(simclk, vcc, gnd, n_res, n_sysclk,
|
||||||
// TSEN1: 150 ohm resistor to GND for LAG.
|
// TSEN1: 150 ohm resistor to GND for LAG.
|
||||||
assign lag_oe2 = gnd;
|
assign lag_oe2 = gnd;
|
||||||
// Pull-down resistor shared by TSG, ASG, and CAS (if present).
|
// Pull-down resistor shared by TSG, ASG, and CAS (if present).
|
||||||
// TODO INVESTIGATE: Surely this is controlled by another switch
|
|
||||||
// related to the RAM data bus switches, otherwise D0 is
|
|
||||||
// unconditionally coerced for non-phase read accesses.
|
|
||||||
assign tsg_oe3 = gnd;
|
assign tsg_oe3 = gnd;
|
||||||
// S5: Pull-up resistor. TODO FIXME: Should this be controlled by
|
// S5: Pull-up resistor. TODO FIXME: Should this be controlled by
|
||||||
// another thing too?
|
// another thing too?
|
||||||
|
|
Loading…
Reference in New Issue