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:
parent
12eb917c24
commit
62d2e920e7
|
@ -48,7 +48,7 @@ a huge number of pins, its purpose can be summarized as follows.
|
|||
* 0x000000 - 0x3fffff: RAM/ROM (switches based on overlay)
|
||||
* 0x400000 - 0x4fffff: ROM
|
||||
* 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
|
||||
* 0xb00000 - 0xbfffff: Zilog 8530 SCC (Serial Control Chip) Write
|
||||
* 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
|
||||
signals.
|
||||
|
||||
|
|
|
@ -118,102 +118,13 @@
|
|||
|
||||
TODO Abbreviations legend, here since they are not noted elsewhere:
|
||||
|
||||
RA = RAM Address
|
||||
RDQ = RAM Data Value
|
||||
PMCYC = Processor Memory Cycle
|
||||
|
||||
PINOUT:
|
||||
Undocumented signal but assumed to exist:
|
||||
|
||||
RA0 79
|
||||
RA1 78
|
||||
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.
|
||||
64KRAM: Here we assign it to pin 21 for our own experimentation, a
|
||||
pin that is specified as just tied to ground.
|
||||
*/
|
||||
module bbu_master_ctrl
|
||||
// Essential sequential logic RESET and clock signals
|
||||
|
@ -250,21 +161,17 @@ module bbu_master_ctrl
|
|||
n_extdtk, n_earen,
|
||||
);
|
||||
|
||||
// TODO FIXME: Signals missing-in-action: OVERLAY, SNDPG2. It's
|
||||
// possible that the Macintosh SE uses a magic address access to
|
||||
// obviate the need for consuming a VIA pin for OVERLAY, but I have
|
||||
// no idea what this address would be. Has support for the second
|
||||
// sound page been dropped in the Macintosh SE? Yes, indeed it has
|
||||
// been. Nevertheless... for the sake of possibly making
|
||||
// quasi-hardware replicas of earlier Macintosh computers easier,
|
||||
// we will preserve an implementation here anyways. As for the
|
||||
// OVERLAY signal, we'll have to use Mini vMac's guess on how to
|
||||
// implement it. At boot, the ROM exclusively accesses the ROM
|
||||
// overlay addresses and the remapped RAM address when setting up.
|
||||
// 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.
|
||||
// The Macintosh SE deprecated SNDPG2. Nevertheless... for the
|
||||
// sake of possibly making quasi-hardware replicas of earlier
|
||||
// Macintosh computers easier, we will preserve an implementation
|
||||
// here anyways. As for the OVERLAY signal, we'll have to use Mini
|
||||
// vMac's guess on how to implement it. At boot, the ROM
|
||||
// exclusively accesses the ROM overlay addresses and the remapped
|
||||
// RAM address when setting up. 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
|
||||
// snooping.
|
||||
|
@ -272,9 +179,9 @@ module bbu_master_ctrl
|
|||
// Essential sequential logic RESET and clock signals
|
||||
input wire n_res; // *RESET signal
|
||||
input wire c16m; // 15.667200 MHz master clock input
|
||||
output reg c8m; // 7.8336 MHz clock output
|
||||
output reg c3_7m; // 3.672 MHz clock output
|
||||
output reg c2m; // 1.9584 MHz clock output
|
||||
output wire c8m; // 7.8336 MHz clock output
|
||||
output wire c3_7m; // 3.672 MHz clock output
|
||||
output wire c2m; // 1.9584 MHz clock output
|
||||
|
||||
// RAM configuration pins
|
||||
input wire row2; // 1/2 rows of RAM SIMMs jumper
|
||||
|
@ -284,40 +191,42 @@ module bbu_master_ctrl
|
|||
// MC68000 signals
|
||||
input wire a9, a17, a19, a20, a21, a22, a23;
|
||||
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;
|
||||
input wire n_vpa;
|
||||
|
||||
// DRAM signals
|
||||
inout wire ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra8;
|
||||
output reg ra7, ra9;
|
||||
output reg n_cas1l, n_cas0l, ram_r_n_w, n_ras, n_cas1h, n_cas0h;
|
||||
output wire ra7, ra9;
|
||||
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,
|
||||
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
|
||||
output reg n_romen;
|
||||
output wire n_romen;
|
||||
|
||||
// VIA signals
|
||||
output reg via_cs1;
|
||||
output wire via_cs1;
|
||||
input wire n_viairq;
|
||||
|
||||
// Video signals
|
||||
input wire vidpg2; // VIDPG2 signal
|
||||
output reg vidout; // VIDOUT signal
|
||||
output reg n_hsync; // *HSYNC signal
|
||||
output reg n_vsync; // *VSYNC signal
|
||||
output wire vidout; // VIDOUT signal
|
||||
output wire n_hsync; // *HSYNC signal
|
||||
output wire n_vsync; // *VSYNC signal
|
||||
|
||||
// Sound and disk speed signals
|
||||
input wire sndres;
|
||||
output reg snd, pwm;
|
||||
output wire snd, pwm;
|
||||
// IWM signals
|
||||
output reg n_iwm;
|
||||
output wire n_iwm;
|
||||
// SCC signals
|
||||
output reg n_sccen, n_sccrd, n_iow;
|
||||
output wire n_sccen, n_sccrd, n_iow;
|
||||
// SCSI signals
|
||||
output reg n_scsi;
|
||||
output wire n_scsi;
|
||||
input wire scsidrq;
|
||||
output reg n_dack;
|
||||
// PDS signals
|
||||
|
@ -326,8 +235,6 @@ module bbu_master_ctrl
|
|||
|
||||
// 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
|
||||
// the address bus. These are the registers we use to store the
|
||||
// address multiplexor outputs.
|
||||
|
@ -336,115 +243,51 @@ module bbu_master_ctrl
|
|||
// Installed RAM size.
|
||||
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.
|
||||
|
||||
// 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.
|
||||
// Important! How to handle SCSI DMA... according to Guide to the
|
||||
// Macintosh family hardware, page 126, this is "pseudo-DMA" mode.
|
||||
// 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.
|
||||
|
||||
// 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.
|
||||
|
||||
// The remainder of definitions are for sequential logic.
|
||||
always @(negedge n_res) begin
|
||||
// Initialize all output registers on RESET.
|
||||
|
||||
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_dack <= 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
|
||||
|
||||
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
|
||||
// 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 c16m;
|
||||
output reg c8m;
|
||||
output reg c3_7m;
|
||||
// c2m is now controlled by the DRAM controller state machine.
|
||||
input wire c2m;
|
||||
output reg n_pmcyc;
|
||||
// This is just an I/O argument placeholder. We still generate the
|
||||
// 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.
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// 15.6672 / 3.6720 = 9792/2295 = (51*2^6*3)/(51*3^2*5)
|
||||
// = (2^6)/(3*5) = 64/15
|
||||
/* Inside Macintosh claims that the serial clock is 3.672 MHz.
|
||||
Clock multiplication (via PLL) and division can be used to
|
||||
generate this from the 15.6672 MHz clock as follows:
|
||||
|
||||
// So, here's how we implement the frequency divider to generate
|
||||
// the 3.672 MHz clock. Initialize to 64 - 15 = 49, and keep
|
||||
// subtracting 15 until we reach zero or less. Then, add back 49,
|
||||
// and toggle the C3.7M output.
|
||||
15.6672 / 3.6720 = 9792/2295 = (51*2^6*3)/(51*3^2*5)
|
||||
= (2^6)/(3*5) = 64/15
|
||||
|
||||
// TODO FIXME: The complex frequency divider will not work
|
||||
// correctly: Since the base frequency is not high enough, there
|
||||
// will be terrible aliasing artifacts. Divide by 4 is a bit too
|
||||
// fast, divide by 5 is a bit too slow, but that's the best we can
|
||||
// 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.
|
||||
This would entail a PLL clock running at 235.008 MHz inside the
|
||||
BBU, which was impractical for the technology available during
|
||||
the 1980s. But if that were configured, a simple divide-by-64
|
||||
frequency counter would yield a perfect clock signal.
|
||||
|
||||
// TODO: Optimize this to minimize the number of register bits
|
||||
// required, while still preserving ideal frequency division and
|
||||
// synchronization behavior.
|
||||
As it turns out, the actual Macintosh did not use a true,
|
||||
constant-period 15.6672 MHz clock, but rather a 3.686 MHz clock
|
||||
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,
|
||||
// minimal cycle overhead.
|
||||
reg [5:0] c16m_div4_cntr; // Complex C16M -> C3_7M divider counter
|
||||
// reg [3:0] c16m_div8_cntr; // C16M / 8 counter
|
||||
reg c16m_div4_cntr; // C16M / 4 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 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
|
||||
// Initialize all output registers on RESET.
|
||||
c8m <= 0;
|
||||
c4m <= 0;
|
||||
c3_7m <= 0;
|
||||
// c2m <= 0;
|
||||
n_pmcyc <= 1;
|
||||
c2m <= 0;
|
||||
c1m <= 0;
|
||||
|
||||
// Initialize all internal registers on RESET.
|
||||
c16m_div4_cntr <= 1;
|
||||
// c16m_div8_cntr <= 1;
|
||||
c16m_div4_cntr <= 0;
|
||||
c16m_div4_0_cntr <= 0;
|
||||
c16m_div4_25_cntr <= 1;
|
||||
c16m_div8_cntr <= 1;
|
||||
c16m_div16_cntr <= 1;
|
||||
end
|
||||
|
||||
always @(posedge c16m) begin
|
||||
if (n_res) begin
|
||||
c8m <= ~c8m;
|
||||
if (c16m_div4_cntr[1]) begin
|
||||
c3_7m <= ~c3_7m;
|
||||
c16m_div4_cntr <= 1;
|
||||
if (c16m_div4_cntr) c4m <= ~c4m;
|
||||
c16m_div4_cntr <= ~c16m_div4_cntr;
|
||||
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
|
||||
else
|
||||
c16m_div4_cntr <= { c16m_div4_cntr[4:0], c16m_div4_cntr[5] };
|
||||
// if (c16m_div8_cntr[3]) c2m <= ~c2m;
|
||||
// c16m_div8_cntr <= { c16m_div8_cntr[2:0], c16m_div8_cntr[3] };
|
||||
if (c16m_div16_cntr[7]) n_pmcyc <= ~n_pmcyc;
|
||||
// else Slip in the extra cycle by not incrementing the
|
||||
// principal divide-by-4 counter.
|
||||
c16m_div4_25_cntr <= { c16m_div4_25_cntr[15:0],
|
||||
c16m_div4_25_cntr[16] };
|
||||
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] };
|
||||
end
|
||||
end
|
||||
|
@ -784,7 +652,7 @@ endmodule
|
|||
* 0x000000 - 0x3fffff: RAM/ROM (switches based on overlay)
|
||||
* 0x400000 - 0x4fffff: ROM
|
||||
* 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
|
||||
* 0xb00000 - 0xbfffff: Zilog 8530 SCC (Serial Control Chip) Write
|
||||
* 0xd00000 - 0xdfffff: IWM (Integrated Woz Machine; floppy)
|
||||
|
@ -792,58 +660,143 @@ endmodule
|
|||
* 0xf00000 - 0xffffef: ??? (the ROM appears to be accessing here)
|
||||
* 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,
|
||||
n_iwm, via_cs1, n_berr, a23_19,
|
||||
boot_overlay, r_n_w, reg_romen, reg_ram_w);
|
||||
module decode_devaddr (n_res, clk, n_ramen, n_romen, n_scsi,
|
||||
n_sccen, n_sccrd, n_iow, n_iwm, via_cs1, n_vpa,
|
||||
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_romen;
|
||||
output wire n_scsi;
|
||||
output wire n_sccen;
|
||||
output wire n_sccrd;
|
||||
output wire n_iow;
|
||||
output wire n_iwm;
|
||||
output wire via_cs1;
|
||||
output wire n_vpa;
|
||||
output wire n_berr;
|
||||
input wire n_as;
|
||||
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 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
|
||||
// signal is used to disable the boot-time memory overlay.
|
||||
output wire reg_romen;
|
||||
// Have we attempted to write to the regular RAM address zone?
|
||||
output wire reg_ram_w;
|
||||
output wire n_dtack_peri; // *DTACK for peripherals
|
||||
|
||||
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
|
||||
// the regular RAM region, then this is a *RAMEN trigger. The
|
||||
// overlay control logic will zero the switch on the next cycle,
|
||||
// but we use combinatorial logic here to act immediately.
|
||||
assign reg_ram_w = (~r_n_w & (a23_19[4:3] == 2'b00));
|
||||
assign n_ramen = ~((boot_overlay) ? (a23_19[4:1] == 4'b0110) :
|
||||
(a23_19[4:3] == 2'b00)) &
|
||||
~reg_ram_w;
|
||||
assign reg_romen = (a23_19[4:1] == 4'h4);
|
||||
// Only trigger *ROMEN for reads, not writes.
|
||||
assign n_romen = ~(reg_romen |
|
||||
(boot_overlay & r_n_w & (a23_19[4:3] == 2'b00)));
|
||||
assign n_scsi = ~(a23_19[4:0] == 5'b01011);
|
||||
assign n_sccen = ~((a23_19[4:1] == 4'h9) |
|
||||
(a23_19[4:1] == 4'hb));
|
||||
assign n_sccrd = ~(a23_19[4:1] == 4'h9);
|
||||
assign n_iwm = ~(a23_19[4:1] == 4'hd);
|
||||
assign via_cs1 = (a23_19[4:0] == 5'b11101);
|
||||
// TODO: We don't currently implement Auto Vector, but neither does
|
||||
// MESS/MAME but its emulation still works just fine? There could
|
||||
// be ROM patch hacks...
|
||||
assign reg_ram = ~n_as & (a23_19[4:3] == 2'b00);
|
||||
assign reg_ram_r = (r_n_w & reg_ram);
|
||||
assign reg_ram_w = (~r_n_w & reg_ram);
|
||||
assign n_ramen = ~((boot_overlay) ?
|
||||
((~n_as & ((a23_19[4:1] == 4'h6) |
|
||||
(a23_19[4:1] == 4'h7))) | reg_ram_w) :
|
||||
reg_ram);
|
||||
assign reg_romen = ~n_as & (a23_19[4:1] == 4'h4);
|
||||
// Only trigger *ROMEN for reads, not writes, in overlay zone.
|
||||
assign n_romen = ~(reg_romen | (boot_overlay & reg_ram_r));
|
||||
assign scsi = ~n_as & (a23_19[4:0] == 5'b01011);
|
||||
assign n_scsi = ~scsi;
|
||||
assign sccrd = ~n_as & (a23_19[4:1] == 4'h9);
|
||||
assign sccwr = ~n_as & (a23_19[4:1] == 4'hb);
|
||||
assign n_sccen = ~(sccrd | sccwr);
|
||||
assign n_sccrd = ~sccrd;
|
||||
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
|
||||
// sure to also signal errors in the boot-time overlay when booting
|
||||
// with less than 1 MB of RAM. This would require decoding more
|
||||
// address bits, though.
|
||||
assign berr_ram = 0;
|
||||
// Optionally trigger bus errors if a read is attempted from the
|
||||
// write-only SCC address space, and vice versa.
|
||||
assign berr_scc = (sccrd & ~r_n_w) | (sccwr & r_n_w);
|
||||
|
||||
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:1] == 4'h7) |
|
||||
(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:0] == 5'b11100));
|
||||
// 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
|
||||
|
||||
// Boot-time memory overlay register and controlling logic. This is
|
||||
// fairly straightforward to implement once you see all the other
|
||||
// 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 clk;
|
||||
output reg overlay;
|
||||
// Boot-time memory overlay switch, 1 = enable, 0 = disable.
|
||||
output reg boot_overlay;
|
||||
input wire reg_romen;
|
||||
input wire reg_ram_w;
|
||||
|
||||
always @(negedge n_res) begin
|
||||
// Initialize the overlay switch to ENABLED on RESET.
|
||||
overlay <= 1;
|
||||
boot_overlay <= 1;
|
||||
end
|
||||
|
||||
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
|
||||
// on the first attempt to write the regular RAM zone.
|
||||
if (reg_romen | reg_ram_w)
|
||||
overlay <= 0;
|
||||
boot_overlay <= 0;
|
||||
else
|
||||
; // Nothing to be done.
|
||||
end
|
||||
end
|
||||
endmodule // btm_overlay
|
||||
|
||||
endmodule
|
||||
|
||||
// Column address strobe decode logic. Determine which column access
|
||||
// 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
|
||||
// next, and so on.
|
||||
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
|
||||
|
||||
/* TODO: Summary of what is missing and left to implement: DRAM
|
||||
initialization pulses, DRAM refresh, video, disk, and audio
|
||||
scanout, SCSI DMA, EXTDTK yielding, 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.
|
||||
|
||||
*/
|
||||
initialization pulses, DRAM refresh, detect 2.5MB of RAM and
|
||||
configure address buffers accordingly, video, disk, and audio
|
||||
scanout, SCSI DMA, EXTDTK yielding, interrupt propagation,
|
||||
double-check SCC read/write logic. */
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
BBU Pin,Signal Name,Description,Device Connection,Device Pin
|
||||
1,GND,,,
|
||||
2,RD7,,,
|
||||
3,RD8,,,
|
||||
4,RD9,,,
|
||||
5,RD10,,,
|
||||
6,RD11,,,
|
||||
7,RD12,,,
|
||||
8,RD13,,,
|
||||
9,RD14,,,
|
||||
10,RD15,,,
|
||||
11,EXTPDS,,,
|
||||
12,EN245,Select Data Buffer,74LS245,
|
||||
13,VCC,,,
|
||||
14,/WR,,,
|
||||
15,/CAS-SIMM3,,SIMM3,2
|
||||
16,/CAS-SIMM1,,SIMM1,2
|
||||
17,/EOP,,53C80,
|
||||
18,/CAS-SIMM4,,SIMM4,2
|
||||
19,/CAS-SIMM2,,SIMM2,2
|
||||
20,/RAS,,,
|
||||
21,GND,,,
|
||||
22,VCC,,,
|
||||
23,A23,,,
|
||||
24,A22,,,
|
||||
25,A21,,,
|
||||
26,A20,,,
|
||||
27,A19,,,
|
||||
28,A17,,,
|
||||
29,A9,,,
|
||||
30,/IPL1,,68000,
|
||||
31,/IPL0,,68000,
|
||||
32,IRQ,,65C22/6523,
|
||||
33,/LDS,,68000,
|
||||
34,/BERR,,68000,
|
||||
35,/UDS,,,
|
||||
36,/VPA,,68000,
|
||||
37,CK,,68000,
|
||||
38,/DTACK,,68000,
|
||||
39,SELROM,Select ROM,ROM,"20 on ROM HI, LO"
|
||||
40,"RTxCB, PCLK, ADB CLK",All the things,"85C30, ADB, GLU","20 & 28 on 85C30, 16 on ADB, 9 on GLU"
|
||||
41,/AS,,,
|
||||
42,VCC,,,
|
||||
43,GND,,,
|
||||
44,FCLK,,"SWIM, GLU","24 on SWIM, 19 on GLU"
|
||||
45,SELSCC,Select SCC,85C30,32 on /CE
|
||||
46,/RD,,85C30,
|
||||
47,R/W,,,
|
||||
48,SELSWIM,Select SWIM,SWIM,7 on /DEV
|
||||
49,EXTFLP,PWM,External Floppy,10 on PWM
|
||||
50,PB7,,65C22/6523,
|
||||
51,SELSND,Select Sound,SND,
|
||||
52,EXTPDS,,,
|
||||
53,PA6,,65C22/6523,
|
||||
54,/LDS,,,
|
||||
55,DRQ,,53C80,22 on DRQ
|
||||
56,/DACK,,53C80,26 on /DACK
|
||||
57,SELSCSI,Select SCSI,53C80,21 on /CS
|
||||
58,SELVIA,Select VIA,65C22/6523,24 on RS0
|
||||
59,/RST,,,
|
||||
60,HSYNC,Horizontal Sync,J12,Pin 10 on J12
|
||||
61,VSYNC,Veritcal Sync,"J12, 65C22/6523","Pin 11 on J12, 40 on DB7"
|
||||
62,VIDOUT,Composite Video Out,"J12, 65C22/6523","Pin 9 on J12, 28 on PC3"
|
||||
63,GND,,,
|
||||
64,VCC,,,
|
||||
65,RA9,,,
|
||||
66,RA7,,,
|
||||
67,RA8,,,
|
||||
68,RA6,,,
|
||||
69,RD0,,,
|
||||
70,RA5,,,
|
||||
71,RA4,,,
|
||||
72,RD1,,,
|
||||
73,RA3,,,
|
||||
74,RD2,,,
|
||||
75,RD3,,,
|
||||
76,RA2,,,
|
||||
77,RD4,,,
|
||||
78,RA1,,,
|
||||
79,RA0,,,
|
||||
80,RD5,,,
|
||||
81,/PMCYC,,74F257,/OE
|
||||
82,EN257,Select Address Buffer,74F257,
|
||||
83,RD6,,,
|
||||
84,VCC,,,
|
||||
Verilog,Signal,Pin,Description,Direction,Device Connection,Device Pin,Device Signal
|
||||
ra0,RA0,79,RAM Address bit 0,inout,DRAM SIMMs
|
||||
ra1,RA1,78,RAM Address bit 1,inout,DRAM SIMMs
|
||||
ra2,RA2,76,RAM Address bit 2,inout,DRAM SIMMs
|
||||
ra3,RA3,73,RAM Address bit 3,inout,DRAM SIMMs
|
||||
ra4,RA4,71,RAM Address bit 4,inout,DRAM SIMMs
|
||||
ra5,RA5,70,RAM Address bit 5,inout,DRAM SIMMs
|
||||
ra6,RA6,68,RAM Address bit 6,inout,DRAM SIMMs
|
||||
ra8,RA8,67,RAM Address bit 8,inout,DRAM SIMMs
|
||||
ra7,RA7,66,RAM Address bit 7,output,DRAM SIMMs
|
||||
ra9,RA9,65,RAM Address bit 9,output,DRAM SIMMs
|
||||
n_cas1l,*CAS1L,16,DRAM Column Access Strobe row #2 low-byte SIMM,output,DRAM SIMMs
|
||||
n_cas0l,*CAS0L,15,DRAM Column Access Strobe row #1 low-byte SIMM,output,DRAM SIMMs
|
||||
ram_r_n_w,RAM R/*W,14,DRAM read/write,output,DRAM SIMMs
|
||||
n_ras,*RAS,20,DRAM Row Access Strobe,output,DRAM SIMMs
|
||||
n_cas1h,*CAS1H,19,DRAM Column Access Strobe row #2 high-byte SIMM,output,DRAM SIMMs
|
||||
n_cas0h,*CAS0H,18,DRAM Column Access Strobe row #1 high-byte SIMM,output,DRAM SIMMs
|
||||
rdq0,RDQ0,69,RAM Data Value bit 0,inout,DRAM SIMMs
|
||||
rdq1,RDQ1,72,RAM Data Value bit 1,inout,DRAM SIMMs
|
||||
rdq2,RDQ2,74,RAM Data Value bit 2,inout,DRAM SIMMs
|
||||
rdq3,RDQ3,75,RAM Data Value bit 3,inout,DRAM SIMMs
|
||||
rdq4,RDQ4,77,RAM Data Value bit 4,inout,DRAM SIMMs
|
||||
rdq5,RDQ5,80,RAM Data Value bit 5,inout,DRAM SIMMs
|
||||
rdq6,RDQ6,83,RAM Data Value bit 6,inout,DRAM SIMMs
|
||||
rdq7,RDQ7,2,RAM Data Value bit 7,inout,DRAM SIMMs
|
||||
rdq8,RDQ8,3,RAM Data Value bit 8,inout,DRAM SIMMs
|
||||
rdq9,RDQ9,4,RAM Data Value bit 9,inout,DRAM SIMMs
|
||||
rdq10,RDQ10,5,RAM Data Value bit 10,inout,DRAM SIMMs
|
||||
rdq11,RDQ11,6,RAM Data Value bit 11,inout,DRAM SIMMs
|
||||
rdq12,RDQ12,7,RAM Data Value bit 12,inout,DRAM SIMMs
|
||||
rdq13,RDQ13,8,RAM Data Value bit 13,inout,DRAM SIMMs
|
||||
rdq14,RDQ14,9,RAM Data Value bit 14,inout,DRAM SIMMs
|
||||
rdq15,RDQ15,10,RAM Data Value bit 15,inout,DRAM SIMMs
|
||||
n_en245,*EN245,12,Enable LS245 DRAM to CPU data bus switch,output,LS245,19,*EO
|
||||
n_dtack,*DTACK,38,CPU Data Transfer Acknowledge,inout,68000,10,*DTACK
|
||||
r_n_w,R/*W,47,CPU memory read/write,input,68000,9,R/*W
|
||||
n_ipl1,*IPL1,30,CPU Interrupt Priority Level bit 1,input,68000,24,*IPL1
|
||||
n_lds,*LDS,33,CPU Lower Data Strobe,input,68000,8,*LDS
|
||||
n_vpa,*VPA,36,CPU Valid Peripheral Address,output,68000,21,*VPA
|
||||
c8m,C8M,37,8MHz clock,output,68000,15,CLK
|
||||
null,VCC,22,+5V power,power
|
||||
null,VCC,64,+5V power,power
|
||||
null,VCC,42,+5V power,power
|
||||
null,VCC,84,+5V power,power
|
||||
mbram,MBRAM,17,1MB RAM SIMMs jumper,input,Jumper J16
|
||||
null,GND,1,Ground,power
|
||||
s64kram,64KRAM,21,UNOFFICIAL 64K RAM SIMMs jumper,input
|
||||
null,GND,43,Ground,power
|
||||
null,GND,63,Ground,power
|
||||
row2,ROW2,13,2 rows of RAM SIMMs jumper,input,Jumper J16
|
||||
n_extdtk,*EXTDTK,11,External PDS will drive *DTACK,input,PDS slot J13,B28,*EXT.DTACK
|
||||
a23,A23,23,CPU Address bit 23,input,68000,52,A23
|
||||
a22,A22,24,CPU Address bit 22,input,68000,51,A22
|
||||
a21,A21,25,CPU Address bit 21,input,68000,50,A21
|
||||
a20,A20,26,CPU Address bit 20,input,68000,48,A20
|
||||
a19,A19,27,CPU Address bit 19,input,68000,47,A19
|
||||
a17,A17,28,CPU Address bit 17,input,68000,45,A17
|
||||
a9,A9,29,CPU Address bit 9,input,68000,37,A9
|
||||
n_pmcyc,*PMCYC,81,Processor Memory CYCle,output,F257,15,*OE
|
||||
c2m,C2M,82,~2MHz DRAM row/column address selector clock,output,F257,1,S
|
||||
n_res,*RES,59,RESet,input,68000,18,*RES
|
||||
c16m,C16MRSF2,44,Filtered 16MHz clock input,input,GLU,19,FCLK
|
||||
c3_7m,C3.7M,40,~3.7MHz clock,output,"8530, ADB, GLU","20 & 28 on 8530, 16 on ADB, 9 on GLU",RTXCB
|
||||
n_romen,*ROMEN,39,ROM ENable,output,ROM,20,*CE
|
||||
n_sccrd,*SCCRD,46,Serial Communications Controller ReaD,output,8530,36,*RD
|
||||
pwm,PWM,49,Pulse Width Modulation floppy disk drive motor speed control,output,External Floppy,10,PWM
|
||||
scsidrq,SCSIDRQ,55,SCSI DMA ReQuest,input,5380,22,DRQ
|
||||
n_iwm,*IWM,48,Integrated Wozniak Machine floppy disk controller chip enable,output,IWM,7,*DEV
|
||||
n_sccen,*SCCEN,45,Serial Communications Controller chip ENable,output,8530,33,*CE
|
||||
n_scsi,*SCSI,57,SCSI chip select,output,5380,21,*CS
|
||||
n_dack,*DACK,56,SCSI DMA ACKnowledge,output,5380,26,*DACK
|
||||
sndres,SNDRES,50,SouND RESet,input,6522,17,PB7 vSndEnb
|
||||
via_cs1,VIA.CS1,58,VIA Chip Select 1,output,6522,24,CS1
|
||||
vidpg2,VIDPG2,53,VIDeo framebuffer PaGe 2,input,6522,8,PA6 vPage2
|
||||
n_earen,*EAREN,52,Unknown reserved PDS input signal,output,PDS slot J13,B11,Reserved
|
||||
n_as,*AS,41,CPU Address Strobe,input,68000,6,*AS
|
||||
n_berr,*BERR,34,CPU Bus ERRor,output,68000,22,*BERR
|
||||
snd,SND,51,PWM SouND output,output,Sound filter circuit
|
||||
n_vsync,*VSYNC,61,Video Vertical Synchronization control,output,Analog board J12,11 on J12 and 40 on 6522,CA1
|
||||
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
|
||||
n_hsync,*HSYNC,60,Video Horizontal Synchronization control,output,Analog board J12,10 on J12
|
||||
n_viairq,*VIAIRQ,32,VIA Interrupt ReQuest,input,6522,21,*IRQ
|
||||
vidout,VIDOUT,62,VIDeo OUTput,output,Analog board J12,9 on J12
|
||||
n_ipl0,*IPL0,31,CPU Interrupt Priority Level bit 0,output,68000,25,*IPL0
|
||||
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.
|
Loading…
Reference in New Issue