mirror of
https://github.com/quorten/macsehw.git
synced 2025-02-11 15:30:29 +00:00
Work-in-progress improvements to BBU.
This commit is contained in:
parent
7ef514a1eb
commit
5fc5d3489d
@ -2,3 +2,24 @@
|
||||
|
||||
This directory contains the firmware for the ADB (Apple Desktop Bus)
|
||||
chip, which is actually an Apple-branded PIC16CR54 microcontroller.
|
||||
|
||||
# Functioning of the ADB
|
||||
|
||||
See Guide to the Macintosh Family Hardware, page 312.
|
||||
|
||||
* Automatically polls the last device that has sent data, the _active
|
||||
device_. Then shifts it out to the VIA, that causes an interrupt.
|
||||
|
||||
* A non-active device asserts a _Service Request_ signal to the ADB
|
||||
when it has data to send. The ADB asserts an interrupt request
|
||||
signal to the VIA, which sets bit 3 in data register 3 to 0.
|
||||
Respond to requests of the ADB Manager to poll each device to find
|
||||
which one asserted the Service Request.
|
||||
|
||||
Data bits are encoded as follows:
|
||||
|
||||
* Bit-cell time: 100 us
|
||||
|
||||
* 0: low 65 us
|
||||
|
||||
* 1: low 35 us
|
||||
|
@ -12,8 +12,14 @@ all: $(TARGETS)
|
||||
|
||||
bbu.vvp: bbu.v common.vh
|
||||
test_stdlogic.vvp: test_stdlogic.v stdlogic.v common.vh
|
||||
|
||||
test_mac128pal.vvp: test_mac128pal.v test_stdlogic.v stdlogic.v \
|
||||
mac128pal.v common.vh
|
||||
iverilog -Wanachronisms -Wimplicit -Wportbind -Wselect-range \
|
||||
-Winfloop -Wsensitivity-entire-vector \
|
||||
-Wsensitivity-entire-array \
|
||||
-o $@ $<
|
||||
./test_mac128pal.vvp -lxt
|
||||
|
||||
clean:
|
||||
rm -f $(TARGETS)
|
||||
|
@ -8,3 +8,4 @@ curl -L -o 'http://www.applelogic.org/files/Z8530UM.pdf'
|
||||
curl -L -O 'http://archive.6502.org/datasheets/rockwell_r6522_via.pdf'
|
||||
curl -L -O 'http://www.assmann-wsw.com/fileadmin/datasheets/ASS_0981_CO.pdf'
|
||||
curl -L -O 'https://media.digikey.com/pdf/Data%20Sheets/Rohm%20PDFs/MSM51V17405F.pdf'
|
||||
curl -L -O 'http://www.bitsavers.org/components/vti/databook/1986_VTI_Gate_Array_Design_Manual.pdf'
|
||||
|
55
hardware/fpga/bbu/lfsr.c
Normal file
55
hardware/fpga/bbu/lfsr.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
20210403/https://patentimages.storage.googleapis.com/52/04/e8/f5a5f0a7214a9c/US4910670.pdf
|
||||
20210403/https://github.com/mamedev/mame/blob/master/src/mame/drivers/mac128.cpp#L486
|
||||
20210403/https://en.wikipedia.org/wiki/Linear-feedback_shift_register
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int k = 1;
|
||||
/* if (argc != 2)
|
||||
return 1;
|
||||
if (sreg == 0)
|
||||
return 1; */
|
||||
|
||||
fputs(" 0, ", stdout);
|
||||
while (k < 64) {
|
||||
unsigned char sreg;
|
||||
unsigned char preg;
|
||||
unsigned char j;
|
||||
unsigned int i = 0;
|
||||
/* sreg = (char)atoi(argv[1]); */
|
||||
sreg = k;
|
||||
sreg &= 64 - 1;
|
||||
/* N.B.: Careful, we do not check the exit condition at the start.
|
||||
We must have a special hardware condition check to allow
|
||||
shifting once before triggering the exit condition. As we also
|
||||
do for the zero condition. */
|
||||
do {
|
||||
sreg = (sreg >> 1) |
|
||||
((((sreg >> 0) ^ (sreg >> 1)) & 1) << 5);
|
||||
sreg &= 64 - 1;
|
||||
|
||||
preg = sreg;
|
||||
/* j = 6;
|
||||
while (j > 0) {
|
||||
j--;
|
||||
putchar((preg & (1 << 5)) ? '1' : '0');
|
||||
preg <<= 1;
|
||||
}
|
||||
putchar('\n'); */
|
||||
i++;
|
||||
} while (sreg != 0x20);
|
||||
printf("%2d, ", i);
|
||||
k++;
|
||||
if ((k & (8 - 1)) == 0)
|
||||
putchar('\n');
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
return 0;
|
||||
}
|
@ -53,12 +53,15 @@ module tsm(simclk, n_res,
|
||||
output wire s0, dtack;
|
||||
`power wire vcc;
|
||||
|
||||
reg qx;
|
||||
|
||||
// We must implement RESET for simulation or else this will never
|
||||
// stabilize.
|
||||
always @(negedge n_res) begin
|
||||
// casl = 1; cash = 1; s0 = 1; dtack = 1;
|
||||
|
||||
ras <= 1; vclk <= 1; q2 <= 1; q1 <= 1;
|
||||
qx <= 1;
|
||||
end
|
||||
|
||||
// Simulate combinatorial logic.
|
||||
@ -88,18 +91,30 @@ module tsm(simclk, n_res,
|
||||
~(~pclk & q1 & s1 // video cycle
|
||||
| ~pclk & q1 & ~ramen & dtack // processor cycle
|
||||
| pclk & ~ras); // any other cycle
|
||||
vclk <=
|
||||
/* vclk <=
|
||||
~(~q1 & pclk & q2 & vclk // divide by 8 (1MHz)
|
||||
| ~vclk & q1
|
||||
| ~vclk & ~pclk
|
||||
| ~vclk & ~q2);
|
||||
| ~vclk & ~q2); */
|
||||
vclk <=
|
||||
~(~sysclk // one-shot divide by 8 (1MHz)
|
||||
| q1
|
||||
| ~pclk
|
||||
| ~qx
|
||||
| ~q2);
|
||||
q1 <=
|
||||
~(~pclk & q1
|
||||
| pclk & ~q1); // divide `pclk` by 2 (4MHz)
|
||||
// TODO FIXME: Real PALs don't have this extra bit of memory!
|
||||
qx <=
|
||||
~(~q1 & ~pclk & qx // divide by 4 (2MHz)
|
||||
| ~qx & q1
|
||||
| ~qx & pclk);
|
||||
q2 <=
|
||||
~(~q1 & pclk & q2 // divide by 4 (2MHz)
|
||||
~(~q1 & ~pclk & qx & q2 // divide by 8 (1MHz)
|
||||
| ~q2 & q1
|
||||
| ~q2 & ~pclk);
|
||||
| ~q2 & pclk
|
||||
| ~q2 & ~qx);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
@ -131,6 +146,9 @@ module lag(simclk, n_res,
|
||||
snddma <= 1; reslin <= 1; resnyb <= 1;
|
||||
end
|
||||
|
||||
// TODO FIXME: After converting to one-shot vclk, we have a few
|
||||
// glitches still to fix up.
|
||||
|
||||
// Simulate registered logic.
|
||||
always @(posedge sysclk) begin
|
||||
if (n_res) begin
|
||||
@ -232,6 +250,11 @@ the whole interplay works in detail.
|
||||
regular visible area sweep before we de-assert *HSYNC, so actually
|
||||
we won't be drawing these pixels during horizontal blanking.
|
||||
|
||||
Nevertheless, if you do need a signal that covers the whole active
|
||||
pixel period, you can logically OR together *HSYNC and VIAPB6.
|
||||
Make sure that you use buffering between the VIA and VIAPB6 to
|
||||
prevent the CPU from driving the CRT haywire.
|
||||
|
||||
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
|
||||
@ -393,21 +416,22 @@ module tsg(simclk, n_res,
|
||||
// Simulate registered logic.
|
||||
always @(posedge sysclk) begin
|
||||
if (n_res) begin
|
||||
// TODO VERIFY: q6 missing?
|
||||
q6 <= ~(0);
|
||||
q6 <= ~(~q3); // delayed copy of 1MHz q3 signal
|
||||
clkscc <=
|
||||
~(clkscc & ~pclk & ~q4
|
||||
| clkscc & ~pclk & ~q3
|
||||
| clkscc & ~pclk & vclk
|
||||
| ~clkscc & pclk
|
||||
| ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
|
||||
~(clkscc & pclk & ~q4
|
||||
| clkscc & pclk & ~q6
|
||||
| clkscc & pclk & q3
|
||||
| ~clkscc & ~pclk
|
||||
| ~clkscc & q4 & q6 & ~q3); // skip one inversion every 32 cycles
|
||||
viacb1 <= ~(~keyclk); // buffer the keyboard clock
|
||||
pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz)
|
||||
q3 <= ~(~vclk); // `sysclk` / 16
|
||||
q3 <=
|
||||
~(~q3 & ~vclk
|
||||
| vclk & q3); // `sysclk` / 16
|
||||
q4 <=
|
||||
~(q4 & q3 & ~vclk // `sysclk` / 32
|
||||
| ~q4 & ~q3 // } J for generating CLKSCC
|
||||
| ~q4 & vclk);
|
||||
~(q4 & q6 & ~q3 // `sysclk` / 32
|
||||
| ~q4 & ~q6 // } J for generating CLKSCC
|
||||
| ~q4 & q3);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
@ -431,7 +455,7 @@ module asg(simclk, n_res,
|
||||
// We must implement RESET for simulation or else this will never
|
||||
// stabilize.
|
||||
always @(negedge n_res) begin
|
||||
n_dmald <= 1;
|
||||
n_dmald <= 1; pwm <= 1;
|
||||
r5 <= 1; r4 <= 1; r3 <= 1; r2 <= 1; r1 <= 1; r0 <= 1;
|
||||
end
|
||||
|
||||
@ -450,14 +474,52 @@ module asg(simclk, n_res,
|
||||
// N.B.: This expansion almost exceeds the term limit of the
|
||||
// PAL.
|
||||
|
||||
// * Load value on *DMALD.
|
||||
|
||||
// * If value is zero, set exit condition immediately.
|
||||
// Otherwise, set "not exit" condition. This way we can
|
||||
// load 0x20 and not immediately quit.
|
||||
|
||||
// * Regular loop, shift and check for exit condition on
|
||||
// shifted condition. Okay, that's a bit ugly, but fine.
|
||||
// It would be simpler to check for exit condition on
|
||||
// stored value.
|
||||
|
||||
// ((a) ? ((b) ? d : e) : c);
|
||||
// (a & ((b & c) | (~b & d))) | (~a & c);
|
||||
// r0 <=
|
||||
// ~(~a & ~c
|
||||
// | ~a & ~c & b
|
||||
// | ~a & ~c & ~e
|
||||
// | ~b & a & ~e
|
||||
// | ~b & a & ~e & ~c
|
||||
// | ~b & ~c & ~a & ~c
|
||||
// | ~b & ~c & ~e & a
|
||||
// | ~b & ~c & ~e & ~c
|
||||
// | ~d & a & b
|
||||
// | ~d & a & b & ~c
|
||||
// | ~d & a & ~e
|
||||
// | ~d & a & ~e & ~c
|
||||
// | ~d & ~c & ~a
|
||||
// | ~d & ~c & b & a
|
||||
// | ~d & ~c & b
|
||||
// | ~d & ~c & ~e & a
|
||||
// | ~d & ~c & ~e & ~c);
|
||||
|
||||
r0 <= (~n_dmald) ? rdq0 : ((pwm & vclk) ? r1 : r0);
|
||||
|
||||
// TODO FIXME: Not in PAL equation format.
|
||||
r0 <= n_dmald & (r0 ^ ~pwm);
|
||||
r1 <= n_dmald & (r1 ^ (r0 & ~pwm));
|
||||
r2 <= n_dmald & (r2 ^ (r1 & r0 & ~pwm));
|
||||
r3 <= n_dmald & (r3 ^ (r2 & r1 & r0 & ~pwm));
|
||||
r4 <= n_dmald & (r4 ^ (r3 & r2 & r1 & r0 & ~pwm));
|
||||
r5 <= n_dmald & (r5 ^ (r4 & r3 & r2 & r1 & r0 & ~pwm));
|
||||
pwm <= n_dmald & r5 & r4 & r3 & r2 & r1 & r0;
|
||||
r0 <= (~n_dmald) ? rdq0 : ((pwm & vclk) ? r1 : r0);
|
||||
r1 <= (~n_dmald) ? rdq1 : ((pwm & vclk) ? r2 : r1);
|
||||
r2 <= (~n_dmald) ? rdq2 : ((pwm & vclk) ? r3 : r2);
|
||||
r3 <= (~n_dmald) ? rdq3 : ((pwm & vclk) ? r4 : r3);
|
||||
r4 <= (~n_dmald) ? rdq4 : ((pwm & vclk) ? r5 : r4);
|
||||
r5 <= (~n_dmald) ? rdq5 : ((pwm & vclk) ? (r0 ^ r1) : r5);
|
||||
pwm <= (~n_dmald)
|
||||
? ((~rdq5 & ~rdq4 & ~rdq3 & ~rdq2 & ~rdq1 & ~rdq0) ? 0 : 1)
|
||||
: ((pwm & vclk)
|
||||
? (((r0 ^ r1) & ~r5 & ~r4 & ~r3 & ~r2 & ~r1) ? 0 : 1)
|
||||
: pwm);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
@ -109,10 +109,10 @@ module test_mac128pal();
|
||||
|
||||
// Set simulation time limit.
|
||||
initial begin
|
||||
// #1920000 $finish;
|
||||
#1920000 $finish;
|
||||
// PLEASE NOTE: We must simulate LOTS of cycles in order to see
|
||||
// what the oscilloscope trace for one video frame looks like.
|
||||
#30720000 $finish;
|
||||
// #30720000 $finish;
|
||||
end
|
||||
|
||||
// We can use `$display()` for printf-style messages and implement
|
||||
|
Loading…
x
Reference in New Issue
Block a user