BBU: More analysis and insight.

This commit is contained in:
Andrew Makousky 2020-11-25 15:46:50 -06:00
parent 602a9b564d
commit c490406c81
4 changed files with 277 additions and 104 deletions

View File

@ -1496,6 +1496,10 @@ module avtimers ();
// point to ponder, this is an area of improvement where a // point to ponder, this is an area of improvement where a
// different algorithm can generate better audio quality. // different algorithm can generate better audio quality.
// Important! Main screen/sound buffers are selected when the VIA
// bit is one, alternate when the VIA bit is zero. These are
// treated as active low signals.
reg [15:0] snddsk_reg; // PCM sound sample and disk speed register 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_main_addr; // Address of main sound/disk buffer

View File

@ -40,9 +40,10 @@
`include "common.vh" `include "common.vh"
// PAL0-16R4: Timing State Machine // PAL0-16R4: Timing State Machine
module tsm(simclk, clk, sysclk, pclk, s1, ramen, romen, as, uds, lds, gnd, module tsm(simclk, n_res,
clk, sysclk, pclk, s1, ramen, romen, as, uds, lds, gnd,
oe1, casl, cash, ras, vclk, q2, q1, s0, dtack, vcc); oe1, casl, cash, ras, vclk, q2, q1, s0, dtack, vcc);
input `virtwire simclk; input `virtwire simclk, n_res;
input wire clk; input wire clk;
input wire sysclk, pclk, s1, ramen, romen, as, uds, lds; input wire sysclk, pclk, s1, ramen, romen, as, uds, lds;
`power wire gnd; `power wire gnd;
@ -52,6 +53,14 @@ module tsm(simclk, clk, sysclk, pclk, s1, ramen, romen, as, uds, lds, gnd,
output `simwire s0, dtack; output `simwire s0, dtack;
`power wire vcc; `power wire vcc;
// We must implement RESET for simulation or else this will never
// stabilize.
always @(negedge n_res) begin
casl <= 0; cash <= 0; s0 <= 0; dtack <= 0;
ras <= 0; vclk <= 0; q2 <= 0; q1 <= 0;
end
// Simulate combinatorial logic sub-cycles. // Simulate combinatorial logic sub-cycles.
always @(posedge simclk) begin always @(posedge simclk) begin
casl <= ~(~s0 & s1 & sysclk // video casl <= ~(~s0 & s1 & sysclk // video
@ -62,19 +71,19 @@ module tsm(simclk, clk, sysclk, pclk, s1, ramen, romen, as, uds, lds, gnd,
| ~s0 & ~ramen & ~uds // processor | ~s0 & ~ramen & ~uds // processor
| ~s0 & ~cash & sysclk | ~s0 & ~cash & sysclk
| pclk & ~cash); | pclk & ~cash);
s0 <= ~(~ras & ~sysclk // 0 for `cas` and 1 for `ras` (estamos contando com o atraso da PAL) s0 <= ~(~ras & ~sysclk // 0 for `cas` and 1 for `ras` (counting with the delay of the PAL)
| ~ras & ~s0); | ~ras & ~s0);
dtack <= ~(~romen // se a ROM for de 250 nS ou SCC ou IWM dtack <= ~(~romen // if the ROM is 250 nS or SCC or IWM
| ~ras & ~ramen & ~s1 // garante que vai ser reconhecido na descida de `pclk` no estado `s5` | ~ras & ~ramen & ~s1 // guarantees that it will be recognized on the falling edge of `pclk` in state `s5`
| ~as & ~dtack & ramen // espera `as` subir para desativar | ~as & ~dtack & ramen // expects `as` to rise for disable
| ~as & ~dtack & ~s1); // mas evite ciclas de video (WE) | ~as & ~dtack & ~s1); // but avoid video cycles (WE)
end end
// Simulate registered logic. // Simulate registered logic.
always @(posedge clk) begin always @(posedge clk) begin
ras <= ~(~pclk & q1 & s1 // video cycle ras <= ~(~pclk & q1 & s1 // video cycle
| ~pclk & q1 & ~ramen & dtack // processor cycle | ~pclk & q1 & ~ramen & dtack // processor cycle
| pclk & ~ras); // any other (?) (segura mais um ciclo) cycle | pclk & ~ras); // any other cycle
vclk <= ~(~q1 & pclk & q2 & vclk // divide by 8 (1MHz) vclk <= ~(~q1 & pclk & q2 & vclk // divide by 8 (1MHz)
| ~vclk & q1 | ~vclk & q1
| ~vclk & ~pclk | ~vclk & ~pclk
@ -95,10 +104,11 @@ endmodule
// cas of sound: pup|pup|pup|spg|pup|spg|spg|spg|3q1 // cas of sound: pup|pup|pup|spg|pup|spg|spg|spg|3q1
// PAL1-16R8: Linear Address Generator // PAL1-16R8: Linear Address Generator
module lag(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1, module lag(simclk, n_res,
sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
gnd, oe2, vshft, vsync, hsync, s1, viapb6, snddma, gnd, oe2, vshft, vsync, hsync, s1, viapb6, snddma,
reslin, resnyb, vcc); reslin, resnyb, vcc);
input `virtwire simclk; input `virtwire simclk, n_res;
input wire sysclk; input wire sysclk;
input wire p2io1, l28, va4, p0q2, vclk, va3, va2, va1; input wire p2io1, l28, va4, p0q2, vclk, va3, va2, va1;
`power wire gnd; `power wire gnd;
@ -106,22 +116,29 @@ module lag(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
output reg vshft, vsync, hsync, s1, viapb6, snddma, reslin, resnyb; output reg vshft, vsync, hsync, s1, viapb6, snddma, reslin, resnyb;
`power wire vcc; `power wire vcc;
// We must implement RESET for simulation or else this will never
// stabilize.
always @(negedge n_res) begin
vshft <= 0; vsync <= 0; hsync <= 0; s1 <= 0; viapb6 <= 0;
snddma <= 0; reslin <= 0; resnyb <= 0;
end
// Simulate combinatorial logic sub-cycles. // Simulate combinatorial logic sub-cycles.
always @(posedge simclk) begin always @(posedge simclk) begin
end end
// Simulate registered logic. // Simulate registered logic.
always @(posedge sysclk) begin always @(posedge sysclk) begin
vshft <= ~(s1 & ~vclk & snddma); // um pulso depois da descida de `vclk` vshft <= ~(s1 & ~vclk & snddma); // one pulse on the falling edge of `vclk`
vsync <= ~(reslin vsync <= ~(reslin
| ~vsync & ~l28); | ~vsync & ~l28);
hsync <= ~(viapb6 & va4 & ~va3 & ~va2 & va1 // comec,a em29 (VA5) hsync <= ~(viapb6 & va4 & ~va3 & ~va2 & va1 // begins in 29 (VA5)
| /*~ ???*/resnyb | /*~ ???*/resnyb
| ~hsync & viapb6); // termina em 0F | ~hsync & viapb6); // ends in 0F
s1 <= ~(~p0q2 // 0 for processor and 1 for video s1 <= ~(~p0q2 // 0 for processor and 1 for video
| ~vclk | ~vclk
| ~vsync & hsync | ~vsync & hsync
| ~vsync & viapb6 // no vertical retrace s'o temos ciclos de som | ~vsync & viapb6 // only in vertical retrace we have sound cycles
| ~viapb6 & hsync & ~va4 & ~va3 & ~va2 | ~viapb6 & hsync & ~va4 & ~va3 & ~va2
| ~viapb6 & ~hsync & (~va4 | va4 & ~va3 & ~va2 | | ~viapb6 & ~hsync & (~va4 | va4 & ~va3 & ~va2 |
va4 & ~va3 & va2 & ~va1)); va4 & ~va3 & va2 & ~va1));
@ -131,10 +148,10 @@ module lag(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
| ~hsync & ~viapb6 | ~hsync & ~viapb6
| resnyb & ~viapb6 | resnyb & ~viapb6
| vshft & ~viapb6); | vshft & ~viapb6);
snddma <= ~(viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 nesta sa'ida snddma <= ~(viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 in this output
| ~snddma & vclk); // ... indicates sound cycle | ~snddma & vclk); // ... indicates sound cycle
reslin <= ~(0); // ??? tentamos gerar linha 370 reslin <= ~(0); // ??? try to generate line 370
resnyb <= ~(vclk // incrementa VA5:VA14 em 0F e 2B resnyb <= ~(vclk // increment VA5:VA14 in 0F and 2B
| viapb6 // ??? | viapb6 // ???
| va1 | va1
| va2 | va2
@ -146,37 +163,45 @@ module lag(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
end end
endmodule endmodule
// 32 ciclas atiuas par linha - UA6..UA1 = 0 to 1F // 32 active cycles for line - UA6..UA1 = 0 to 1F
// 1 ciclos de som/pwm = 2B // 1 cycle for sound/PWM = 2B
// 11 ciclos de retrac,o = 20 to 2A // 11 cycles for retrace = 20 to 2A
// 342 linhas ativas - VA6..VA14 = 010011100 to 111110001 // 342 active lines - VA6..VA14 = 010011100 to 111110001
// 28 linhas de retrac,o = 010000000 to 010011011 // 28 retrace lines = 010000000 to 010011011
// PAL2-16L8: Bus Management Unit 1 // PAL2-16L8: Bus Management Unit 1
module bmu1(simclk, va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd, module bmu1(simclk, n_res,
va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd,
as, csiwm, rd, cescc, vpa, romen, ramen, io1, l28, vcc); as, csiwm, rd, cescc, vpa, romen, ramen, io1, l28, vcc);
input `virtwire simclk; input `virtwire simclk, n_res;
input wire va9, va8, va7, l15, va14, ovlay, a23, a22, a21; input wire va9, va8, va7, l15, va14, ovlay, a23, a22, a21;
`power wire gnd; `power wire gnd;
input wire as; input wire as;
output `simwire csiwm, rd, cescc, vpa, romen, ramen, io1, l28; output `simwire csiwm, rd, cescc, vpa, romen, ramen, io1, l28;
`power wire vcc; `power wire vcc;
// We must implement RESET for simulation or else this will never
// stabilize.
always @(negedge n_res) begin
csiwm <= 0; rd <= 0; cescc <= 0; vpa <= 0; romen <= 0;
ramen <= 0; io1 <= 0; l28 <= 0;
end
// Simulate combinatorial logic sub-cycles. // Simulate combinatorial logic sub-cycles.
always @(posedge simclk) begin always @(posedge simclk) begin
csiwm <= ~(a23 & a22 & ~a21 & ~as); // DFE1FF csiwm <= ~(a23 & a22 & ~a21 & ~as); // DFE1FF
rd <= ~(a23 & ~a22 & ~a21 & ~as); // 9FFFF8 rd <= ~(a23 & ~a22 & ~a21 & ~as); // 9FFFF8
cescc <= ~(a23 & ~a22 & ~as); // 9FFFF8(R) or BFFFF9(W) cescc <= ~(a23 & ~a22 & ~as); // 9FFFF8(R) or BFFFF9(W)
vpa <= ~(a23 & a22 & a21 & ~as); // acima de E00000 'e s'incrano vpa <= ~(a23 & a22 & a21 & ~as); // above E00000 is synchronous
romen <= ~(~a23 & a22 & ~a21 & ~as // 400000 romen <= ~(~a23 & a22 & ~a21 & ~as // 400000
| ~a23 & ~a22 & ~a21 & ~as & ovlay // (and 000000 with `ovlay`) | ~a23 & ~a22 & ~a21 & ~as & ovlay // (and 000000 with `ovlay`)
| a23 & ~a22 & ~as | a23 & ~a22 & ~as
| a23 & ~a21 & ~as); // para gerar DTACK (n~ao acessa ROM: A20) | a23 & ~a21 & ~as); // for generating DTACK (not accessing ROM: A20)
ramen <= ~(~a23 & ~a22 & ~a21 & ~as & ~ovlay // 000000 ramen <= ~(~a23 & ~a22 & ~a21 & ~as & ~ovlay // 000000
| ~a23 & a22 & a21 & ~as & ovlay); // (600000 with `ovlay`) | ~a23 & a22 & a21 & ~as & ovlay); // (600000 with `ovlay`)
io1 <= ~(0); // ??? io1 <= ~(0); // ???
l28 <= ~(~l15 & ~va9 & ~va8 & va7 // chegamos a 370 ou n~ao passamos da limha 28 l28 <= ~(~l15 & ~va9 & ~va8 & va7 // reached 370 or we don't pass line 28
| ~l28 & ~va9 | ~l28 & ~va9
| ~l28 & ~va8 | ~l28 & ~va8
| ~l28 & ~va7); | ~l28 & ~va7);
@ -184,9 +209,10 @@ module bmu1(simclk, va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd,
endmodule endmodule
// PAL3-16R4: Bus Management Unit 0 // PAL3-16R4: Bus Management Unit 0
module bmu0(simclk, sysclk, ramen, romen, va10, va11, va12, va13, va14, rw, module bmu0(simclk, n_res,
sysclk, ramen, romen, va10, va11, va12, va13, va14, rw,
gnd, oe1, g244, we, ava14, l15, vid, ava13, servid, dtack, vcc); gnd, oe1, g244, we, ava14, l15, vid, ava13, servid, dtack, vcc);
input `virtwire simclk; input `virtwire simclk, n_res;
input wire sysclk; input wire sysclk;
input wire ramen, romen, va10, va11, va12, va13, va14, rw; input wire ramen, romen, va10, va11, va12, va13, va14, rw;
`power wire gnd; `power wire gnd;
@ -198,28 +224,37 @@ module bmu0(simclk, sysclk, ramen, romen, va10, va11, va12, va13, va14, rw,
input wire servid, dtack; input wire servid, dtack;
`power wire vcc; `power wire vcc;
// We must implement RESET for simulation or else this will never
// stabilize.
always @(negedge n_res) begin
g244 <= 0; we <= 0;
ava14 <= 0; l15 <= 0; vid <= 0; ava13 <= 0;
end
// Simulate combinatorial logic sub-cycles. // Simulate combinatorial logic sub-cycles.
always @(posedge simclk) begin always @(posedge simclk) begin
g244 <= ~(~ramen & rw g244 <= ~(~ramen & rw
| ~g244 & ~ramen); | ~g244 & ~ramen);
we <= ~(~ramen & ~rw we <= ~(~ramen & ~rw
| ~we & ~dtack); // o dtack 'e mais curto antes de ciclo de video | ~we & ~dtack); // or `dtack` is shorter before the video cycle
end end
// Simulate registered logic. // Simulate registered logic.
always @(posedge sysclk) begin always @(posedge sysclk) begin
ava14 <= ~(~va14 & ~va13); // + 1 ava14 <= ~(~va14 & ~va13); // + 1
l15 <= ~(~va14 & ~va13 & ~va12 & ~va11 & ~va10 // n~ao passamos da linha 15 l15 <= ~(~va14 & ~va13 & ~va12 & ~va11 & ~va10 // we haven't passed line 15
| va14 & ~va13 & va12 & va11 & va10); // passamos de 368 | va14 & ~va13 & va12 & va11 & va10); // passed by 368
vid <= ~(servid); // aqui estamos invertendo: blanking est'a em `vshft` vid <= ~(servid); // here we invert: blanking is in `vshft`
ava13 <= ~(va13); // + 1 ava13 <= ~(va13); // + 1
end end
endmodule endmodule
// PAL4-16R6: Timing Signal Generator // PAL4-16R6: Timing Signal Generator
module tsg(simclk, sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia, module tsg(simclk, n_res,
sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia,
gnd, oe3, d0, q6, clkscc, q4, q3, viacb1, pclk, ipl0, vcc); gnd, oe3, d0, q6, clkscc, q4, q3, viacb1, pclk, ipl0, vcc);
input `virtwire simclk; input `virtwire simclk, n_res;
input wire sysclk; input wire sysclk;
input wire vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia; input wire vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia;
`power wire gnd; `power wire gnd;
@ -229,11 +264,20 @@ module tsg(simclk, sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia,
output `simwire ipl0; output `simwire ipl0;
`power wire vcc; `power wire vcc;
// We must implement RESET for simulation or else this will never
// stabilize.
always @(negedge n_res) begin
d0 <= 0; ipl0 <= 0;
q6 <= 0; clkscc <= 0; q4 <= 0; q3 <= 0; viacb1 <= 0;
pclk <= 0;
end
// Simulate combinatorial logic sub-cycles. // Simulate combinatorial logic sub-cycles.
always @(posedge simclk) begin always @(posedge simclk) begin
ipl0 <= ~intscc | intvia; // CORRECTION ipl0 <= ~intscc | intvia; // CORRECTION
// ipl0 <= ~(0); // ??? /M nanda // ipl0 <= ~(0); // ??? /M nanda
d0 <= ~(~vpa & ~a19 & e); // F00000 amostra a fase como 0 /n e' + usado d0 <= ~(~vpa & ~a19 & e); // F00000 sample the phase with 0 /n e' + usado
end end
// Simulate registered logic. // Simulate registered logic.
@ -244,26 +288,42 @@ module tsg(simclk, sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia,
| clkscc & ~pclk & ~q3 | clkscc & ~pclk & ~q3
| clkscc & ~pclk & vclk | clkscc & ~pclk & vclk
| ~clkscc & pclk | ~clkscc & pclk
| ~clkscc & q4 & q3 & ~vclk); // a cada 32 ciclos n~ao vira | ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
viacb1 <= ~(0); // ??? /M nanda viacb1 <= ~(0); // ??? /M nanda
pclk <= ~(pclk); // divide SYSCLK por 2 (8MHz) pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz)
q3 <= ~(~vclk); // `sysclk` / 16 q3 <= ~(~vclk); // `sysclk` / 16
q4 <= ~(q4 & q3 & ~vclk // `sysclk` / 32 q4 <= ~(q4 & q3 & ~vclk // `sysclk` / 32
| ~q4 & ~q3 // } J p/gerar CLKSCC | ~q4 & ~q3 // } J for generating CLKSCC
| ~q4 & vclk); | ~q4 & vclk);
end end
endmodule endmodule
/* TODO: Now in order to fully implement the Macintosh's custom board /* Now in order to fully implement the Macintosh's custom board
capabilities, we must as a baseline have an implementation of some capabilities, we must as a baseline have an implementation of some
standard logic chips that are found on the Macintosh Main Logic standard logic chips that are found on the Macintosh Main Logic
Board. This is where we implement the modules. */ Board. This is where we implement the modules. */
`include "stdlogic.v" `include "stdlogic.v"
// Wire that PAL cluster together, along with supporting standard // Wire that PAL cluster together, along with supporting standard
// logic chip. Here, we try to better indicate active high and active // logic chips. Here, we try to better indicate active high and
// low because we also need to stick in a hex inverter chip. // active low because we also need to stick in a hex inverter chip.
module palcl(); module palcl(simclk, vcc, gnd, n_res, n_sysclk,
sysclk, pclk, p0q1, clkscc, p0q2, vclk, q3, q4,
e, keyclk,
a23, a22, a21, a20, a19, a18, a17, a16,
a15, a14, a13, a12, a11, a10, a9,
a8, a7, a6, a5, a4, a3, a2, a1,
n_as, n_uds, n_lds, n_dtack, r_n_w,
d0, d1, d2, d3, d4, d5, d6, d7,
d8, d9, d10, d11, d12, d13, d14, d15,
casl, cash, ras, we,
ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra7, ra8, ra9,
rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, rdq6, rdq7,
rdq8, rdq9, rdq10, rdq11, rdq12, rdq13, rdq14, rdq15,
n_intscc, n_intvia, n_ipl0,
n_ramen, n_romen, n_csiwm, n_sccrd, n_cescc, n_vpa,
viapb6, ovlay, viacb1, n_sndpg2, n_vidpg2,
n_vsync, n_hsync, vid);
input `virtwire simclk; input `virtwire simclk;
`power wire vcc; `power wire vcc;
`power wire gnd; `power wire gnd;
@ -272,23 +332,12 @@ module palcl();
// Clocks // Clocks
// 8,4,3.686,2,1,1,0.5 MHz // 8,4,3.686,2,1,1,0.5 MHz
output wire pclk, p0q1, clkscc, p0q2, vclk, q3, q4; output wire sysclk, pclk, p0q1, clkscc, p0q2, vclk, q3, q4;
input wire e; // 6800 synchronous I/O "E" clock, ~1MHz input wire e; // 6800 synchronous I/O "E" clock, ~1MHz
input wire keyclk; input wire keyclk;
// TODO: Also implement dual video address counter ICs as part of
// the PAL cluster.
// Video address signals, comes from video counter IC
wire va14, va13, va12, va11, va10, va9, va8, va7,
va6, va5, va4, va3, va2, va1;
// Audio address signals?
output wire ava14, ava13;
// Video control signals
output wire n_vsync, n_hsync, vid;
// MC68000 CPU address signals // MC68000 CPU address signals
input wire a23, a22, a21, a20, a19, a17, a16, input wire a23, a22, a21, a20, a19, a18, a17, a16,
a15, a14, a13, a12, a11, a10, a9, a15, a14, a13, a12, a11, a10, a9,
a8, a7, a6, a5, a4, a3, a2, a1; a8, a7, a6, a5, a4, a3, a2, a1;
// not used: a18 // not used: a18
@ -298,27 +347,37 @@ module palcl();
inout wire d0, d1, d2, d3, d4, d5, d6, d7, inout wire d0, d1, d2, d3, d4, d5, d6, d7,
d8, d9, d10, d11, d12, d13, d14, d15; d8, d9, d10, d11, d12, d13, d14, d15;
// Chip enable signals
output wire n_ramen, n_romen, n_csiwm, n_sccrd, n_cescc, n_vpa;
// Interrupt signals
input wire n_intscc, n_intvia;
output wire n_ipl0;
// VIA signals
output wire viapb6; // horizontal blanking
input wire ovlay; // Boot-time overlay
output wire viacb1; // keyboard interrupt
// wire d0; // Video timing phase sense signal
// DRAM signals // DRAM signals
output wire casl, cash, ras, we; output wire casl, cash, ras, we;
output wire ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra7, ra8, ra9; output wire ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra7, ra8, ra9;
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;
// Interrupt signals
input wire n_intscc, n_intvia;
output wire n_ipl0;
// Chip enable signals
output wire n_ramen, n_romen, n_csiwm, n_sccrd, n_cescc, n_vpa;
// VIA signals
output wire viapb6; // horizontal blanking
input wire ovlay; // Boot-time overlay
output wire viacb1; // keyboard interrupt
input wire n_sndpg2; // VIA PA3
input wire n_vidpg2; // VIA PA6
// wire d0; // Video timing phase sense signal
// Video control signals
output wire n_vsync, n_hsync, vid;
// Internal video address signals, comes from video counter IC
wire va14, va13, va12, va11, va10, va9, va8, va7,
va6, va5, va4, va3, va2, va1;
// Incremented high-order video address lines
wire ava14, ava13;
// Internal video signals // Internal video signals
wire n_vshft, n_snddma, servid; wire n_vshft, n_snddma, n_servid;
// Address multiplexer signals? // Address multiplexer signals?
wire s0, s1, l28, l15, n_245oe; wire s0, s1, l28, l15, n_245oe;
@ -331,41 +390,54 @@ module palcl();
wire p2io1, q6; wire p2io1, q6;
// Wires to/from standard logic chips. // Wires to/from standard logic chips.
wire sysclk, snddma, n_a20, n_sndres, sndres, n_snd, snd, wr, n_wr; wire snddma, n_a20, n_sndres, sndres, n_snd, snd, wr, n_wr;
// N.B.: *WR comes from IWM chip, WR goes to floppy drives. *A20 // N.B.: *WR comes from IWM chip, WR goes to floppy drives. *A20
// goes to VIA.CS1. *SNDDMA comes from the LAG. *SYSCLK comes // goes to VIA.CS1. *SNDDMA comes from the LAG. *SYSCLK comes
// from the 16MHz crystal oscillator. // from the 16MHz crystal oscillator. SND comes from the dual PWM
// disk driver counters.
// *DMALD is generated by ASG. wire n_dmald; // *DMALD is generated by ASG.
wire c8mf, c16mf, n_dmald, u12f_tc, ram_r_n_w_f; wire c8mf, c16mf, c2m, u12f_tc, ram_r_n_w_f;
wire vmsh; // video mid-shift, connect two register chips together wire vmsh; // video mid-shift, connect two register chips together
wire n_lermd; // ???
wire n_ldps; // => n_vshft
wire s5;
wire vid_n_a4; // => s1 wire s5; // Video shift register final output
// L12 => va13
// L13 => va14
// va12 => ava13
// va13 => ava14
// n_ldps => n_vshft
// VID/*u => s1
// tc => vclk // tc => vclk
wire l13, l12; // ???
wire n_sndpg2; // ???
wire n_vidpg2; // ???
// TODO FIXME! We're not using assign correctly! `assign` implies // TODO FIXME! We're not using assign correctly! `assign` implies
// diode isolation between separate nets. We want to merge // diode isolation between separate nets. We want to merge
// multiple names together for the same net. // multiple names together for the same net.
// N.B. on PCB, use c8mf for high-frequency signal // N.B. on PCB, use c8mf for high-frequency signal
// filter/conditioning. // filter/conditioning, we add a resistor.
assign c8mf = pclk; assign c8mf = pclk;
assign c16mf = sysclk; assign c16mf = sysclk;
assign ram_r_n_w_f = we; assign ram_r_n_w_f = we;
assign c2m = p0q2;
// TSEN0: 150 ohm resistor to GND for PAL for TSM and BMU0.
assign tsm_oe1 = gnd;
assign bmu0_oe1 = gnd;
// TSEN1: 150 ohm resistor to GND for LAG.
assign lag_oe2 = gnd;
// TSG Output Enable is controlled by CAS on Macintosh Plus,
// otherwise just go straight to ground on Macintosh 128k.
assign tsg_oe3 = gnd;
/* N.B. The reason why phase calibration is required in the /* N.B. The reason why phase calibration is required in the
Macintosh is because the PALs do not have a RESET pin. It is Macintosh 128k/512k/Plus is because the PALs do not have a RESET
the logic designer's discretion to implement one explicitly, of pin. It is the logic designer's discretion to implement one
they could forgo it to allow for more I/O pins. Hence the explicitly, of they could forgo it to allow for more I/O pins.
motivation to use software phase correction instead. */ Hence the motivation to use software phase correction
instead. */
// Inverters and 16MHz clock buffer // Inverters and 16MHz clock buffer
f04 u4d(n_sysclk, sysclk, n_snddma, snddma, a20, n_a20, gnd, f04 u4d(n_sysclk, sysclk, n_snddma, snddma, a20, n_a20, gnd,
@ -377,9 +449,9 @@ module palcl();
n_dmald, n_sndres, , , , , u12f_tc, vcc); n_dmald, n_sndres, , , , , u12f_tc, vcc);
// Dual video shift registers // Dual video shift registers
ls166 u10f(vmsh, rdq8, rdq9, rdq10, rdq11, 1'b0, c16mf, gnd, ls166 u10f(vmsh, rdq8, rdq9, rdq10, rdq11, 1'b0, c16mf, gnd,
s5, rdq12, rdq13, rdq14, n_lermd, rdq15, n_ldps, vcc); s5, rdq12, rdq13, rdq14, n_servid, rdq15, n_vshft, vcc);
ls166 u11f(s5, rdq0, rdq1, rdq2, rdq3, 1'b0, c16mf, gnd, ls166 u11f(s5, rdq0, rdq1, rdq2, rdq3, 1'b0, c16mf, gnd,
s5, rdq4, rdq5, rdq6, vmsh, rdq7, n_ldps, vcc); s5, rdq4, rdq5, rdq6, vmsh, rdq7, n_vshft, vcc);
// Dual RAM data bus transceivers // Dual RAM data bus transceivers
ls245 u9e(ram_r_n_w_f, rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, rdq6, rdq7, ls245 u9e(ram_r_n_w_f, rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, rdq6, rdq7,
gnd, d7, d6, d5, d4, d3, d2, d1, d0, n_245oe, vcc); gnd, d7, d6, d5, d4, d3, d2, d1, d0, n_245oe, vcc);
@ -388,38 +460,39 @@ module palcl();
n_245oe, vcc); n_245oe, vcc);
// RAM RA8/RA9 row/column video/CPU address multiplexer // RAM RA8/RA9 row/column video/CPU address multiplexer
f253 u10g(snddma, s1, va9, s5, a9, a17, ra8, gnd, f253 u10g(snddma, s1, va9, s5, a9, a17, ra8, gnd,
ra9, a20, a19, s5, s5, p0q2/*c2m*/, 1'b0, vcc); ra9, a20, a19, s5, s5, c2m, 1'b0, vcc);
// Dual video address counters // Dual video address counters
ls393 u1f(vclk, resnyb, va1, va2, va3, va4, gnd, ls393 u1f(vclk, resnyb, va1, va2, va3, va4, gnd,
va8, va7, va6, va5, reslin, resnyb, vcc); va8, va7, va6, va5, reslin, resnyb, vcc);
ls393 u1g(va8, reslin, va9, va10, va11, va12, gnd, ls393 u1g(va8, reslin, va9, va10, va11, va12, gnd,
, , l13, l12, reslin, va12, vcc); , , va14, va13, reslin, va12, vcc);
// RAM row/column video/CPU address multiplexers // RAM row/column video/CPU address multiplexers
f257 u2f(p0q2/*c2m*/, s5, va6, ra0, n_snd, va7, ra1, gnd, f257 u2f(c2m, s5, va6, ra0, n_snd, va7, ra1, gnd,
ra3/*???*/, va9, n_sndpg2, ra2, va8, n_sndpg2, n_snddma, vcc); ra3/*???*/, va9, n_sndpg2, ra2, va8, n_sndpg2, n_snddma, vcc);
f257 u2g(p0q2/*c2m*/, s5, va10, ra4, n_sndpg2, va11, ra5, gnd, f257 u2g(c2m, s5, va10, ra4, n_sndpg2, va11, ra5, gnd,
ra7, va13, s5, ra6, va12, s5, n_snddma, vcc); ra7, va13, s5, ra6, va12, s5, n_snddma, vcc);
f253 u3f(snddma, s1, va3, va11, a3, a11, ra2, gnd, f253 u3f(snddma, s1, va3, va11, a3, a11, ra2, gnd,
ra3, a12, a4, va12, va4, p0q2/*c2m*/, snddma, vcc); ra3, a12, a4, va12, va4, c2m, snddma, vcc);
f253 u3g(snddma, s1, va5, va13, a5, a13, ra4, gnd, f253 u3g(snddma, s1, va5, va13, a5, a13, ra4, gnd,
ra5, a14, a6, va14, va6, p0q2/*c2m*/, snddma, vcc); ra5, a14, a6, va14, va6, c2m, snddma, vcc);
f253 u4f(snddma, s1, va1, s5, a1, a9, ra0, gnd, f253 u4f(snddma, s1, va1, s5, a1, a9, ra0, gnd,
ra1, a10, a2, va10, va2, p0q2/*c2m*/, snddma, vcc); ra1, a10, a2, va10, va2, c2m, snddma, vcc);
f253 u4g(snddma, s1, va7, n_vidpg2, a7, a15, ra6, gnd, f253 u4g(snddma, s1, va7, n_vidpg2, a7, a15, ra6, gnd,
ra7, a16, a8, s5, va8, p0q2/*c2m*/, snddma, vcc); ra7, a16, a8, s5, va8, c2m, snddma, vcc);
tsm pal0(simclk, sysclk, sysclk, pclk, s1, n_ramen, n_romen, n_as, n_uds, n_lds, tsm pal0(simclk, n_res, sysclk, sysclk, pclk, s1, n_ramen, n_romen, n_as, n_uds, n_lds,
gnd, tsm_oe1, casl, cash, ras, vclk, p0q2, p0q1, s0, n_dtack, vcc); gnd, tsm_oe1, casl, cash, ras, vclk, p0q2, p0q1, s0, n_dtack, vcc);
lag pal1(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1, lag pal1(simclk, n_res, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
gnd, lag_oe2, n_vshft, n_vsync, n_hsync, s1, viapb6, gnd, lag_oe2, n_vshft, n_vsync, n_hsync, s1, viapb6,
n_snddma, reslin, n_snddma, reslin,
resnyb, vcc); resnyb, vcc);
bmu1 pal2(simclk, va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd, bmu1 pal2(simclk, n_res, va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd,
n_as, n_csiwm, n_sccrd, n_cescc, n_vpa, n_romen, n_ramen, p2io1, l28, vcc); n_as, n_csiwm, n_sccrd, n_cescc, n_vpa, n_romen, n_ramen, p2io1, l28, vcc);
bmu0 pal3(simclk, sysclk, n_ramen, n_romen, va10, va11, va12, va13, va14, bmu0 pal3(simclk, n_res, sysclk, n_ramen, n_romen, va10, va11, va12, va13, va14,
r_n_w, gnd, bmu0_oe1, n_245oe, we, ava14, l15, vid, ava13, r_n_w, gnd, bmu0_oe1, n_245oe, we, ava14, l15, vid, ava13,
servid, n_dtack, vcc); n_servid, n_dtack, vcc);
tsg pal4(simclk, sysclk, n_vpa, a19, vclk, p0q1, e, keyclk, n_intscc, tsg pal4(simclk, n_res,
sysclk, n_vpa, a19, vclk, p0q1, e, keyclk, n_intscc,
n_intvia, gnd, tsg_oe3, d0, q6, clkscc, q4, q3, viacb1, n_intvia, gnd, tsg_oe3, d0, q6, clkscc, q4, q3, viacb1,
pclk, n_ipl0, vcc); pclk, n_ipl0, vcc);

View File

@ -143,12 +143,18 @@ module ls161(n_clr, clk, a, b, c, d, enp, gnd,
assign rco = (outvec == 4'hf); assign rco = (outvec == 4'hf);
assign { q_d, q_c, q_b, q_a } = outvec; assign { q_d, q_c, q_b, q_a } = outvec;
// Clear is asynchronous, so it is not dependent on the clock.
always @(negedge n_clr) begin
if (~n_clr) outvec <= 0;
end
// N.B. As soon as the rising edge of the clock is detected under // N.B. As soon as the rising edge of the clock is detected under
// the proper conditions, we propagate the incremented value to the // the proper conditions, we propagate the incremented value to the
// output pins. We do not wait until the next rising edge of the // output pins. We do not wait until the next rising edge of the
// clock. // clock.
always @(posedge clk) begin always @(posedge clk) begin
if (~n_clr) outvec <= 0; if (~n_clr)
; // Nothing to be done.
else if (~n_load) outvec <= loadvec; else if (~n_load) outvec <= loadvec;
else if (enp & ent) else if (enp & ent)
outvec <= outvec + 1; outvec <= outvec + 1;

View File

@ -4,16 +4,106 @@
`include "test_stdlogic.v" `include "test_stdlogic.v"
module test_palcl();
wire vcc, gnd;
reg n_res;
reg clock;
reg simclk;
wire sysclk, pclk, p0q1, clkscc, p0q2, vclk, q3, q4;
reg e, keyclk;
reg [23:0] a;
reg n_as, n_uds, n_lds;
wire n_dtack;
reg r_n_w;
wire [15:0] d;
wire casl, cash, ras, we;
wire [9:0] ra;
wire [15:0] rdq;
reg n_intscc, n_intvia;
wire n_ipl0;
wire n_ramen, n_romen, n_csiwm, n_sccrd, n_cescc, n_vpa;
wire viapb6;
reg ovlay;
wire viacb1;
reg n_sndpg2, n_vidpg2;
wire n_vsync, n_hsync, vid;
assign vcc = 1;
assign gnd = 0;
palcl u0_palcl(simclk, vcc, gnd, n_res, clock,
sysclk, pclk, p0q1, clkscc, p0q2, vclk, q3, q4,
e, keyclk,
a[23], a[22], a[21], a[20], a[19], a[18], a[17], a[16],
a[15], a[14], a[13], a[12], a[11], a[10], a[9],
a[8], a[7], a[6], a[5], a[4], a[3], a[2], a[1],
n_as, n_uds, n_lds, n_dtack, r_n_w,
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15],
casl, cash, ras, we,
ra[0], ra[1], ra[2], ra[3], ra[4], ra[5], ra[6], ra[7],
ra[8], ra[9],
rdq[0], rdq[1], rdq[2], rdq[3], rdq[4], rdq[5], rdq[6],
rdq[7], rdq[8], rdq[9], rdq[10], rdq[11], rdq[12], rdq[13],
rdq[14], rdq[15],
n_intscc, n_intvia, n_ipl0,
n_ramen, n_romen, n_csiwm, n_sccrd, n_cescc, n_vpa,
viapb6, ovlay, viacb1, n_sndpg2, n_vidpg2,
n_vsync, n_hsync, vid);
// Trigger RESET at beginning of simulation. Make sure there is an
// initial falling edge.
initial begin
n_res = 1;
#2 n_res = 0;
#18 n_res = 1;
end
// Initialize clock.
initial begin
clock = 0;
simclk = 0;
e = 0;
keyclk = 0;
end
// 64 unit clock cycle (~16MHz).
always
#32 clock = ~clock;
// ~1MHz 6800 E clock
always begin
#768 e = 1; // 6 CPU clocks low
#512 e = 0; // 4 CPU clocks high
end
// Sub-cycle simulator clock triggers as fast as possible.
always
#1 simclk = ~simclk;
// Initialize all other control inputs.
initial begin
a <= 0;
n_as <= 1; n_uds <= 1; n_lds <= 1; r_n_w <= 1;
n_intscc <= 1; n_intvia <= 1; ovlay <= 1;
n_sndpg2 <= 1; n_vidpg2 <= 1;
end
endmodule
module test_mac128pal(); module test_mac128pal();
// Instantiate individual test modules. // Instantiate individual test modules.
test_ls161 tu0(); test_ls161 tu0();
test_ls245 tu1(); test_ls245 tu1();
test_palcl tu2();
// Perform the remainder of global configuration here. // Perform the remainder of global configuration here.
// Set simulation time limit. // Set simulation time limit.
initial begin initial begin
#480 $finish; #480000 $finish;
end end
// We can use `$display()` for printf-style messages and implement // We can use `$display()` for printf-style messages and implement