2020-11-25 07:05:48 +00:00
|
|
|
/* Implementation of Macintosh 128k/512k PALs in Verilog,
|
|
|
|
mainly to assist verification of the Macintosh SE BBU. They are
|
|
|
|
not identical, of course, but this should at least be helpful is
|
|
|
|
spotting significant flaws.
|
|
|
|
|
|
|
|
Note that the signal names use here are the same as used in the
|
|
|
|
Unitron Macintosh clone's reverse engineering documentation. Many
|
|
|
|
of the signals are active low but not indicated here, for now.
|
|
|
|
|
|
|
|
Written in 2020 by Andrew Makousky
|
|
|
|
|
|
|
|
Public Domain Dedication:
|
|
|
|
|
|
|
|
To the extent possible under law, the author(s) have dedicated all
|
|
|
|
copyright and related and neighboring rights to this software to
|
|
|
|
the public domain worldwide. This software is distributed without
|
|
|
|
any warranty.
|
|
|
|
|
|
|
|
You should have received a copy of the CC0 Public Domain Dedication
|
|
|
|
along with this software. If not, see
|
|
|
|
<http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Note: All arguments are listed in the order of the pinout of each
|
|
|
|
PAL chip.
|
|
|
|
|
|
|
|
Another point, our cheap and easy way to hand self-referential PAL
|
|
|
|
logic equations is to simply treat them as registered sequential
|
|
|
|
logic equations and use enough simulation sub-cycles on them for
|
|
|
|
them to reach settle time. `simclk` controls these sub-cycles.
|
|
|
|
|
|
|
|
Also note, PAL registers do not have a deterministic
|
|
|
|
initialization, hence the absence of a RESET signal.
|
|
|
|
*/
|
|
|
|
|
|
|
|
`ifndef MAC128PAL_V
|
|
|
|
`define MAC128PAL_V
|
|
|
|
|
|
|
|
`include "common.vh"
|
|
|
|
|
|
|
|
// PAL0-16R4: Timing State Machine
|
2020-11-25 21:46:50 +00:00
|
|
|
module tsm(simclk, n_res,
|
|
|
|
clk, sysclk, pclk, s1, ramen, romen, as, uds, lds, gnd,
|
2020-11-25 07:05:48 +00:00
|
|
|
oe1, casl, cash, ras, vclk, q2, q1, s0, dtack, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
input `virtwire simclk, n_res;
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire clk;
|
|
|
|
input wire sysclk, pclk, s1, ramen, romen, as, uds, lds;
|
|
|
|
`power wire gnd;
|
|
|
|
input wire oe1;
|
2020-12-27 21:52:15 +00:00
|
|
|
output wire casl, cash;
|
2020-11-25 07:05:48 +00:00
|
|
|
output reg ras, vclk, q2, q1;
|
2020-12-27 21:52:15 +00:00
|
|
|
output wire s0, dtack;
|
2020-11-25 07:05:48 +00:00
|
|
|
`power wire vcc;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// We must implement RESET for simulation or else this will never
|
|
|
|
// stabilize.
|
|
|
|
always @(negedge n_res) begin
|
2020-12-27 21:52:15 +00:00
|
|
|
// casl = 1; cash = 1; s0 = 1; dtack = 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
|
2020-11-28 22:30:45 +00:00
|
|
|
ras <= 1; vclk <= 1; q2 <= 1; q1 <= 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
end
|
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// Simulate combinatorial logic.
|
|
|
|
assign casl
|
|
|
|
= ~(~s0 & s1 & sysclk // video
|
|
|
|
| ~s0 & ~ramen & ~lds // processor
|
|
|
|
| ~s0 & ~casl & sysclk
|
|
|
|
| pclk & ~casl);
|
|
|
|
assign cash
|
|
|
|
= ~(~s0 & s1 & sysclk // video
|
|
|
|
| ~s0 & ~ramen & ~uds // processor
|
|
|
|
| ~s0 & ~cash & sysclk
|
|
|
|
| pclk & ~cash);
|
|
|
|
assign s0
|
|
|
|
= ~(~ras & ~sysclk // 0 for `cas` and 1 for `ras` (counting with the delay of the PAL)
|
|
|
|
| ~ras & ~s0);
|
|
|
|
assign 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)
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// Simulate registered logic.
|
2020-12-27 15:19:35 +00:00
|
|
|
always @(posedge clk) begin
|
2020-11-28 22:30:45 +00:00
|
|
|
if (n_res) begin
|
2020-12-27 15:19:35 +00:00
|
|
|
ras <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(~pclk & q1 & s1 // video cycle
|
|
|
|
| ~pclk & q1 & ~ramen & dtack // processor cycle
|
|
|
|
| pclk & ~ras); // any other cycle
|
2020-12-27 15:19:35 +00:00
|
|
|
vclk <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(~q1 & pclk & q2 & vclk // divide by 8 (1MHz)
|
|
|
|
| ~vclk & q1
|
|
|
|
| ~vclk & ~pclk
|
|
|
|
| ~vclk & ~q2);
|
2020-12-27 15:19:35 +00:00
|
|
|
q1 <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(~pclk & q1
|
|
|
|
| pclk & ~q1); // divide `pclk` by 2 (4MHz)
|
2020-12-27 15:19:35 +00:00
|
|
|
q2 <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(~q1 & pclk & q2 // divide by 4 (2MHz)
|
|
|
|
| ~q2 & q1
|
|
|
|
| ~q2 & ~pclk);
|
|
|
|
end
|
2020-11-25 07:05:48 +00:00
|
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
// ras of processor: a16| a8| a7| a6| a5| a4| a3| a2| a1
|
|
|
|
// cas of processor: a17|a16|a15|a14|a13|a12|a11|a10| a9
|
|
|
|
// ras of video: pup| v8| v7| v6| v5| v4| v3| v2| v1
|
|
|
|
// cas of video: pup|pup|vpg|3q1|3q4|v12|v11|v10| v9
|
|
|
|
// ras of sound: pup|3q4|v12|v11|v10|?v8|?v9| v7| v6
|
|
|
|
// cas of sound: pup|pup|pup|spg|pup|spg|spg|spg|3q1
|
|
|
|
|
|
|
|
// PAL1-16R8: Linear Address Generator
|
2020-11-25 21:46:50 +00:00
|
|
|
module lag(simclk, n_res,
|
|
|
|
sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
|
2020-11-25 07:05:48 +00:00
|
|
|
gnd, oe2, vshft, vsync, hsync, s1, viapb6, snddma,
|
|
|
|
reslin, resnyb, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
input `virtwire simclk, n_res;
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire sysclk;
|
|
|
|
input wire p2io1, l28, va4, p0q2, vclk, va3, va2, va1;
|
|
|
|
`power wire gnd;
|
|
|
|
input wire oe2;
|
|
|
|
output reg vshft, vsync, hsync, s1, viapb6, snddma, reslin, resnyb;
|
|
|
|
`power wire vcc;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// We must implement RESET for simulation or else this will never
|
|
|
|
// stabilize.
|
|
|
|
always @(negedge n_res) begin
|
2020-11-28 22:30:45 +00:00
|
|
|
vshft <= 1; vsync <= 1; hsync <= 1; s1 <= 1; viapb6 <= 1;
|
|
|
|
snddma <= 1; reslin <= 1; resnyb <= 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
end
|
|
|
|
|
2020-11-25 07:05:48 +00:00
|
|
|
// Simulate registered logic.
|
2020-12-27 15:19:35 +00:00
|
|
|
always @(posedge sysclk) begin
|
2020-11-28 22:30:45 +00:00
|
|
|
if (n_res) begin
|
2020-12-27 15:19:35 +00:00
|
|
|
vshft <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(s1 & ~vclk & snddma); // one pulse on the falling edge of `vclk`
|
2020-12-27 15:19:35 +00:00
|
|
|
vsync <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(reslin
|
|
|
|
| ~vsync & ~l28);
|
2020-12-27 15:19:35 +00:00
|
|
|
// hsync <=
|
2020-11-28 22:30:45 +00:00
|
|
|
// ~(viapb6 & va4 & ~va3 & ~va2 & va1 // begins in 29 (VA5)
|
|
|
|
// | /*~ ???*/resnyb
|
|
|
|
// | ~hsync & viapb6); // ends in 0F
|
2020-12-27 15:19:35 +00:00
|
|
|
// hsync <=
|
|
|
|
// ~(~viapb6 & ~va4 & ~va3 & va2 & va1 // begins in 29 (VA5)
|
|
|
|
// | ~hsync & ~va4
|
|
|
|
// | ~hsync & ~viapb6); // ends in 0F
|
|
|
|
// TODO FIXME: This is incorrect, temporary equations in order
|
|
|
|
// to get at least partial behavior for analysis.
|
|
|
|
// TODO FIXME: We trigger hsync a bit too soon at the end of the
|
|
|
|
// scanline. And, we release it too soon at the beginning.
|
|
|
|
hsync <=
|
2020-12-28 00:43:37 +00:00
|
|
|
~(viapb6 /* & ~p0q2 & s1 */ & ~vclk & va1 & va2 & va3 & va4 /* FIXME & ~va1 & ~va2 & ~va3 & ~va4 */
|
2020-11-28 22:30:45 +00:00
|
|
|
| ~hsync & ~va4
|
2020-12-27 15:19:35 +00:00
|
|
|
| ~hsync & ~va3
|
|
|
|
| ~hsync & va2
|
|
|
|
| ~hsync & va1);
|
|
|
|
s1 <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(~p0q2 // 0 for processor and 1 for video
|
|
|
|
| ~vclk
|
|
|
|
| ~vsync & hsync
|
2020-12-27 15:19:35 +00:00
|
|
|
| ~vsync & viapb6 // vertical retrace only has sound cycles
|
2020-12-28 04:25:03 +00:00
|
|
|
| ~vsync & ~viapb6 & ~hsync & va4 & va3 & va2 & va1
|
|
|
|
| ~viapb6 & ~hsync & ~va4
|
|
|
|
| ~viapb6 & ~hsync & va4 & ~va3 & ~va2
|
|
|
|
| ~viapb6 & ~hsync & va4 & ~va3 & va2 & ~va1);
|
2020-12-27 15:19:35 +00:00
|
|
|
// viapb6 <=
|
2020-11-28 22:30:45 +00:00
|
|
|
// ~(~hsync & resnyb // 1 indicates horizontal retrace (pseudo VA6)
|
|
|
|
// | va1 & ~viapb6
|
|
|
|
// | va2 & ~viapb6
|
|
|
|
// | ~hsync & ~viapb6
|
|
|
|
// | resnyb & ~viapb6
|
|
|
|
// | vshft & ~viapb6);
|
2020-12-27 15:19:35 +00:00
|
|
|
// viapb6 <=
|
|
|
|
// ~(hsync & ~va4 & ~va3 & va2 & va1 // 1 indicates horizontal retrace (pseudo VA6)
|
|
|
|
// | ~viapb6 & snddma
|
|
|
|
// | ~viapb6 & vclk);
|
|
|
|
// TODO FIXME: This is incorrect, temporary equations in order
|
|
|
|
// to get at least partial behavior for analysis.
|
2020-12-27 21:52:15 +00:00
|
|
|
// TODO FIXME: Why this latches up and is broken, we should not
|
|
|
|
// use memory access to clock this to one sensitivity cycle.
|
2020-12-28 00:43:37 +00:00
|
|
|
|
|
|
|
// TODO FIXME: Okay, this is how to do it. The trick is within
|
|
|
|
// "self-latching" logic equations. When another clock period
|
|
|
|
// remains the same, we use self-latching logic equations, but
|
|
|
|
// they loose effect... okay, I don't know what I'm talking
|
|
|
|
// about.
|
2020-12-27 15:19:35 +00:00
|
|
|
viapb6 <=
|
|
|
|
~(~hsync // 1 indicates horizontal retrace (pseudo VA6)
|
2020-12-28 00:43:37 +00:00
|
|
|
/* | ~viapb6 & p0q2
|
|
|
|
| ~viapb6 & ~s1 */
|
|
|
|
| ~viapb6 & ~vclk
|
|
|
|
| ~viapb6 & ~va1 // TODO FIXME wrong phase
|
|
|
|
| ~viapb6 & ~va2
|
|
|
|
| ~viapb6 & ~va3
|
|
|
|
| ~viapb6 & ~va4);
|
2020-12-27 15:19:35 +00:00
|
|
|
// TODO FIXME HACK: Previously viapb6 but negated for testing.
|
|
|
|
snddma <=
|
|
|
|
~(~viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 in this output
|
2020-11-28 22:30:45 +00:00
|
|
|
| ~snddma & vclk); // ... indicates sound cycle
|
2020-12-27 15:19:35 +00:00
|
|
|
// TODO FIXME HACK: Previously ~viapb6 but negated for testing.
|
|
|
|
reslin <= // try to generate line 370
|
2020-11-28 22:30:45 +00:00
|
|
|
~(l28
|
|
|
|
| ~vsync
|
2020-12-28 04:25:03 +00:00
|
|
|
| ~hsync // HACKED previously hsync, but negated for testing.
|
2020-12-27 15:19:35 +00:00
|
|
|
| viapb6
|
|
|
|
| ~vclk);
|
|
|
|
// N.B. Primary conceptual equation:
|
|
|
|
// resnyb <=
|
|
|
|
// ((~viapb6 & hsync & ~va4 & ~va3 & ~va2 & ~va1)
|
|
|
|
// | (~viapb6 & ~hsync & va4 & va3 & ~va2 & ~va1));
|
|
|
|
// TODO FIXME HACK: Possibly incorrect interpretation of viapb6
|
|
|
|
// with hsync.
|
|
|
|
resnyb <=
|
2020-12-28 04:25:03 +00:00
|
|
|
~(vclk // increment VA5:VA14 in 0F and 2B
|
|
|
|
| // viapb6 // TODO FIXME HACK PHASE
|
|
|
|
| va1
|
|
|
|
| va2
|
|
|
|
| hsync & va4
|
|
|
|
| hsync & va3
|
|
|
|
| ~hsync & ~va4
|
|
|
|
| ~hsync & ~va3
|
|
|
|
| ~va4 & va3
|
|
|
|
| va4 & ~va3);
|
2020-11-28 22:30:45 +00:00
|
|
|
end
|
2020-11-25 07:05:48 +00:00
|
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
2020-12-27 15:19:35 +00:00
|
|
|
/*
|
|
|
|
This LAG doesn't work correctly, here's how it is supposed to work.
|
|
|
|
|
|
|
|
1. Count video addresses to 32. During this count, generate resnyb
|
|
|
|
every time we need a carry.
|
|
|
|
|
|
|
|
2. Once we reach 32, that's 512 pixels, one scanline. Now, we assert
|
|
|
|
the *HSYNC signal. But please note, at this point we do **not**
|
|
|
|
generate resnyb for the carry at 32, instead we let that counter
|
|
|
|
wrap around to zero without a carry.
|
|
|
|
|
|
|
|
3. When the *HSYNC signal is asserted, we only count to 12. That's
|
|
|
|
192 pixels for horizontal blanking. Just when we're about to reach
|
|
|
|
the end, we assert the *SNDDMA signal. That's when we fetch the
|
|
|
|
sound sample, at the very end of horizontal blanking, not the very
|
|
|
|
beginning.
|
|
|
|
|
|
|
|
Finally, we assert resnyb to clear the counter and finally
|
|
|
|
propagate the carry to the next video address.
|
|
|
|
|
|
|
|
At the very end of vertical blanking, we assert *RESLIN to clear the
|
|
|
|
video address counter back to zero. Until then, we keep counting
|
|
|
|
positive to keep track of the vertical blanking time.
|
|
|
|
|
|
|
|
But, to implement this... it's tricky because va5 and va6 are not
|
|
|
|
connected to any PAL. How do we generate the signals then? We can
|
|
|
|
otherwise only count to 16, we need to get to 32.
|
|
|
|
|
|
|
|
Okay, I think I've got it figured out. VIAPB6 is a little white lie,
|
|
|
|
it's not the actual horizontal blanking signal, it's a prep signal
|
|
|
|
before the horizontal blanking actually occurs. But, nevertheless, it
|
|
|
|
is almost the same thing, 16 cycles at 16MHz rather than 12 cycles.
|
|
|
|
For the 8 MHz CPU, it pretty much looks like the same thing. And
|
|
|
|
that's where we hide the additional bit of memory we need.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// 32 active cycles for line - UA6..UA1 = 0 to 1F
|
|
|
|
// 1 cycle for sound/PWM = 2B
|
|
|
|
// 11 cycles for retrace = 20 to 2A
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// 342 active lines - VA6..VA14 = 010011100 to 111110001
|
|
|
|
// 28 retrace lines = 010000000 to 010011011
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// PAL2-16L8: Bus Management Unit 1
|
2020-11-25 21:46:50 +00:00
|
|
|
module bmu1(simclk, n_res,
|
|
|
|
va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd,
|
2020-11-25 07:05:48 +00:00
|
|
|
as, csiwm, rd, cescc, vpa, romen, ramen, io1, l28, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
input `virtwire simclk, n_res;
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire va9, va8, va7, l15, va14, ovlay, a23, a22, a21;
|
|
|
|
`power wire gnd;
|
|
|
|
input wire as;
|
2020-12-27 21:52:15 +00:00
|
|
|
output wire csiwm, rd, cescc, vpa, romen, ramen, io1, l28;
|
2020-11-25 07:05:48 +00:00
|
|
|
`power wire vcc;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// We must implement RESET for simulation or else this will never
|
|
|
|
// stabilize.
|
|
|
|
always @(negedge n_res) begin
|
2020-12-27 21:52:15 +00:00
|
|
|
// csiwm = 1; rd = 1; cescc = 1; vpa = 1; romen = 1;
|
|
|
|
// ramen = 1; io1 = 1; l28 = 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
end
|
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// Simulate combinatorial logic.
|
|
|
|
assign csiwm
|
|
|
|
= ~(a23 & a22 & ~a21 & ~as); // DFE1FF
|
|
|
|
assign rd
|
|
|
|
= ~(a23 & ~a22 & ~a21 & ~as); // 9FFFF8
|
|
|
|
assign cescc
|
|
|
|
= ~(a23 & ~a22 & ~as); // 9FFFF8(R) or BFFFF9(W)
|
|
|
|
assign vpa
|
|
|
|
= ~(a23 & a22 & a21 & ~as); // above E00000 is synchronous
|
|
|
|
assign romen
|
|
|
|
= ~(~a23 & a22 & ~a21 & ~as // 400000
|
|
|
|
| ~a23 & ~a22 & ~a21 & ~as & ovlay // (and 000000 with `ovlay`)
|
|
|
|
| a23 & ~a22 & ~as
|
|
|
|
| a23 & ~a21 & ~as); // for generating DTACK (not accessing ROM: A20)
|
|
|
|
assign ramen
|
|
|
|
= ~(~a23 & ~a22 & ~a21 & ~as & ~ovlay // 000000
|
|
|
|
| ~a23 & a22 & a21 & ~as & ovlay); // (600000 with `ovlay`)
|
|
|
|
assign io1
|
2020-12-28 00:43:37 +00:00
|
|
|
= ~(~l15 & ~va9 & va8 & ~va7 // reached 368 or we don't pass line 26
|
|
|
|
| ~l28 & ~l15
|
|
|
|
| ~l28 & ~va9
|
|
|
|
| ~l28 & va8
|
|
|
|
| ~l28 & ~va7
|
|
|
|
| ~n_res); // SIMULATION ONLY: Else we never settle.
|
2020-12-27 21:52:15 +00:00
|
|
|
assign l28
|
|
|
|
= ~(~l15 & ~va9 & ~va8 & va7 // reached 370 or we don't pass line 28
|
|
|
|
| ~l28 & ~l15
|
|
|
|
| ~l28 & ~va9
|
|
|
|
| ~l28 & ~va8
|
|
|
|
| ~l28 & va7
|
|
|
|
| ~n_res); // SIMULATION ONLY: Else we never settle.
|
2020-11-25 07:05:48 +00:00
|
|
|
endmodule
|
|
|
|
|
|
|
|
// PAL3-16R4: Bus Management Unit 0
|
2020-11-25 21:46:50 +00:00
|
|
|
module bmu0(simclk, n_res,
|
|
|
|
sysclk, ramen, romen, va10, va11, va12, va13, va14, rw,
|
2020-11-25 07:05:48 +00:00
|
|
|
gnd, oe1, g244, we, ava14, l15, vid, ava13, servid, dtack, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
input `virtwire simclk, n_res;
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire sysclk;
|
|
|
|
input wire ramen, romen, va10, va11, va12, va13, va14, rw;
|
|
|
|
`power wire gnd;
|
|
|
|
input wire oe1;
|
2020-12-27 21:52:15 +00:00
|
|
|
output wire g244, we;
|
2020-11-25 07:05:48 +00:00
|
|
|
output reg ava14, l15, vid, ava13;
|
|
|
|
// N.B. Although this is nominally an output we can treat it as an
|
|
|
|
// input?
|
|
|
|
input wire servid, dtack;
|
|
|
|
`power wire vcc;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// We must implement RESET for simulation or else this will never
|
|
|
|
// stabilize.
|
|
|
|
always @(negedge n_res) begin
|
2020-12-27 21:52:15 +00:00
|
|
|
// g244 = 1; we = 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
|
2020-11-28 22:30:45 +00:00
|
|
|
ava14 <= 1; l15 <= 1; vid <= 1; ava13 <= 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
end
|
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// Simulate combinatorial logic.
|
|
|
|
assign g244
|
|
|
|
= ~(~ramen & rw
|
|
|
|
| ~g244 & ~ramen);
|
|
|
|
assign we
|
|
|
|
= ~(~ramen & ~rw
|
|
|
|
| ~we & ~dtack); // or `dtack` is shorter before the video cycle
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// Simulate registered logic.
|
2020-12-27 15:19:35 +00:00
|
|
|
always @(posedge sysclk) begin
|
2020-11-28 22:30:45 +00:00
|
|
|
if (n_res) begin
|
2020-12-27 15:19:35 +00:00
|
|
|
ava14 <= ~(~va14 & ~va13); // + 1
|
|
|
|
l15 <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(~va14 & ~va13 & ~va12 & ~va11 & ~va10 // we haven't passed line 15
|
|
|
|
| va14 & ~va13 & va12 & va11 & va10); // passed by 368
|
2020-12-27 15:19:35 +00:00
|
|
|
vid <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(servid); // here we invert: blanking is in `vshft`
|
2020-12-27 15:19:35 +00:00
|
|
|
ava13 <= ~(va13); // + 1
|
2020-11-28 22:30:45 +00:00
|
|
|
end
|
2020-11-25 07:05:48 +00:00
|
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
// PAL4-16R6: Timing Signal Generator
|
2020-11-25 21:46:50 +00:00
|
|
|
module tsg(simclk, n_res,
|
|
|
|
sysclk, vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia,
|
2020-11-25 07:05:48 +00:00
|
|
|
gnd, oe3, d0, q6, clkscc, q4, q3, viacb1, pclk, ipl0, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
input `virtwire simclk, n_res;
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire sysclk;
|
|
|
|
input wire vpa, a19, vclk, p0q1, e, keyclk, intscc, intvia;
|
|
|
|
`power wire gnd;
|
|
|
|
input wire oe3;
|
2020-12-27 21:52:15 +00:00
|
|
|
output wire d0;
|
2020-11-25 07:05:48 +00:00
|
|
|
output reg q6, clkscc, q4, q3, viacb1, pclk;
|
2020-12-27 21:52:15 +00:00
|
|
|
output wire ipl0;
|
2020-11-25 07:05:48 +00:00
|
|
|
`power wire vcc;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// We must implement RESET for simulation or else this will never
|
|
|
|
// stabilize.
|
|
|
|
always @(negedge n_res) begin
|
2020-12-27 21:52:15 +00:00
|
|
|
// d0 = 1; ipl0 = 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
|
2020-11-28 22:30:45 +00:00
|
|
|
q6 <= 1; clkscc <= 1; q4 <= 1; q3 <= 1; viacb1 <= 1;
|
|
|
|
pclk <= 1;
|
2020-11-25 21:46:50 +00:00
|
|
|
end
|
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// Simulate combinatorial logic.
|
|
|
|
assign ipl0
|
|
|
|
= ~intscc | intvia; // CORRECTION
|
|
|
|
// assign ipl0 = ~(0); // ??? /M nanda
|
|
|
|
assign d0
|
|
|
|
= ~(~vpa & ~a19 & e); // F00000 sample the phase with 0 /n e' + usado
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// Simulate registered logic.
|
2020-12-27 15:19:35 +00:00
|
|
|
always @(posedge sysclk) begin
|
2020-11-28 22:30:45 +00:00
|
|
|
if (n_res) begin
|
2020-11-25 07:05:48 +00:00
|
|
|
// TODO VERIFY: q6 missing?
|
2020-12-27 15:19:35 +00:00
|
|
|
q6 <= ~(0);
|
|
|
|
clkscc <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(clkscc & ~pclk & ~q4
|
|
|
|
| clkscc & ~pclk & ~q3
|
|
|
|
| clkscc & ~pclk & vclk
|
|
|
|
| ~clkscc & pclk
|
|
|
|
| ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
|
2020-12-27 15:19:35 +00:00
|
|
|
viacb1 <= ~(0); // ??? /M nanda
|
|
|
|
pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz)
|
|
|
|
q3 <= ~(~vclk); // `sysclk` / 16
|
|
|
|
q4 <=
|
2020-11-28 22:30:45 +00:00
|
|
|
~(q4 & q3 & ~vclk // `sysclk` / 32
|
|
|
|
| ~q4 & ~q3 // } J for generating CLKSCC
|
|
|
|
| ~q4 & vclk);
|
|
|
|
end
|
2020-11-25 07:05:48 +00:00
|
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
/* Now in order to fully implement the Macintosh's custom board
|
2020-11-25 07:05:48 +00:00
|
|
|
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
|
2020-11-25 21:46:50 +00:00
|
|
|
// 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);
|
2020-11-25 07:05:48 +00:00
|
|
|
input `virtwire simclk;
|
|
|
|
`power wire vcc;
|
|
|
|
`power wire gnd;
|
|
|
|
input wire n_res;
|
|
|
|
input wire n_sysclk; // 16MHz
|
|
|
|
|
|
|
|
// Clocks
|
|
|
|
// 8,4,3.686,2,1,1,0.5 MHz
|
2020-11-25 21:46:50 +00:00
|
|
|
output wire sysclk, pclk, p0q1, clkscc, p0q2, vclk, q3, q4;
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire e; // 6800 synchronous I/O "E" clock, ~1MHz
|
|
|
|
input wire keyclk;
|
|
|
|
|
|
|
|
// MC68000 CPU address signals
|
2020-11-25 21:46:50 +00:00
|
|
|
input wire a23, a22, a21, a20, a19, a18, a17, a16,
|
2020-11-25 12:04:07 +00:00
|
|
|
a15, a14, a13, a12, a11, a10, a9,
|
|
|
|
a8, a7, a6, a5, a4, a3, a2, a1;
|
|
|
|
// not used: a18
|
2020-11-25 07:05:48 +00:00
|
|
|
input wire n_as, n_uds, n_lds;
|
|
|
|
output wire n_dtack;
|
|
|
|
input wire r_n_w;
|
|
|
|
inout wire d0, d1, d2, d3, d4, d5, d6, d7,
|
|
|
|
d8, d9, d10, d11, d12, d13, d14, d15;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// 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;
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// Interrupt signals
|
|
|
|
input wire n_intscc, n_intvia;
|
|
|
|
output wire n_ipl0;
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// Chip enable signals
|
|
|
|
output wire n_ramen, n_romen, n_csiwm, n_sccrd, n_cescc, n_vpa;
|
|
|
|
|
2020-11-25 07:05:48 +00:00
|
|
|
// VIA signals
|
|
|
|
output wire viapb6; // horizontal blanking
|
|
|
|
input wire ovlay; // Boot-time overlay
|
|
|
|
output wire viacb1; // keyboard interrupt
|
2020-11-25 21:46:50 +00:00
|
|
|
input wire n_sndpg2; // VIA PA3
|
|
|
|
input wire n_vidpg2; // VIA PA6
|
2020-11-25 07:05:48 +00:00
|
|
|
// wire d0; // Video timing phase sense signal
|
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// Video control signals
|
|
|
|
output wire n_vsync, n_hsync, vid;
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
// 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;
|
2020-11-25 12:04:07 +00:00
|
|
|
// Internal video signals
|
2020-12-27 15:19:35 +00:00
|
|
|
wire vshft, n_snddma, n_servid;
|
2020-11-25 12:04:07 +00:00
|
|
|
|
2020-11-25 07:05:48 +00:00
|
|
|
// Address multiplexer signals?
|
2020-11-25 12:04:07 +00:00
|
|
|
wire s0, s1, l28, l15, n_245oe;
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// PAL chip-select and unknown "IO" signals
|
|
|
|
wire tsm_oe1, lag_oe2, bmu0_oe1, tsg_oe3;
|
|
|
|
|
|
|
|
// Internal PAL cluster use only, supports video
|
|
|
|
wire reslin, resnyb; // video counter controllers?
|
|
|
|
wire p2io1, q6;
|
|
|
|
|
|
|
|
// Wires to/from standard logic chips.
|
2020-11-25 21:46:50 +00:00
|
|
|
wire snddma, n_a20, n_sndres, sndres, n_snd, snd, wr, n_wr;
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// N.B.: *WR comes from IWM chip, WR goes to floppy drives. *A20
|
|
|
|
// goes to VIA.CS1. *SNDDMA comes from the LAG. *SYSCLK comes
|
2020-11-25 21:46:50 +00:00
|
|
|
// from the 16MHz crystal oscillator. SND comes from the dual PWM
|
|
|
|
// disk driver counters.
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// *DMALD is generated by ASG. It's very similar to how *LDPS is
|
|
|
|
// generated.
|
|
|
|
// n_dmald <=
|
|
|
|
// ~(s1 & ~vclk & ~n_snddma);
|
|
|
|
wire n_dmald;
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// u12f_tc is the carry propagation signal for the dual PWM sound
|
|
|
|
// counters.
|
2020-11-25 21:46:50 +00:00
|
|
|
wire c8mf, c16mf, c2m, u12f_tc, ram_r_n_w_f;
|
2020-11-25 07:05:48 +00:00
|
|
|
wire vmsh; // video mid-shift, connect two register chips together
|
|
|
|
|
2020-12-27 15:19:35 +00:00
|
|
|
// This is just a pull-up resistor, possibly connected to a RESET
|
|
|
|
// circuit.
|
|
|
|
wire s5;
|
2020-11-25 21:46:50 +00:00
|
|
|
|
|
|
|
// L12 => va13
|
|
|
|
// L13 => va14
|
|
|
|
// va12 => ava13
|
|
|
|
// va13 => ava14
|
2020-12-27 15:19:35 +00:00
|
|
|
// n_ldps => vshft
|
2020-11-25 21:46:50 +00:00
|
|
|
// VID/*u => s1
|
2020-11-25 12:04:07 +00:00
|
|
|
// tc => vclk
|
2020-11-25 07:05:48 +00:00
|
|
|
|
|
|
|
// 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
|
2020-11-25 21:46:50 +00:00
|
|
|
// filter/conditioning, we add a resistor.
|
2020-11-25 07:05:48 +00:00
|
|
|
assign c8mf = pclk;
|
|
|
|
assign c16mf = sysclk;
|
|
|
|
assign ram_r_n_w_f = we;
|
2020-11-25 21:46:50 +00:00
|
|
|
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;
|
2020-12-27 21:52:15 +00:00
|
|
|
// Pull-down resistor shared by TSG, ASG, and CAS (if present).
|
|
|
|
// TODO INVESTIGATE: Surely this is controlled by another switch
|
|
|
|
// related to the RAM data bus switches, otherwise D0 is
|
|
|
|
// unconditionally coerced for non-phase read accesses.
|
2020-11-25 21:46:50 +00:00
|
|
|
assign tsg_oe3 = gnd;
|
2020-12-27 15:19:35 +00:00
|
|
|
// S5: Pull-up resistor. TODO FIXME: Should this be controlled by
|
|
|
|
// another thing too?
|
2020-12-24 17:23:08 +00:00
|
|
|
assign s5 = vcc;
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-12-27 15:19:35 +00:00
|
|
|
// TODO FIXME: A1 - A13 are connected to a pull-up resistors bank
|
|
|
|
// RP1.
|
|
|
|
|
2020-11-25 07:05:48 +00:00
|
|
|
/* N.B. The reason why phase calibration is required in the
|
2020-11-25 21:46:50 +00:00
|
|
|
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. */
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-11-25 12:04:07 +00:00
|
|
|
// Inverters and 16MHz clock buffer
|
2020-11-25 07:05:48 +00:00
|
|
|
f04 u4d(n_sysclk, sysclk, n_snddma, snddma, a20, n_a20, gnd,
|
|
|
|
n_sndres, sndres, n_snd, snd, wr, n_wr, vcc);
|
2020-12-27 21:52:15 +00:00
|
|
|
// Dual PWM sound counters. The final carry-out is the PWM sound
|
|
|
|
// signal, and it is inverted and fed back to the sound counters to
|
|
|
|
// form a saturating counter.
|
2020-11-25 07:05:48 +00:00
|
|
|
ls161 u13e(n_sndres, c8mf, rdq12, rdq13, rdq14, rdq15, n_snd, gnd,
|
|
|
|
n_dmald, u12f_tc, , , , , snd, vcc);
|
|
|
|
ls161 u12f(n_sndres, c8mf, rdq8, rdq9, rdq10, rdq11, n_snd, gnd,
|
|
|
|
n_dmald, n_sndres, , , , , u12f_tc, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
// Dual video shift registers
|
2020-11-25 07:05:48 +00:00
|
|
|
ls166 u10f(vmsh, rdq8, rdq9, rdq10, rdq11, 1'b0, c16mf, gnd,
|
2020-12-27 15:19:35 +00:00
|
|
|
s5, rdq12, rdq13, rdq14, n_servid, rdq15, vshft, vcc);
|
2020-11-25 07:05:48 +00:00
|
|
|
ls166 u11f(s5, rdq0, rdq1, rdq2, rdq3, 1'b0, c16mf, gnd,
|
2020-12-27 15:19:35 +00:00
|
|
|
s5, rdq4, rdq5, rdq6, vmsh, rdq7, vshft, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
// Dual RAM data bus transceivers
|
2020-11-25 07:05:48 +00:00
|
|
|
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);
|
|
|
|
ls245 u10e(ram_r_n_w_f, rdq8, rdq9, rdq10, rdq11, rdq12, rdq13, rdq14,
|
|
|
|
rdq15, gnd, d15, d14, d13, d12, d11, d10, d9, d8,
|
|
|
|
n_245oe, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
// RAM RA8/RA9 row/column video/CPU address multiplexer
|
|
|
|
f253 u10g(snddma, s1, va9, s5, a9, a17, ra8, gnd,
|
2020-11-25 21:46:50 +00:00
|
|
|
ra9, a20, a19, s5, s5, c2m, 1'b0, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
// 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,
|
2020-11-25 21:46:50 +00:00
|
|
|
, , va14, va13, reslin, va12, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
// RAM row/column video/CPU address multiplexers
|
2020-11-25 21:46:50 +00:00
|
|
|
f257 u2f(c2m, s5, va6, ra0, n_snd, va7, ra1, gnd,
|
2020-11-25 12:04:07 +00:00
|
|
|
ra3/*???*/, va9, n_sndpg2, ra2, va8, n_sndpg2, n_snddma, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
f257 u2g(c2m, s5, va10, ra4, n_sndpg2, va11, ra5, gnd,
|
2020-11-25 12:04:07 +00:00
|
|
|
ra7, va13, s5, ra6, va12, s5, n_snddma, vcc);
|
|
|
|
f253 u3f(snddma, s1, va3, va11, a3, a11, ra2, gnd,
|
2020-11-25 21:46:50 +00:00
|
|
|
ra3, a12, a4, va12, va4, c2m, snddma, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
f253 u3g(snddma, s1, va5, va13, a5, a13, ra4, gnd,
|
2020-11-25 21:46:50 +00:00
|
|
|
ra5, a14, a6, va14, va6, c2m, snddma, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
f253 u4f(snddma, s1, va1, s5, a1, a9, ra0, gnd,
|
2020-11-25 21:46:50 +00:00
|
|
|
ra1, a10, a2, va10, va2, c2m, snddma, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
f253 u4g(snddma, s1, va7, n_vidpg2, a7, a15, ra6, gnd,
|
2020-11-25 21:46:50 +00:00
|
|
|
ra7, a16, a8, s5, va8, c2m, snddma, vcc);
|
2020-11-25 07:05:48 +00:00
|
|
|
|
2020-11-25 21:46:50 +00:00
|
|
|
tsm pal0(simclk, n_res, sysclk, sysclk, pclk, s1, n_ramen, n_romen, n_as, n_uds, n_lds,
|
2020-11-25 07:05:48 +00:00
|
|
|
gnd, tsm_oe1, casl, cash, ras, vclk, p0q2, p0q1, s0, n_dtack, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
lag pal1(simclk, n_res, sysclk, p2io1, l28, va4, p0q2, vclk, va3, va2, va1,
|
2020-12-27 15:19:35 +00:00
|
|
|
gnd, lag_oe2, vshft, n_vsync, n_hsync, s1, viapb6,
|
2020-11-25 07:05:48 +00:00
|
|
|
n_snddma, reslin,
|
|
|
|
resnyb, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
bmu1 pal2(simclk, n_res, va9, va8, va7, l15, va14, ovlay, a23, a22, a21, gnd,
|
2020-11-25 07:05:48 +00:00
|
|
|
n_as, n_csiwm, n_sccrd, n_cescc, n_vpa, n_romen, n_ramen, p2io1, l28, vcc);
|
2020-11-25 21:46:50 +00:00
|
|
|
bmu0 pal3(simclk, n_res, sysclk, n_ramen, n_romen, va10, va11, va12, va13, va14,
|
2020-11-25 12:04:07 +00:00
|
|
|
r_n_w, gnd, bmu0_oe1, n_245oe, we, ava14, l15, vid, ava13,
|
2020-11-25 21:46:50 +00:00
|
|
|
n_servid, n_dtack, vcc);
|
|
|
|
tsg pal4(simclk, n_res,
|
|
|
|
sysclk, n_vpa, a19, vclk, p0q1, e, keyclk, n_intscc,
|
2020-11-25 07:05:48 +00:00
|
|
|
n_intvia, gnd, tsg_oe3, d0, q6, clkscc, q4, q3, viacb1,
|
|
|
|
pclk, n_ipl0, vcc);
|
2020-11-25 12:04:07 +00:00
|
|
|
|
2020-12-27 21:52:15 +00:00
|
|
|
// N.B.: ASG as a "sound generator" is largely a misnomer, it is
|
|
|
|
// primarily a PWM disk speed generator.
|
|
|
|
|
2020-11-25 12:04:07 +00:00
|
|
|
// TODO FIXME: ASG not implemented.
|
|
|
|
// asg u11e(c16mf, rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, n_dma, vclk, gnd,
|
|
|
|
// tsen2, n_dmald, pwm, , , , , , , vcc);
|
2020-11-25 07:05:48 +00:00
|
|
|
endmodule
|
|
|
|
|
|
|
|
`endif // not MAC128PAL_V
|