From c490406c817f60d0792d9deab731aed71933628a Mon Sep 17 00:00:00 2001 From: Andrew Makousky Date: Wed, 25 Nov 2020 15:46:50 -0600 Subject: [PATCH] BBU: More analysis and insight. --- hardware/fpga/bbu/bbu.v | 4 + hardware/fpga/bbu/mac128pal.v | 277 ++++++++++++++++++----------- hardware/fpga/bbu/stdlogic.v | 8 +- hardware/fpga/bbu/test_mac128pal.v | 92 +++++++++- 4 files changed, 277 insertions(+), 104 deletions(-) diff --git a/hardware/fpga/bbu/bbu.v b/hardware/fpga/bbu/bbu.v index 28caec3..ab8098f 100644 --- a/hardware/fpga/bbu/bbu.v +++ b/hardware/fpga/bbu/bbu.v @@ -1496,6 +1496,10 @@ module avtimers (); // point to ponder, this is an area of improvement where a // 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 wire [23:0] snddsk_main_addr; // Address of main sound/disk buffer diff --git a/hardware/fpga/bbu/mac128pal.v b/hardware/fpga/bbu/mac128pal.v index 3283a7f..716bcd0 100644 --- a/hardware/fpga/bbu/mac128pal.v +++ b/hardware/fpga/bbu/mac128pal.v @@ -40,9 +40,10 @@ `include "common.vh" // 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); - input `virtwire simclk; + input `virtwire simclk, n_res; input wire clk; input wire sysclk, pclk, s1, ramen, romen, as, uds, lds; `power wire gnd; @@ -52,6 +53,14 @@ module tsm(simclk, clk, sysclk, pclk, s1, ramen, romen, as, uds, lds, gnd, output `simwire s0, dtack; `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. always @(posedge simclk) begin 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 & ~cash & sysclk | 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); - dtack <= ~(~romen // se a ROM for de 250 nS ou SCC ou IWM - | ~ras & ~ramen & ~s1 // garante que vai ser reconhecido na descida de `pclk` no estado `s5` - | ~as & ~dtack & ramen // espera `as` subir para desativar - | ~as & ~dtack & ~s1); // mas evite ciclas de video (WE) + dtack <= ~(~romen // if the ROM is 250 nS or SCC or IWM + | ~ras & ~ramen & ~s1 // guarantees that it will be recognized on the falling edge of `pclk` in state `s5` + | ~as & ~dtack & ramen // expects `as` to rise for disable + | ~as & ~dtack & ~s1); // but avoid video cycles (WE) end // Simulate registered logic. always @(posedge clk) begin ras <= ~(~pclk & q1 & s1 // video 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 | ~vclk & ~pclk @@ -95,10 +104,11 @@ endmodule // cas of sound: pup|pup|pup|spg|pup|spg|spg|spg|3q1 // 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, reslin, resnyb, vcc); - input `virtwire simclk; + input `virtwire simclk, n_res; input wire sysclk; input wire p2io1, l28, va4, p0q2, vclk, va3, va2, va1; `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; `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. always @(posedge simclk) begin end // Simulate registered logic. 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 & ~l28); - hsync <= ~(viapb6 & va4 & ~va3 & ~va2 & va1 // comec,a em29 (VA5) + hsync <= ~(viapb6 & va4 & ~va3 & ~va2 & va1 // begins in 29 (VA5) | /*~ ???*/resnyb - | ~hsync & viapb6); // termina em 0F + | ~hsync & viapb6); // ends in 0F s1 <= ~(~p0q2 // 0 for processor and 1 for video | ~vclk | ~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 | va4 & ~va3 & ~va2 | va4 & ~va3 & va2 & ~va1)); @@ -131,10 +148,10 @@ module lag(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1, | ~hsync & ~viapb6 | resnyb & ~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 - reslin <= ~(0); // ??? tentamos gerar linha 370 - resnyb <= ~(vclk // incrementa VA5:VA14 em 0F e 2B + reslin <= ~(0); // ??? try to generate line 370 + resnyb <= ~(vclk // increment VA5:VA14 in 0F and 2B | viapb6 // ??? | va1 | va2 @@ -146,37 +163,45 @@ module lag(simclk, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1, end endmodule -// 32 ciclas atiuas par linha - UA6..UA1 = 0 to 1F -// 1 ciclos de som/pwm = 2B -// 11 ciclos de retrac,o = 20 to 2A +// 32 active cycles for line - UA6..UA1 = 0 to 1F +// 1 cycle for sound/PWM = 2B +// 11 cycles for retrace = 20 to 2A -// 342 linhas ativas - VA6..VA14 = 010011100 to 111110001 -// 28 linhas de retrac,o = 010000000 to 010011011 +// 342 active lines - VA6..VA14 = 010011100 to 111110001 +// 28 retrace lines = 010000000 to 010011011 // 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); - input `virtwire simclk; + input `virtwire simclk, n_res; input wire va9, va8, va7, l15, va14, ovlay, a23, a22, a21; `power wire gnd; input wire as; output `simwire csiwm, rd, cescc, vpa, romen, ramen, io1, l28; `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. always @(posedge simclk) begin csiwm <= ~(a23 & a22 & ~a21 & ~as); // DFE1FF rd <= ~(a23 & ~a22 & ~a21 & ~as); // 9FFFF8 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 | ~a23 & ~a22 & ~a21 & ~as & ovlay // (and 000000 with `ovlay`) | 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 | ~a23 & a22 & a21 & ~as & ovlay); // (600000 with `ovlay`) 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 & ~va8 | ~l28 & ~va7); @@ -184,9 +209,10 @@ module bmu1(simclk, va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd, endmodule // 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); - input `virtwire simclk; + input `virtwire simclk, n_res; input wire sysclk; input wire ramen, romen, va10, va11, va12, va13, va14, rw; `power wire gnd; @@ -198,28 +224,37 @@ module bmu0(simclk, sysclk, ramen, romen, va10, va11, va12, va13, va14, rw, input wire servid, dtack; `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. always @(posedge simclk) begin g244 <= ~(~ramen & rw | ~g244 & ~ramen); 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 // Simulate registered logic. always @(posedge sysclk) begin ava14 <= ~(~va14 & ~va13); // + 1 - l15 <= ~(~va14 & ~va13 & ~va12 & ~va11 & ~va10 // n~ao passamos da linha 15 - | va14 & ~va13 & va12 & va11 & va10); // passamos de 368 - vid <= ~(servid); // aqui estamos invertendo: blanking est'a em `vshft` + l15 <= ~(~va14 & ~va13 & ~va12 & ~va11 & ~va10 // we haven't passed line 15 + | va14 & ~va13 & va12 & va11 & va10); // passed by 368 + vid <= ~(servid); // here we invert: blanking is in `vshft` ava13 <= ~(va13); // + 1 end endmodule // 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); - input `virtwire simclk; + input `virtwire simclk, n_res; input wire sysclk; input wire vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia; `power wire gnd; @@ -229,11 +264,20 @@ module tsg(simclk, sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia, output `simwire ipl0; `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. always @(posedge simclk) begin ipl0 <= ~intscc | intvia; // CORRECTION // 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 // Simulate registered logic. @@ -244,26 +288,42 @@ module tsg(simclk, sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia, | clkscc & ~pclk & ~q3 | clkscc & ~pclk & vclk | ~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 - pclk <= ~(pclk); // divide SYSCLK por 2 (8MHz) + pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz) q3 <= ~(~vclk); // `sysclk` / 16 q4 <= ~(q4 & q3 & ~vclk // `sysclk` / 32 - | ~q4 & ~q3 // } J p/gerar CLKSCC + | ~q4 & ~q3 // } J for generating CLKSCC | ~q4 & vclk); end 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 standard logic chips that are found on the Macintosh Main Logic Board. This is where we implement the modules. */ `include "stdlogic.v" // Wire that PAL cluster together, along with supporting standard -// logic chip. Here, we try to better indicate active high and active -// low because we also need to stick in a hex inverter chip. -module palcl(); +// logic chips. Here, we try to better indicate active high and +// active low because we also need to stick in a hex inverter chip. +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; `power wire vcc; `power wire gnd; @@ -272,23 +332,12 @@ module palcl(); // Clocks // 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 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 - 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, a8, a7, a6, a5, a4, a3, a2, a1; // not used: a18 @@ -298,27 +347,37 @@ module palcl(); inout wire d0, d1, d2, d3, d4, d5, d6, d7, 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 output wire casl, cash, ras, we; output wire ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra7, ra8, ra9; inout wire rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, rdq6, rdq7, 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 - wire n_vshft, n_snddma, servid; + wire n_vshft, n_snddma, n_servid; // Address multiplexer signals? wire s0, s1, l28, l15, n_245oe; @@ -331,41 +390,54 @@ module palcl(); wire p2io1, q6; // 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 // 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 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 - wire l13, l12; // ??? - wire n_sndpg2; // ??? - wire n_vidpg2; // ??? // TODO FIXME! We're not using assign correctly! `assign` implies // diode isolation between separate nets. We want to merge // multiple names together for the same net. // N.B. on PCB, use c8mf for high-frequency signal - // filter/conditioning. + // filter/conditioning, we add a resistor. assign c8mf = pclk; assign c16mf = sysclk; 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 - Macintosh is because the PALs do not have a RESET pin. It is - the logic designer's discretion to implement one explicitly, of - they could forgo it to allow for more I/O pins. Hence the - motivation to use software phase correction instead. */ + Macintosh 128k/512k/Plus is because the PALs do not have a RESET + pin. It is the logic designer's discretion to implement one + explicitly, of they could forgo it to allow for more I/O pins. + Hence the motivation to use software phase correction + instead. */ // Inverters and 16MHz clock buffer 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); // Dual video shift registers 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, - s5, rdq4, rdq5, rdq6, vmsh, rdq7, n_ldps, vcc); + s5, rdq4, rdq5, rdq6, vmsh, rdq7, n_vshft, vcc); // Dual RAM data bus transceivers 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); @@ -388,38 +460,39 @@ module palcl(); n_245oe, vcc); // RAM RA8/RA9 row/column video/CPU address multiplexer 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 ls393 u1f(vclk, resnyb, va1, va2, va3, va4, gnd, va8, va7, va6, va5, reslin, resnyb, vcc); 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 - 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); - 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); 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, - 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, - 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, - 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); - 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, n_snddma, reslin, 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); - 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, - servid, n_dtack, vcc); - tsg pal4(simclk, sysclk, n_vpa, a19, vclk, p0q1, e, keyclk, n_intscc, + n_servid, n_dtack, vcc); + 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, pclk, n_ipl0, vcc); diff --git a/hardware/fpga/bbu/stdlogic.v b/hardware/fpga/bbu/stdlogic.v index ed66bb4..293fca4 100644 --- a/hardware/fpga/bbu/stdlogic.v +++ b/hardware/fpga/bbu/stdlogic.v @@ -143,12 +143,18 @@ module ls161(n_clr, clk, a, b, c, d, enp, gnd, assign rco = (outvec == 4'hf); 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 // the proper conditions, we propagate the incremented value to the // output pins. We do not wait until the next rising edge of the // clock. always @(posedge clk) begin - if (~n_clr) outvec <= 0; + if (~n_clr) + ; // Nothing to be done. else if (~n_load) outvec <= loadvec; else if (enp & ent) outvec <= outvec + 1; diff --git a/hardware/fpga/bbu/test_mac128pal.v b/hardware/fpga/bbu/test_mac128pal.v index 14401b1..66b5782 100644 --- a/hardware/fpga/bbu/test_mac128pal.v +++ b/hardware/fpga/bbu/test_mac128pal.v @@ -4,16 +4,106 @@ `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(); // Instantiate individual test modules. test_ls161 tu0(); test_ls245 tu1(); + test_palcl tu2(); // Perform the remainder of global configuration here. // Set simulation time limit. initial begin - #480 $finish; + #480000 $finish; end // We can use `$display()` for printf-style messages and implement