Commit work-in-progress.

Much better BBU pinout chart, lots of notes learned from Guide to the
Macintosh family hardware.
This commit is contained in:
Andrew Makousky 2020-11-18 10:21:05 -06:00
parent 12eb917c24
commit 62d2e920e7
3 changed files with 513 additions and 431 deletions

View File

@ -48,7 +48,7 @@ a huge number of pins, its purpose can be summarized as follows.
* 0x000000 - 0x3fffff: RAM/ROM (switches based on overlay) * 0x000000 - 0x3fffff: RAM/ROM (switches based on overlay)
* 0x400000 - 0x4fffff: ROM * 0x400000 - 0x4fffff: ROM
* 0x580000 - 0x5fffff: 5380 NCR/Symbios SCSI peripherals chip * 0x580000 - 0x5fffff: 5380 NCR/Symbios SCSI peripherals chip
* 0x600000 - 0x6fffff: RAM, boot-time overlay only * 0x600000 - 0x7fffff: RAM, boot-time overlay only
* 0x900000 - 0x9fffff: Zilog 8530 SCC (Serial Control Chip) Read * 0x900000 - 0x9fffff: Zilog 8530 SCC (Serial Control Chip) Read
* 0xb00000 - 0xbfffff: Zilog 8530 SCC (Serial Control Chip) Write * 0xb00000 - 0xbfffff: Zilog 8530 SCC (Serial Control Chip) Write
* 0xd00000 - 0xdfffff: IWM (Integrated Woz Machine; floppy) * 0xd00000 - 0xdfffff: IWM (Integrated Woz Machine; floppy)
@ -298,6 +298,12 @@ Peripheral device signals, input or output?
---------- ----------
Please note: Information on how the older compact Macintosh PAL gates
worked, which provide nearly identical functionality of the BBU.
20201116/http://www.retro.co.za/ccc/mac/ReverseEngineering/PALs.html
20201116/https://web.archive.org/web/20170726142931/http://www.mactech.com/articles/mactech/Vol.01/01.11/PAL/index.html
There is still more to learn/investigate relating to unspecified There is still more to learn/investigate relating to unspecified
signals. signals.

View File

@ -118,102 +118,13 @@
TODO Abbreviations legend, here since they are not noted elsewhere: TODO Abbreviations legend, here since they are not noted elsewhere:
RA = RAM Address
RDQ = RAM Data Value RDQ = RAM Data Value
PMCYC = Processor Memory Cycle PMCYC = Processor Memory Cycle
PINOUT: Undocumented signal but assumed to exist:
RA0 79 64KRAM: Here we assign it to pin 21 for our own experimentation, a
RA1 78 pin that is specified as just tied to ground.
RA2 76
RA3 73
RA4 71
RA5 70
RA6 68
RA8 67
RA7 66
RA9 65
*CAS1L 16
*CAS0L 15
RAM R/*W 14
*RAS 20
*CAS1H 19
*CAS0H 18
RDQ0 69
RDQ1 72
RDQ2 74
RDQ3 75
RDQ4 77
RDQ5 80
RDQ6 83
RDQ7 2
RDQ8 3
RDQ9 4
RDQ10 5
RDQ11 6
RDQ12 7
RDQ13 8
RDQ14 9
RDQ15 10
*EN245 12
*DTACK 38
R/*W 47
*IPL1 30
*LDS 33
*VPA 36
*C8M 37
VCC 22
VCC 64
VCC 42
VCC 84
MBRAM 17
GND 1
GND 21
GND 43
GND 63
ROW2 13
*EXTDTK 11
A23 23
A22 24
A21 25
A20 26
A19 27
A17 28
A9 29
*PMCYC 81
C2M 82
*RES 59
C16MRSF2 44
C3.7M 40
*ROMEN 39
*SCCRD 46
PWM 49
SCSIDRQ 55
*IWM 48
*SCCEN 45
*SCSI 57
*DACK 56
SNDRES 50
VIA.CS1 58
VIDPG2 53
*EAREN 52
*AS 41
*BERR 34
SND 51
*VSYNC 61
*IOW 54
*HSYNC 60
*VIAIRQ 32
VIDOUT 62
*IPL0 31
*UDS 35
Undocumented but assumed to exist:
64KRAM ???
Note that *IOW controls both *SCSI.IOW and *SCC.WR.
*/ */
module bbu_master_ctrl module bbu_master_ctrl
// Essential sequential logic RESET and clock signals // Essential sequential logic RESET and clock signals
@ -250,21 +161,17 @@ module bbu_master_ctrl
n_extdtk, n_earen, n_extdtk, n_earen,
); );
// TODO FIXME: Signals missing-in-action: OVERLAY, SNDPG2. It's // The Macintosh SE deprecated SNDPG2. Nevertheless... for the
// possible that the Macintosh SE uses a magic address access to // sake of possibly making quasi-hardware replicas of earlier
// obviate the need for consuming a VIA pin for OVERLAY, but I have // Macintosh computers easier, we will preserve an implementation
// no idea what this address would be. Has support for the second // here anyways. As for the OVERLAY signal, we'll have to use Mini
// sound page been dropped in the Macintosh SE? Yes, indeed it has // vMac's guess on how to implement it. At boot, the ROM
// been. Nevertheless... for the sake of possibly making // exclusively accesses the ROM overlay addresses and the remapped
// quasi-hardware replicas of earlier Macintosh computers easier, // RAM address when setting up. When it is done, it jumps into the
// we will preserve an implementation here anyways. As for the // standard ROM address access. As soon as the BBU detects this
// OVERLAY signal, we'll have to use Mini vMac's guess on how to // memory access (any address in the standard ROM address space),
// implement it. At boot, the ROM exclusively accesses the ROM // it switches the overlay, and it cannot be switched back except
// overlay addresses and the remapped RAM address when setting up. // by a RESET signal.
// When it is done, it jumps into the standard ROM address access.
// As soon as the BBU detects this memory access (any address in
// the standard ROM address space), it switches the overlay, and it
// cannot be switched back except by a RESET signal.
// So yes... it turns out the BBU must actually do address bus // So yes... it turns out the BBU must actually do address bus
// snooping. // snooping.
@ -272,9 +179,9 @@ module bbu_master_ctrl
// Essential sequential logic RESET and clock signals // Essential sequential logic RESET and clock signals
input wire n_res; // *RESET signal input wire n_res; // *RESET signal
input wire c16m; // 15.667200 MHz master clock input input wire c16m; // 15.667200 MHz master clock input
output reg c8m; // 7.8336 MHz clock output output wire c8m; // 7.8336 MHz clock output
output reg c3_7m; // 3.672 MHz clock output output wire c3_7m; // 3.672 MHz clock output
output reg c2m; // 1.9584 MHz clock output output wire c2m; // 1.9584 MHz clock output
// RAM configuration pins // RAM configuration pins
input wire row2; // 1/2 rows of RAM SIMMs jumper input wire row2; // 1/2 rows of RAM SIMMs jumper
@ -284,40 +191,42 @@ module bbu_master_ctrl
// MC68000 signals // MC68000 signals
input wire a9, a17, a19, a20, a21, a22, a23; input wire a9, a17, a19, a20, a21, a22, a23;
input wire r_n_w, n_as, n_uds, n_lds; input wire r_n_w, n_as, n_uds, n_lds;
output reg n_dtack, n_ipl0, n_ipl1; inout wire n_dtack;
output wire n_ipl0;
input wire n_ipl1;
output wire n_berr; output wire n_berr;
input wire n_vpa; input wire n_vpa;
// DRAM signals // DRAM signals
inout wire ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra8; inout wire ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra8;
output reg ra7, ra9; output wire ra7, ra9;
output reg n_cas1l, n_cas0l, ram_r_n_w, n_ras, n_cas1h, n_cas0h; output wire n_cas1l, n_cas0l, ram_r_n_w, n_ras, n_cas1h, n_cas0h;
inout wire rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, rdq6, rdq7, inout wire rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, rdq6, rdq7,
rdq8, rdq9, rdq10, rdq11, rdq12, rdq13, rdq14, rdq15; rdq8, rdq9, rdq10, rdq11, rdq12, rdq13, rdq14, rdq15;
output reg n_en245, n_pmcyc; output wire n_en245, n_pmcyc;
// ROM and memory overlay signals // ROM and memory overlay signals
output reg n_romen; output wire n_romen;
// VIA signals // VIA signals
output reg via_cs1; output wire via_cs1;
input wire n_viairq; input wire n_viairq;
// Video signals // Video signals
input wire vidpg2; // VIDPG2 signal input wire vidpg2; // VIDPG2 signal
output reg vidout; // VIDOUT signal output wire vidout; // VIDOUT signal
output reg n_hsync; // *HSYNC signal output wire n_hsync; // *HSYNC signal
output reg n_vsync; // *VSYNC signal output wire n_vsync; // *VSYNC signal
// Sound and disk speed signals // Sound and disk speed signals
input wire sndres; input wire sndres;
output reg snd, pwm; output wire snd, pwm;
// IWM signals // IWM signals
output reg n_iwm; output wire n_iwm;
// SCC signals // SCC signals
output reg n_sccen, n_sccrd, n_iow; output wire n_sccen, n_sccrd, n_iow;
// SCSI signals // SCSI signals
output reg n_scsi; output wire n_scsi;
input wire scsidrq; input wire scsidrq;
output reg n_dack; output reg n_dack;
// PDS signals // PDS signals
@ -326,8 +235,6 @@ module bbu_master_ctrl
// Note tristate inout ... 'bz for high impedance. 8'bz for wide. // Note tristate inout ... 'bz for high impedance. 8'bz for wide.
// Boot-time memory overlay switch, 1 = enable, 0 = disable.
reg boot_overlay;
// In order to implement the memory overlay switch, we must snoop // In order to implement the memory overlay switch, we must snoop
// the address bus. These are the registers we use to store the // the address bus. These are the registers we use to store the
// address multiplexor outputs. // address multiplexor outputs.
@ -336,115 +243,51 @@ module bbu_master_ctrl
// Installed RAM size. // Installed RAM size.
wire [23:0] ramsz; wire [23:0] ramsz;
// C16M pixel clock (0.064 us per pixel).
// 512 horizontal draw pixels, 192 horizontal blanking pixels.
// 342 scan lines, 28 scan lines vertical blanking.
// 60.15 Hz vertical scan rate.
// (512 + 192) * (342 + 28) = 260480 pixel clock ticks per frame.
// Total screen buffer size = 10944 words. High-order bit of each
// 16-bit word is the leftmost pixel, low-order bit is the
// rightmost pixel. Words in ascending order move from left to
// right in the scan line, first scan line is topmost and then
// moves downward.
// *HSYNC and *VSYNC counters are negative during blanking.
reg [15:0] vidout_sreg; // VIDOUT shift register
reg [4:0] vidout_cntr; // VIDOUT remaining counter
reg [9:0] vid_hsync_cntr; // *HSYNC counter
reg [8:0] vid_vsync_cntr; // *VSYNC counter
wire [23:0] vid_main_addr; // Address of main video buffer
wire [23:0] vid_alt_addr; // Address of alternate video buffer
// Sound and disk speed buffers are scanned 370 words per video
// frame, and the size of both buffers together is 370 words. Or,
// 260480 pixel clock ticks / 370 = 704 pixel clock ticks per word.
// In a single scan line, (512 + 192) / 704 = 704 / 704 = exactly 1
// word is read. The sound byte is the most significant byte, the
// disk speed byte is the least significant byte. Both the sound
// sample and disk speed represent a PCM amplitude value, this is
// used to generate a PDM waveform that can be processed by a
// low-pass filter to generate the analog signal.
// Well, at least in concept... Inside Macintosh claims that only a
// single pulse is generated, so this is not quite your typical PDM
// audio circuit. Nevertheless, the sample rate is 22.2555 kHz, so
// it's not too bad overall for generating lo-fi audio. But, good
// point to ponder, this is an area of improvement where a
// different algorithm can generate better audio quality.
reg [15:0] snddsk_reg; // PCM sound sample and disk speed register
wire [23:0] snddsk_main_addr; // Address of main sound/disk buffer
wire [23:0] snddsk_alt_addr; // Address of alternate sound/disk buffer
// We must be careful that the sound circuitry does not attempt to
// access RAM at the same time as the video circuitry. Because the
// phases are coherent, we can simply align the sound and disk
// speed RAM fetch to be at a constant offset relative to the video
// RAM fetch.
// PLEASE NOTE: We must carefully time our RAM accesses since they
// have delays and we don't want the screen bits shift register
// buffer to run empty before we have the next word available from
// RAM. Our ideal is that the next word is available from RAM just
// as we are shifting out the last pixel, so that we can use a
// non-blocking assign and the new first pixel will be available
// right at the start of the next pixel clock cycle. Otherwise,
// less ideal but easier to program would be to use two 16-bit
// buffers as a FIFO.
// SCC access notes: Even byte accesses are a read, odd byte
// accesses are a write. Namely: `*LDS` == 0 == write, `*UDS` == 0
// == read. Remember, it's big endian. What about the separate
// address regions? Well, I say just ignore those, it's there for
// a convenient convention, but it's not the officially documented
// hardware protocol.
// VIA support: Simply handle chip select, and issue an MC68000
// interrupt priority zero if we receive an interrupt signal from
// the VIA.
// SCSI support: Handle chip select, and handle DMA. // SCSI support: Handle chip select, and handle DMA.
// NOTE: For all peripherals, we must set `*DTACK` from the BBU // Important! How to handle SCSI DMA... according to Guide to the
// upon successful access condition and time durations because it // Macintosh family hardware, page 126, this is "pseudo-DMA" mode.
// is not set by the device itself. // The BBU does not assert `*DTACK` until `SCSIDRQ` is received to
// indicate the DMA transfer is complete. And again, noting from
// page 126, . Likewise, `*DTACK` is asserted for all addresses in
// range, even if nothing is mapped. No stringent bus error
// control here, that's a hobbyist extension. And again, inded
// `*DTACK` is tri-stated according to the manual when `*EXTDTK`
// (`*EXT.DTACK`) is asserted.
// Now, here's the golden rule: "If any access has not terminated
// within 265 ms, the BBU asserts the bus error signal /BERR."
// There you go, that's how it is driven. So, another thing,
// yes... there must be at least a nominal delay to assert `*DTACK`
// to allow PDS cards to intervene by asserting `*EXTDTK` first.
// TODO MOVE DOCUMENTATION: PLEASE NOTE, PDS cards can also access
// DRAM, not just the CPU. This is mainly a matter of bus
// arbitration, then as far s the BBU is concerned, PDS access to
// DRAM should appear identical to CPU access to DRAM. Guide to
// the Macintosh Family hardware, page 84.
////////////////////////////////////////////////// //////////////////////////////////////////////////
// Pure combinatorial logic is defined first. // Pure combinatorial logic is defined first.
// TODO: Assert `*IPL0` if we receive an interrupt signal from the
// VIA or SCSI. However, do not assert `*IPL0` if the SCC asserts
// `*IPL1`. Guide to the Macintosh family hardware, page 113.
// SCSI interrupts are signaled only on IRQ from the SCSI
// controller. DRQ is not attached to MC68000 interrupt lines
// whatsoever, it must be polled by software and is only used by
// the BBU as specified in the other section. TODO CONFIRM: The
// SCSI IRQ line attaches directly to `*IPL0`?
assign n_ipl0 = ~n_ipl1 | n_viairq;
////////////////////////////////////////////////// //////////////////////////////////////////////////
// Sub-modules are instantiated here. // Sub-modules are instantiated here.
// The remainder of definitions are for sequential logic. // The remainder of definitions are for sequential logic.
always @(negedge n_res) begin always @(negedge n_res) begin
// Initialize all output registers on RESET. // Initialize all output registers on RESET.
n_dack <= 1;
n_dtack <= 1; n_ipl0 <= 1; n_ipl1 <= 1;
ra7 <= 0; ra9 <= 0;
n_cas1l <= 1; n_cas0l <= 1;
ram_r_n_w <= 0; n_ras <= 1;
n_cas1h <= 1; n_cas0h <= 1;
n_en245 <= 1;
n_pmcyc <= 1;
vidout <= 0; n_hsync <= 1; n_vsync <= 1;
snd <= 0; pwm <= 0;
n_iwm <= 1; n_sccen <= 1; n_sccrd <= 1; n_iow <= 1;
n_scsi <= 1; n_dack <= 1;
n_earen <= 1; n_earen <= 1;
// Initialize all internal registers on RESET.
boot_overlay <= 1;
vidout_sreg <= 0;
vidout_cntr <= 0;
vid_hsync_cntr <= 0;
vid_vsync_cntr <= 0;
snddsk_reg <= 0;
end end
always @(posedge c16m) begin always @(posedge c16m) begin
@ -541,88 +384,113 @@ Write down all my questions thus far about the BBU:
// Clock divider module. Generate the frequency-divided clock // Clock divider module. Generate the frequency-divided clock
// signals. // signals.
module clock_div (n_res, c16m, c8m, c3_7m, c2m, n_pmcyc); module clock_div (n_res, c16m, c8m, c3_7m, c2m_e, n_pmcyc, pmcyc_pt);
input wire n_res; input wire n_res;
input wire c16m; input wire c16m;
output reg c8m; output reg c8m;
output reg c3_7m; output reg c3_7m;
// c2m is now controlled by the DRAM controller state machine. // c2m is now controlled by the DRAM controller state machine.
input wire c2m; // This is just an I/O argument placeholder. We still generate the
output reg n_pmcyc; // signal internally, though.
input wire c2m_e;
output wire n_pmcyc;
// *PMCYC "pre-trigger": will the *PMCYC state be negated on the
// next cycle?
output wire pmcyc_pt;
// TODO FIXME: `*PMCYC` should not be a strict 1MHz clock, because
// during vertical blanking, all cycles (except for horizontal
// blanking sound cycles) are fair game for CPU use. PLEASE NOTE:
// According to Guide to the Macintosh family hardware, page 194,
// the process of scanning the screen buffer also refreshes the
// DRAM. But I don't quite understand how this works, wouldn't you
// need to access more addresses to refresh all the DRAM? But,
// PLEASE NOTE. Macintosh SE/30 takes one access cycle every
// 15.6us for DRAM refresh.
/////////////////////////////////////////////////////////// /* Inside Macintosh claims that the serial clock is 3.672 MHz.
// 15.6672 / 3.6720 = 9792/2295 = (51*2^6*3)/(51*3^2*5) Clock multiplication (via PLL) and division can be used to
// = (2^6)/(3*5) = 64/15 generate this from the 15.6672 MHz clock as follows:
// So, here's how we implement the frequency divider to generate 15.6672 / 3.6720 = 9792/2295 = (51*2^6*3)/(51*3^2*5)
// the 3.672 MHz clock. Initialize to 64 - 15 = 49, and keep = (2^6)/(3*5) = 64/15
// subtracting 15 until we reach zero or less. Then, add back 49,
// and toggle the C3.7M output.
// TODO FIXME: The complex frequency divider will not work This would entail a PLL clock running at 235.008 MHz inside the
// correctly: Since the base frequency is not high enough, there BBU, which was impractical for the technology available during
// will be terrible aliasing artifacts. Divide by 4 is a bit too the 1980s. But if that were configured, a simple divide-by-64
// fast, divide by 5 is a bit too slow, but that's the best we can frequency counter would yield a perfect clock signal.
// do without PLL clock frequency multiplication.
//
// PLL clock frequency synthesis inside the BBU is conceivable to
// believe, however, considering that the the GLUE chip in the
// Macintosh SE/30 doubles the 16 MHz crystal input to 32 MHz.
// Easiest method, we want the least common multiple between these
// two frequencies. So, back to where we started.
//
// 15.6672 / 3.6720 = 16/16 * 9792/2295 = (51*2^10*3)/(51*2^4*3^2*5)
// LCM: 51*2^10*3^2*5 = 2350080 -> 235.0080 MHz
// 235.0080 / 15.6672 = 15
// 235.0080 / 3.6720 = 64
//
// So, this is how we synthesize the perfect 3.6720 MHz clock
// signal. Multiply the source frequency of 15.6672 MHz by 15 via
// a PLL to get an intermediate clock frequency of 235.0080 MHz,
// then divide by 64 to get the target 3.6720 MHz clock signal.
// Yes, we could really just use divide-by-four (3.9168 MHz) if
// going a tad bit faster wasn't an issue.
//
// How about this, 16 / (64 * 16/15) ~= 16/68. Multiply by 16,
// divide by 68. PLL = 250.6752 MHz, result = 3.6864 MHz. I guess
// that's a lot better. Alternatively, PLL = 250 MHz, result =
// 3.6765 MHz. Even better.
// TODO: Optimize this to minimize the number of register bits As it turns out, the actual Macintosh did not use a true,
// required, while still preserving ideal frequency division and constant-period 15.6672 MHz clock, but rather a 3.686 MHz clock
// synchronization behavior. with a phase/period error of up to 1 clock cycle of the 15.6672
MHz clock. Sequential logic is used to effect a principal
divide-by-four clock cycle format, and at every fourth 3.686 MHz
clock cycle, one extra 15.6672 MHz clock cycle is slipped in on
the last low-edge half-period of the 3.686 MHz clock. Over a
long period of time, this effects an average frequency division
factor of 4.25.
And yes, even with that introduced phase/period error, the
downstream hardware apparently still works just fine, thanks to
the divide-by-16 in front of the SCC's internal baud rate
generator. This gives you a max baud of 230 kbits/sec, with a
phase/period error of 1/(16*16) = 0.39%.
*/
// TODO EVALUATE: Optimize this to minimize the number of register
// bits required, while still preserving ideal frequency division
// and synchronization behavior. Maybe not... less registers
// entails more combinatorial logic delay.
// We use shift registers or 1-bit inverters for high performance, // We use shift registers or 1-bit inverters for high performance,
// minimal cycle overhead. // minimal cycle overhead.
reg [5:0] c16m_div4_cntr; // Complex C16M -> C3_7M divider counter reg c16m_div4_cntr; // C16M / 4 counter
// reg [3:0] c16m_div8_cntr; // C16M / 8 counter // Complex C16M -> C3_7M divider counter, principal divide-by-4
reg c16m_div4_0_cntr;
// Complex C16M -> C3_7M divider counter, counter for slipping in
// extra cycle
reg [16:0] c16m_div4_25_cntr;
reg [3:0] c16m_div8_cntr; // C16M / 8 counter
reg [7:0] c16m_div16_cntr; // C16M / 16 counter reg [7:0] c16m_div16_cntr; // C16M / 16 counter
reg c4m;
reg c2m;
reg c1m;
assign pmcyc_pt = c16m_div16_cntr[7];
// assign c2m_e = c2m;
assign n_pmcyc = c1m;
always @(negedge n_res) begin always @(negedge n_res) begin
// Initialize all output registers on RESET. // Initialize all output registers on RESET.
c8m <= 0; c8m <= 0;
c4m <= 0;
c3_7m <= 0; c3_7m <= 0;
// c2m <= 0; c2m <= 0;
n_pmcyc <= 1; c1m <= 0;
// Initialize all internal registers on RESET. // Initialize all internal registers on RESET.
c16m_div4_cntr <= 1; c16m_div4_cntr <= 0;
// c16m_div8_cntr <= 1; c16m_div4_0_cntr <= 0;
c16m_div4_25_cntr <= 1;
c16m_div8_cntr <= 1;
c16m_div16_cntr <= 1; c16m_div16_cntr <= 1;
end end
always @(posedge c16m) begin always @(posedge c16m) begin
if (n_res) begin if (n_res) begin
c8m <= ~c8m; c8m <= ~c8m;
if (c16m_div4_cntr[1]) begin if (c16m_div4_cntr) c4m <= ~c4m;
c3_7m <= ~c3_7m; c16m_div4_cntr <= ~c16m_div4_cntr;
c16m_div4_cntr <= 1; if (~c16m_div4_25_cntr[16]) begin
if (c16m_div4_0_cntr) c3_7m <= ~c3_7m;
c16m_div4_0_cntr <= ~c16m_div4_0_cntr;
end end
else // else Slip in the extra cycle by not incrementing the
c16m_div4_cntr <= { c16m_div4_cntr[4:0], c16m_div4_cntr[5] }; // principal divide-by-4 counter.
// if (c16m_div8_cntr[3]) c2m <= ~c2m; c16m_div4_25_cntr <= { c16m_div4_25_cntr[15:0],
// c16m_div8_cntr <= { c16m_div8_cntr[2:0], c16m_div8_cntr[3] }; c16m_div4_25_cntr[16] };
if (c16m_div16_cntr[7]) n_pmcyc <= ~n_pmcyc; if (c16m_div8_cntr[3]) c2m <= ~c2m;
c16m_div8_cntr <= { c16m_div8_cntr[2:0], c16m_div8_cntr[3] };
if (c16m_div16_cntr[7]) c1m <= ~c1m;
c16m_div16_cntr <= { c16m_div16_cntr[6:0], c16m_div16_cntr[7] }; c16m_div16_cntr <= { c16m_div16_cntr[6:0], c16m_div16_cntr[7] };
end end
end end
@ -784,7 +652,7 @@ endmodule
* 0x000000 - 0x3fffff: RAM/ROM (switches based on overlay) * 0x000000 - 0x3fffff: RAM/ROM (switches based on overlay)
* 0x400000 - 0x4fffff: ROM * 0x400000 - 0x4fffff: ROM
* 0x580000 - 0x5fffff: 5380 NCR/Symbios SCSI peripherals chip * 0x580000 - 0x5fffff: 5380 NCR/Symbios SCSI peripherals chip
* 0x600000 - 0x6fffff: RAM, boot-time overlay only * 0x600000 - 0x7fffff: RAM, boot-time overlay only
* 0x900000 - 0x9fffff: Zilog 8530 SCC (Serial Control Chip) Read * 0x900000 - 0x9fffff: Zilog 8530 SCC (Serial Control Chip) Read
* 0xb00000 - 0xbfffff: Zilog 8530 SCC (Serial Control Chip) Write * 0xb00000 - 0xbfffff: Zilog 8530 SCC (Serial Control Chip) Write
* 0xd00000 - 0xdfffff: IWM (Integrated Woz Machine; floppy) * 0xd00000 - 0xdfffff: IWM (Integrated Woz Machine; floppy)
@ -792,58 +660,143 @@ endmodule
* 0xf00000 - 0xffffef: ??? (the ROM appears to be accessing here) * 0xf00000 - 0xffffef: ??? (the ROM appears to be accessing here)
* 0xfffff0 - 0xffffff: Auto Vector * 0xfffff0 - 0xffffff: Auto Vector
This address map has also been confirmed with Guide to the
Macintosh family hardware, page 127. PLEASE NOTE: In SCC Read
zone, if A0 == 1, then that is an SCC RESET. IWM must be A0 == 1,
VIA must be A0 == 0, SCC write must be A0 == 1. SCSI read A0 == 0,
SCSI write A0 == 1.
SCC access notes: In the Macintosh Plus and older, even byte
accesses are a read, odd byte accesses are a write. Namely: `*LDS`
== 0 == write, `*UDS` == 0 == read. Remember, it's big endian.
What about the separate address regions? Well, I say just ignore
those, it's there for a convenient convention, but it's not the
officially documented hardware protocol.
In the Macintosh SE, this behavior is somewhat changed. Now `*IOW`
controls both `*SCSI.IOW` and `*SCC.WR`, and `*SCCRD` is wired
directly from the BBU to `*SCC.RD`. `*UDS` is used to trigger
`*SCSI.IOR`.
PLEASE NOTE: Guide to the Macintosh family hardware, page 121.
Rather than signaling bus errors for out of range RAM addresses,
overflow accesses should just wrap around and repeat access to the
same RAM.
PLEASE NOTE: Guide to the Macintosh family hardware, page 122. "A
word-wide access to any SCC address causes a phase shift in the
processor clock, and is used by the operating system to correct the
phase when necessary."
"At system startup, the operating system reads an address in the
range $F0 0000 through $F7 FFFF (labeled _Phase read_ in Gifgures
3-1 and 3-2) to determine whether the computer's high-frequency
timing signals are correctly in phase. When the timing signals are
not in phase, RAM accesses are not timed correctly, causing an
unstable video display, RAM errors, and VIA errors." Well, I can
see how that would be happening with just a bunch of PALs, but I
don't think it still needs to be that way when you have the BBU in
charge, you can do better! And indeed, that note only appears to
apply to the Macintosh Plus, not the Macintosh SE, as it is listed
in that section.
TODO FIXME: Guide to the Macintosh family hardware, page 127.
Okay, so this is how to interpret the information about the
boot-time overlay for the alternate RAM location. Only a 2MB zone
is exposed, even though you may have up to 4MB of RAM. So, 2.5MB
and 4MB RAM configurations need to be treated specially. In
particular, only the "upper row" of RAM is accessible greater than
or equal to the address 0x680000. Below that address, you get
access to the first 512K of RAM. Macintosh Plus actually uses the
same overlay map too. That's a defect in MESS/MAME source code but
apparently it's not important, interestingly enough. Okay, I guess
I don't really quite understand, though, sorry. Okay, this means,
the first row, right? "If 2.5 or 4 MB only upper row is
accessible" page 127.
The signal *VPA is asserted in address range 0xe00000 - 0xffffff,
optionally excluding invalid addresses when a bus error signal is
generated. This is for synchronous I/O devices accessed in the old
6800 fashion.
*/ */
module decode_devaddr (n_ramen, n_romen, n_scsi, n_sccen, n_sccrd, module decode_devaddr (n_res, clk, n_ramen, n_romen, n_scsi,
n_iwm, via_cs1, n_berr, a23_19, n_sccen, n_sccrd, n_iow, n_iwm, via_cs1, n_vpa,
boot_overlay, r_n_w, reg_romen, reg_ram_w); n_berr, n_as, a23_19, berr_ram, n_extdtk,
boot_overlay, r_n_w, reg_romen, reg_ram_w,
n_dtack_peri);
input wire n_res;
input wire clk;
output wire n_ramen; output wire n_ramen;
output wire n_romen; output wire n_romen;
output wire n_scsi; output wire n_scsi;
output wire n_sccen; output wire n_sccen;
output wire n_sccrd; output wire n_sccrd;
output wire n_iow;
output wire n_iwm; output wire n_iwm;
output wire via_cs1; output wire via_cs1;
output wire n_vpa;
output wire n_berr; output wire n_berr;
input wire n_as;
input wire [4:0] a23_19; input wire [4:0] a23_19;
input wire berr_ram; // Would this RAM address be a bus error?
input wire n_extdtk;
input wire boot_overlay; input wire boot_overlay;
input wire r_n_w; input wire r_n_w;
// Have we attempted to write to the regular RAM address zone?
output wire reg_ram_w;
// Has an address access to the regular *ROMEN zone occurred? This // Has an address access to the regular *ROMEN zone occurred? This
// signal is used to disable the boot-time memory overlay. // signal is used to disable the boot-time memory overlay.
output wire reg_romen; output wire reg_romen;
// Have we attempted to write to the regular RAM address zone? output wire n_dtack_peri; // *DTACK for peripherals
output wire reg_ram_w;
wire berr_ram; wire reg_ram, reg_ram_r;
wire scsi, sccrd, sccwr;
wire berr_scc;
wire n_dtack_peri_pt; // *DTACK peripherals "pre-trigger"
reg n_dtack_peri_bf; // *DTACK for peripherals buffer
// If the boot-time overlay is enabled but we attempt to write to // If the boot-time overlay is enabled but we attempt to write to
// the regular RAM region, then this is a *RAMEN trigger. The // the regular RAM region, then this is a *RAMEN trigger. The
// overlay control logic will zero the switch on the next cycle, // overlay control logic will zero the switch on the next cycle,
// but we use combinatorial logic here to act immediately. // but we use combinatorial logic here to act immediately.
assign reg_ram_w = (~r_n_w & (a23_19[4:3] == 2'b00)); assign reg_ram = ~n_as & (a23_19[4:3] == 2'b00);
assign n_ramen = ~((boot_overlay) ? (a23_19[4:1] == 4'b0110) : assign reg_ram_r = (r_n_w & reg_ram);
(a23_19[4:3] == 2'b00)) & assign reg_ram_w = (~r_n_w & reg_ram);
~reg_ram_w; assign n_ramen = ~((boot_overlay) ?
assign reg_romen = (a23_19[4:1] == 4'h4); ((~n_as & ((a23_19[4:1] == 4'h6) |
// Only trigger *ROMEN for reads, not writes. (a23_19[4:1] == 4'h7))) | reg_ram_w) :
assign n_romen = ~(reg_romen | reg_ram);
(boot_overlay & r_n_w & (a23_19[4:3] == 2'b00))); assign reg_romen = ~n_as & (a23_19[4:1] == 4'h4);
assign n_scsi = ~(a23_19[4:0] == 5'b01011); // Only trigger *ROMEN for reads, not writes, in overlay zone.
assign n_sccen = ~((a23_19[4:1] == 4'h9) | assign n_romen = ~(reg_romen | (boot_overlay & reg_ram_r));
(a23_19[4:1] == 4'hb)); assign scsi = ~n_as & (a23_19[4:0] == 5'b01011);
assign n_sccrd = ~(a23_19[4:1] == 4'h9); assign n_scsi = ~scsi;
assign n_iwm = ~(a23_19[4:1] == 4'hd); assign sccrd = ~n_as & (a23_19[4:1] == 4'h9);
assign via_cs1 = (a23_19[4:0] == 5'b11101); assign sccwr = ~n_as & (a23_19[4:1] == 4'hb);
// TODO: We don't currently implement Auto Vector, but neither does assign n_sccen = ~(sccrd | sccwr);
// MESS/MAME but its emulation still works just fine? There could assign n_sccrd = ~sccrd;
// be ROM patch hacks... assign n_iow = ~((scsi & ~r_n_w) | sccwr);
assign n_iwm = ~(~n_as & (a23_19[4:1] == 4'hd));
assign via_cs1 = ~n_as & (a23_19[4:0] == 5'b11101);
assign n_vpa = ~(via_cs1 | (~n_as & (a23_19[4:1] == 4'hf)));
// N.B.: According to Guide to the Macintosh family hardware, page
// 126, the implementation of Auto Vector is easy and
// straightforward for the BBU. Just assert `*VPA` in the address
// range. The CPU sets address lines A3 - A1, and this causes the
// CPU to automatically jump to the memory location containing the
// interrupt handler.
// TODO: Signal a bus error for out-of-range RAM addresses. Make // Optionally trigger bus errors if a read is attempted from the
// sure to also signal errors in the boot-time overlay when booting // write-only SCC address space, and vice versa.
// with less than 1 MB of RAM. This would require decoding more assign berr_scc = (sccrd & ~r_n_w) | (sccwr & r_n_w);
// address bits, though.
assign berr_ram = 0;
assign n_berr = ~(berr_ram | // Note that if the PDS card asserts *EXTDTK, we also must not
// drive *BERR. TODO EVALUATE: Should we wait a cycle before
// asserting *BERR to give the PDS card time to respond first?
assign n_berr = n_as | ~n_extdtk |
~((~n_ramen & berr_ram) |
berr_scc |
(a23_19[4:0] == 5'b01010) | (a23_19[4:0] == 5'b01010) |
(a23_19[4:1] == 4'h7) | (a23_19[4:1] == 4'h7) |
(a23_19[4:1] == 4'h8) | (a23_19[4:1] == 4'h8) |
@ -851,21 +804,88 @@ module decode_devaddr (n_ramen, n_romen, n_scsi, n_sccen, n_sccrd,
(a23_19[4:1] == 4'hc) | (a23_19[4:1] == 4'hc) |
(a23_19[4:0] == 5'b11100)); (a23_19[4:0] == 5'b11100));
// TODO: Also flag bus errors for the final address zone. // TODO: Also flag bus errors for the final address zone.
// NOTE: For all peripherals, we must set `*DTACK` from the BBU
// upon successful access condition and time durations because it
// is not set by the device itself. From the time *AS is asserted,
// we simply wait one clock cycle on whatever clock is given to us
// before we trigger *DTACK for the peripheral.
// N.B.: According to Guide to the Macintosh family hardware,
// `*DTACK` is not used to respond to addresses in the range
// 0xe00000 - 0xffffff, only below that. `*VPA` alone is used to
// respond to these addresses. So therefore, we exclude `VIA.CS1`.
assign n_dtack_peri_pt = n_scsi & n_sccen & n_iwm;
// N.B. We use combinatorial logic here to deassert *DTACK for
// peripherals as soon as *AS is released.
assign n_dtack_peri = n_as | n_dtack_peri_bf;
always @(negedge n_res) begin
n_dtack_peri_bf <= 1;
end
always @(posedge clk) begin
if (n_res) begin
if (n_as)
n_dtack_peri_bf <= 1;
else begin
if (n_dtack_peri_pt)
n_dtack_peri_bf <= 0;
else
n_dtack_peri_bf <= 1;
end
end
else
; // Nothing to be done during RESET.
end
endmodule
// Determine if a RAM address is out of range and should therefore
// signal a bus error.
module berr_ram_logic (a0_21, ramsz, /*ramsz_en,*/ berr_ram);
input wire [21:0] a0_21;
input wire [23:0] ramsz;
// input wire [6:0] ramsz_en;
output wire berr_ram;
// We could either use arithmetic comparison (easiest to code in
// Verilog), or bit-wise comparisons (possibly more efficient in
// hardware). We may simply consider implementing this logic in a
// separate module.
// 4MB valid: 0x000000 - 0x3fffff
// 4MB invalid: None!
// 2.5MB valid: 0x000000 - 0x27ffff
// 2.5MB invalid: 0x280000 - 0x3fffff
// 2MB valid: 0x000000 - 0x1fffff
// 2MB invalid: 0x200000 - 0x3fffff
// 1MB valid: 0x000000 - 0x0fffff
// 1MB invalid: 0x100000 - 0x3fffff
// 512K valid: 0x000000 - 0x07ffff
// 512K invalid: 0x080000 - 0x3fffff
// 256K valid: 0x000000 - 0x03ffff
// 256K invalid: 0x040000 - 0x3fffff
// 128K valid: 0x000000 - 0x01ffff
// 128K invalid: 0x020000 - 0x3fffff
// N.B. Verilog comparison is unsigned by default.
assign berr_ram = { 1'b0, a0_21[21:17] } < ramsz[22:17];
endmodule endmodule
// Boot-time memory overlay register and controlling logic. This is // Boot-time memory overlay register and controlling logic. This is
// fairly straightforward to implement once you see all the other // fairly straightforward to implement once you see all the other
// logic of the BBU in place. // logic of the BBU in place.
module overlay_logic (n_res, clk, overlay, reg_romen, reg_ram_w); module overlay_logic (n_res, clk, boot_overlay, reg_romen, reg_ram_w);
input wire n_res; input wire n_res;
input wire clk; input wire clk;
output reg overlay; // Boot-time memory overlay switch, 1 = enable, 0 = disable.
output reg boot_overlay;
input wire reg_romen; input wire reg_romen;
input wire reg_ram_w; input wire reg_ram_w;
always @(negedge n_res) begin always @(negedge n_res) begin
// Initialize the overlay switch to ENABLED on RESET. // Initialize the overlay switch to ENABLED on RESET.
overlay <= 1; boot_overlay <= 1;
end end
always @(posedge clk) begin always @(posedge clk) begin
@ -874,13 +894,12 @@ module overlay_logic (n_res, clk, overlay, reg_romen, reg_ram_w);
// address zone. And, according to MESS/MAME, also disable // address zone. And, according to MESS/MAME, also disable
// on the first attempt to write the regular RAM zone. // on the first attempt to write the regular RAM zone.
if (reg_romen | reg_ram_w) if (reg_romen | reg_ram_w)
overlay <= 0; boot_overlay <= 0;
else else
; // Nothing to be done. ; // Nothing to be done.
end end
end end
endmodule // btm_overlay endmodule
// Column address strobe decode logic. Determine which column access // Column address strobe decode logic. Determine which column access
// strobe line to assert based off of the installed RAM, high-order // strobe line to assert based off of the installed RAM, high-order
@ -1324,39 +1343,96 @@ endmodule
// determine where we are on the screen, which buffer address to fetch // determine where we are on the screen, which buffer address to fetch
// next, and so on. // next, and so on.
module avtimers (); module avtimers ();
input wire n_res;
input wire c16m;
// Video signals
input wire vidpg2; // VIDPG2 signal
output reg vidout; // VIDOUT signal
output reg n_hsync; // *HSYNC signal
output reg n_vsync; // *VSYNC signal
// Sound and disk speed signals
input wire sndres;
output reg snd, pwm;
// C16M pixel clock (0.064 us per pixel).
// 512 horizontal draw pixels, 192 horizontal blanking pixels.
// 342 scan lines, 28 scan lines vertical blanking.
// 60.15 Hz vertical scan rate.
// (512 + 192) * (342 + 28) = 260480 pixel clock ticks per frame.
// Total screen buffer size = 10944 words. High-order bit of each
// 16-bit word is the leftmost pixel, low-order bit is the
// rightmost pixel. Words in ascending order move from left to
// right in the scan line, first scan line is topmost and then
// moves downward.
// *HSYNC and *VSYNC counters are negative during blanking.
reg [15:0] vidout_sreg; // VIDOUT shift register
reg [4:0] vidout_cntr; // VIDOUT remaining counter
reg [9:0] vid_hsync_cntr; // *HSYNC counter
reg [8:0] vid_vsync_cntr; // *VSYNC counter
wire [23:0] vid_main_addr; // Address of main video buffer
wire [23:0] vid_alt_addr; // Address of alternate video buffer
// Sound and disk speed buffers are scanned 370 words per video
// frame, and the size of both buffers together is 370 words. Or,
// 260480 pixel clock ticks / 370 = 704 pixel clock ticks per word.
// In a single scan line, (512 + 192) / 704 = 704 / 704 = exactly 1
// word is read. The sound byte is the most significant byte, the
// disk speed byte is the least significant byte. Both the sound
// sample and disk speed represent a PCM amplitude value, this is
// used to generate a PDM waveform that can be processed by a
// low-pass filter to generate the analog signal.
// Well, at least in concept... Inside Macintosh claims that only a
// single pulse is generated, so this is not quite your typical PDM
// audio circuit. Nevertheless, the sample rate is 22.2555 kHz, so
// it's not too bad overall for generating lo-fi audio. But, good
// point to ponder, this is an area of improvement where a
// different algorithm can generate better audio quality.
reg [15:0] snddsk_reg; // PCM sound sample and disk speed register
wire [23:0] snddsk_main_addr; // Address of main sound/disk buffer
wire [23:0] snddsk_alt_addr; // Address of alternate sound/disk buffer
// We must be careful that the sound circuitry does not attempt to
// access RAM at the same time as the video circuitry. Because the
// phases are coherent, we can simply align the sound and disk
// speed RAM fetch to be at a constant offset relative to the video
// RAM fetch.
// PLEASE NOTE: We must carefully time our RAM accesses since they
// have delays and we don't want the screen bits shift register
// buffer to run empty before we have the next word available from
// RAM. Our ideal is that the next word is available from RAM just
// as we are shifting out the last pixel, so that we can use a
// non-blocking assign and the new first pixel will be available
// right at the start of the next pixel clock cycle. Otherwise,
// less ideal but easier to program would be to use two 16-bit
// buffers as a FIFO.
always @(negedge n_res) begin
// Initialize all output registers on RESET.
vidout <= 0; n_hsync <= 1; n_vsync <= 1;
snd <= 0; pwm <= 0;
// Initialize all internal registers on RESET.
vidout_sreg <= 0;
vidout_cntr <= 0;
vid_hsync_cntr <= 0;
vid_vsync_cntr <= 0;
snddsk_reg <= 0;
end
endmodule endmodule
/* TODO: Summary of what is missing and left to implement: DRAM /* TODO: Summary of what is missing and left to implement: DRAM
initialization pulses, DRAM refresh, video, disk, and audio initialization pulses, DRAM refresh, detect 2.5MB of RAM and
scanout, SCSI DMA, EXTDTK yielding, double-check SCC read/write configure address buffers accordingly, video, disk, and audio
logic. */ scanout, SCSI DMA, EXTDTK yielding, interrupt propagation,
double-check SCC read/write logic. */
/*
TODO: Okay, we really have a plan now to try to make my code modular
and easy to understand. The original probably wasn't too nice since
it was only written by really one person working by themself, but hey,
let's go better a second time around. So, yes, this is the plan. See
that nice, clean, simple DRAM controller main state advancement
module? My goal is to create just a series of modules like that, they
plug together to create the full integrated system. We use
combinatorial logic and rerouting wires as necessary to get the final
intended behavior.
One thing to remember is that we have monopoly control over the output
logic of RA7 and RA9. We never need to yield high-impedance on this.
So we just use combinatorial logic to set this as we please, from
jumpers, internal registers, and the like. Yes, namely the configured
installed RAM mode.
To keep the main DRAM controller simple, we can use combinatorial
logic spelled out separately and `n_cas` as a register to trigger the
proper CAS lines on the individual DRAM SIMMs. This is also where we
handle *LDS and *UDS.
Since we use a module for the DRAM controller main loop, we can use
wires and other modules to feed it whatever state advancement clock we
want. That's really good! That solves a problem I was worrying
about.
*/

View File

@ -1,85 +1,85 @@
BBU Pin,Signal Name,Description,Device Connection,Device Pin Verilog,Signal,Pin,Description,Direction,Device Connection,Device Pin,Device Signal
1,GND,,, ra0,RA0,79,RAM Address bit 0,inout,DRAM SIMMs
2,RD7,,, ra1,RA1,78,RAM Address bit 1,inout,DRAM SIMMs
3,RD8,,, ra2,RA2,76,RAM Address bit 2,inout,DRAM SIMMs
4,RD9,,, ra3,RA3,73,RAM Address bit 3,inout,DRAM SIMMs
5,RD10,,, ra4,RA4,71,RAM Address bit 4,inout,DRAM SIMMs
6,RD11,,, ra5,RA5,70,RAM Address bit 5,inout,DRAM SIMMs
7,RD12,,, ra6,RA6,68,RAM Address bit 6,inout,DRAM SIMMs
8,RD13,,, ra8,RA8,67,RAM Address bit 8,inout,DRAM SIMMs
9,RD14,,, ra7,RA7,66,RAM Address bit 7,output,DRAM SIMMs
10,RD15,,, ra9,RA9,65,RAM Address bit 9,output,DRAM SIMMs
11,EXTPDS,,, n_cas1l,*CAS1L,16,DRAM Column Access Strobe row #2 low-byte SIMM,output,DRAM SIMMs
12,EN245,Select Data Buffer,74LS245, n_cas0l,*CAS0L,15,DRAM Column Access Strobe row #1 low-byte SIMM,output,DRAM SIMMs
13,VCC,,, ram_r_n_w,RAM R/*W,14,DRAM read/write,output,DRAM SIMMs
14,/WR,,, n_ras,*RAS,20,DRAM Row Access Strobe,output,DRAM SIMMs
15,/CAS-SIMM3,,SIMM3,2 n_cas1h,*CAS1H,19,DRAM Column Access Strobe row #2 high-byte SIMM,output,DRAM SIMMs
16,/CAS-SIMM1,,SIMM1,2 n_cas0h,*CAS0H,18,DRAM Column Access Strobe row #1 high-byte SIMM,output,DRAM SIMMs
17,/EOP,,53C80, rdq0,RDQ0,69,RAM Data Value bit 0,inout,DRAM SIMMs
18,/CAS-SIMM4,,SIMM4,2 rdq1,RDQ1,72,RAM Data Value bit 1,inout,DRAM SIMMs
19,/CAS-SIMM2,,SIMM2,2 rdq2,RDQ2,74,RAM Data Value bit 2,inout,DRAM SIMMs
20,/RAS,,, rdq3,RDQ3,75,RAM Data Value bit 3,inout,DRAM SIMMs
21,GND,,, rdq4,RDQ4,77,RAM Data Value bit 4,inout,DRAM SIMMs
22,VCC,,, rdq5,RDQ5,80,RAM Data Value bit 5,inout,DRAM SIMMs
23,A23,,, rdq6,RDQ6,83,RAM Data Value bit 6,inout,DRAM SIMMs
24,A22,,, rdq7,RDQ7,2,RAM Data Value bit 7,inout,DRAM SIMMs
25,A21,,, rdq8,RDQ8,3,RAM Data Value bit 8,inout,DRAM SIMMs
26,A20,,, rdq9,RDQ9,4,RAM Data Value bit 9,inout,DRAM SIMMs
27,A19,,, rdq10,RDQ10,5,RAM Data Value bit 10,inout,DRAM SIMMs
28,A17,,, rdq11,RDQ11,6,RAM Data Value bit 11,inout,DRAM SIMMs
29,A9,,, rdq12,RDQ12,7,RAM Data Value bit 12,inout,DRAM SIMMs
30,/IPL1,,68000, rdq13,RDQ13,8,RAM Data Value bit 13,inout,DRAM SIMMs
31,/IPL0,,68000, rdq14,RDQ14,9,RAM Data Value bit 14,inout,DRAM SIMMs
32,IRQ,,65C22/6523, rdq15,RDQ15,10,RAM Data Value bit 15,inout,DRAM SIMMs
33,/LDS,,68000, n_en245,*EN245,12,Enable LS245 DRAM to CPU data bus switch,output,LS245,19,*EO
34,/BERR,,68000, n_dtack,*DTACK,38,CPU Data Transfer Acknowledge,inout,68000,10,*DTACK
35,/UDS,,, r_n_w,R/*W,47,CPU memory read/write,input,68000,9,R/*W
36,/VPA,,68000, n_ipl1,*IPL1,30,CPU Interrupt Priority Level bit 1,input,68000,24,*IPL1
37,CK,,68000, n_lds,*LDS,33,CPU Lower Data Strobe,input,68000,8,*LDS
38,/DTACK,,68000, n_vpa,*VPA,36,CPU Valid Peripheral Address,output,68000,21,*VPA
39,SELROM,Select ROM,ROM,"20 on ROM HI, LO" c8m,C8M,37,8MHz clock,output,68000,15,CLK
40,"RTxCB, PCLK, ADB CLK",All the things,"85C30, ADB, GLU","20 & 28 on 85C30, 16 on ADB, 9 on GLU" null,VCC,22,+5V power,power
41,/AS,,, null,VCC,64,+5V power,power
42,VCC,,, null,VCC,42,+5V power,power
43,GND,,, null,VCC,84,+5V power,power
44,FCLK,,"SWIM, GLU","24 on SWIM, 19 on GLU" mbram,MBRAM,17,1MB RAM SIMMs jumper,input,Jumper J16
45,SELSCC,Select SCC,85C30,32 on /CE null,GND,1,Ground,power
46,/RD,,85C30, s64kram,64KRAM,21,UNOFFICIAL 64K RAM SIMMs jumper,input
47,R/W,,, null,GND,43,Ground,power
48,SELSWIM,Select SWIM,SWIM,7 on /DEV null,GND,63,Ground,power
49,EXTFLP,PWM,External Floppy,10 on PWM row2,ROW2,13,2 rows of RAM SIMMs jumper,input,Jumper J16
50,PB7,,65C22/6523, n_extdtk,*EXTDTK,11,External PDS will drive *DTACK,input,PDS slot J13,B28,*EXT.DTACK
51,SELSND,Select Sound,SND, a23,A23,23,CPU Address bit 23,input,68000,52,A23
52,EXTPDS,,, a22,A22,24,CPU Address bit 22,input,68000,51,A22
53,PA6,,65C22/6523, a21,A21,25,CPU Address bit 21,input,68000,50,A21
54,/LDS,,, a20,A20,26,CPU Address bit 20,input,68000,48,A20
55,DRQ,,53C80,22 on DRQ a19,A19,27,CPU Address bit 19,input,68000,47,A19
56,/DACK,,53C80,26 on /DACK a17,A17,28,CPU Address bit 17,input,68000,45,A17
57,SELSCSI,Select SCSI,53C80,21 on /CS a9,A9,29,CPU Address bit 9,input,68000,37,A9
58,SELVIA,Select VIA,65C22/6523,24 on RS0 n_pmcyc,*PMCYC,81,Processor Memory CYCle,output,F257,15,*OE
59,/RST,,, c2m,C2M,82,~2MHz DRAM row/column address selector clock,output,F257,1,S
60,HSYNC,Horizontal Sync,J12,Pin 10 on J12 n_res,*RES,59,RESet,input,68000,18,*RES
61,VSYNC,Veritcal Sync,"J12, 65C22/6523","Pin 11 on J12, 40 on DB7" c16m,C16MRSF2,44,Filtered 16MHz clock input,input,GLU,19,FCLK
62,VIDOUT,Composite Video Out,"J12, 65C22/6523","Pin 9 on J12, 28 on PC3" c3_7m,C3.7M,40,~3.7MHz clock,output,"8530, ADB, GLU","20 & 28 on 8530, 16 on ADB, 9 on GLU",RTXCB
63,GND,,, n_romen,*ROMEN,39,ROM ENable,output,ROM,20,*CE
64,VCC,,, n_sccrd,*SCCRD,46,Serial Communications Controller ReaD,output,8530,36,*RD
65,RA9,,, pwm,PWM,49,Pulse Width Modulation floppy disk drive motor speed control,output,External Floppy,10,PWM
66,RA7,,, scsidrq,SCSIDRQ,55,SCSI DMA ReQuest,input,5380,22,DRQ
67,RA8,,, n_iwm,*IWM,48,Integrated Wozniak Machine floppy disk controller chip enable,output,IWM,7,*DEV
68,RA6,,, n_sccen,*SCCEN,45,Serial Communications Controller chip ENable,output,8530,33,*CE
69,RD0,,, n_scsi,*SCSI,57,SCSI chip select,output,5380,21,*CS
70,RA5,,, n_dack,*DACK,56,SCSI DMA ACKnowledge,output,5380,26,*DACK
71,RA4,,, sndres,SNDRES,50,SouND RESet,input,6522,17,PB7 vSndEnb
72,RD1,,, via_cs1,VIA.CS1,58,VIA Chip Select 1,output,6522,24,CS1
73,RA3,,, vidpg2,VIDPG2,53,VIDeo framebuffer PaGe 2,input,6522,8,PA6 vPage2
74,RD2,,, n_earen,*EAREN,52,Unknown reserved PDS input signal,output,PDS slot J13,B11,Reserved
75,RD3,,, n_as,*AS,41,CPU Address Strobe,input,68000,6,*AS
76,RA2,,, n_berr,*BERR,34,CPU Bus ERRor,output,68000,22,*BERR
77,RD4,,, snd,SND,51,PWM SouND output,output,Sound filter circuit
78,RA1,,, n_vsync,*VSYNC,61,Video Vertical Synchronization control,output,Analog board J12,11 on J12 and 40 on 6522,CA1
79,RA0,,, n_iow,*IOW,54,SCSI and Serial Communications Controller I/O Write,output,5380 and 8530,29 on 5380 and 35 on 8530,*IOW on 5380 and *WR on 8530
80,RD5,,, n_hsync,*HSYNC,60,Video Horizontal Synchronization control,output,Analog board J12,10 on J12
81,/PMCYC,,74F257,/OE n_viairq,*VIAIRQ,32,VIA Interrupt ReQuest,input,6522,21,*IRQ
82,EN257,Select Address Buffer,74F257, vidout,VIDOUT,62,VIDeo OUTput,output,Analog board J12,9 on J12
83,RD6,,, n_ipl0,*IPL0,31,CPU Interrupt Priority Level bit 0,output,68000,25,*IPL0
84,VCC,,, n_uds,*UDS,35,CPU Upper Data Strobe,input,68000,7,*UDS

Can't render this file because it has a wrong number of fields in line 2.