Fixes to mac128k PAL simulation issues, more documentation.
This commit is contained in:
parent
c490406c81
commit
fe87fea02c
|
@ -1319,6 +1319,11 @@ module dramctl_bbu (n_res, clk, r_n_w,
|
|||
// are in state 64.
|
||||
assign bbu_dtack = drc_state[6];
|
||||
|
||||
// TODO FIXME Important! High speed control for column access
|
||||
// strobes? The Macintosh 128K and Macintosh Plus use
|
||||
// combinatorial logic to assert the *CAS signal for half of a C16M
|
||||
// clock cycle, one pulse.
|
||||
|
||||
always @(negedge n_res) begin
|
||||
// Initialize all output registers on RESET.
|
||||
ra <= 10'bz; // Set to high-impedance to disable output.
|
||||
|
|
|
@ -56,13 +56,14 @@ module tsm(simclk, n_res,
|
|||
// 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;
|
||||
casl <= 1; cash <= 1; s0 <= 1; dtack <= 1;
|
||||
|
||||
ras <= 0; vclk <= 0; q2 <= 0; q1 <= 0;
|
||||
ras <= 1; vclk <= 1; q2 <= 1; q1 <= 1;
|
||||
end
|
||||
|
||||
// Simulate combinatorial logic sub-cycles.
|
||||
always @(posedge simclk) begin
|
||||
if (n_res) begin
|
||||
casl <= ~(~s0 & s1 & sysclk // video
|
||||
| ~s0 & ~ramen & ~lds // processor
|
||||
| ~s0 & ~casl & sysclk
|
||||
|
@ -77,22 +78,29 @@ module tsm(simclk, n_res,
|
|||
| ~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
|
||||
end
|
||||
|
||||
// Simulate registered logic.
|
||||
always @(posedge clk) begin
|
||||
ras <= ~(~pclk & q1 & s1 // video cycle
|
||||
| ~pclk & q1 & ~ramen & dtack // processor cycle
|
||||
| pclk & ~ras); // any other cycle
|
||||
vclk <= ~(~q1 & pclk & q2 & vclk // divide by 8 (1MHz)
|
||||
| ~vclk & q1
|
||||
| ~vclk & ~pclk
|
||||
| ~vclk & ~q2);
|
||||
q1 <= ~(~pclk & q1
|
||||
| pclk & ~q1); // divide `pclk` by 2 (4MHz)
|
||||
q2 <= ~(~q1 & pclk & q2 // divide by 4 (2MHz)
|
||||
| ~q2 & q1
|
||||
| ~q2 & ~pclk);
|
||||
always @(negedge clk) begin
|
||||
if (n_res) begin
|
||||
ras <= @(posedge clk)
|
||||
~(~pclk & q1 & s1 // video cycle
|
||||
| ~pclk & q1 & ~ramen & dtack // processor cycle
|
||||
| pclk & ~ras); // any other cycle
|
||||
vclk <= @(posedge clk)
|
||||
~(~q1 & pclk & q2 & vclk // divide by 8 (1MHz)
|
||||
| ~vclk & q1
|
||||
| ~vclk & ~pclk
|
||||
| ~vclk & ~q2);
|
||||
q1 <= @(posedge clk)
|
||||
~(~pclk & q1
|
||||
| pclk & ~q1); // divide `pclk` by 2 (4MHz)
|
||||
q2 <= @(posedge clk)
|
||||
~(~q1 & pclk & q2 // divide by 4 (2MHz)
|
||||
| ~q2 & q1
|
||||
| ~q2 & ~pclk);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
@ -119,8 +127,8 @@ module lag(simclk, n_res,
|
|||
// 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;
|
||||
vshft <= 1; vsync <= 1; hsync <= 1; s1 <= 1; viapb6 <= 1;
|
||||
snddma <= 1; reslin <= 1; resnyb <= 1;
|
||||
end
|
||||
|
||||
// Simulate combinatorial logic sub-cycles.
|
||||
|
@ -128,38 +136,60 @@ module lag(simclk, n_res,
|
|||
end
|
||||
|
||||
// Simulate registered logic.
|
||||
always @(posedge sysclk) begin
|
||||
vshft <= ~(s1 & ~vclk & snddma); // one pulse on the falling edge of `vclk`
|
||||
vsync <= ~(reslin
|
||||
| ~vsync & ~l28);
|
||||
hsync <= ~(viapb6 & va4 & ~va3 & ~va2 & va1 // begins in 29 (VA5)
|
||||
| /*~ ???*/resnyb
|
||||
| ~hsync & viapb6); // ends in 0F
|
||||
s1 <= ~(~p0q2 // 0 for processor and 1 for video
|
||||
| ~vclk
|
||||
| ~vsync & hsync
|
||||
| ~vsync & viapb6 // only in vertical retrace we have sound cycles
|
||||
| ~viapb6 & hsync & ~va4 & ~va3 & ~va2
|
||||
| ~viapb6 & ~hsync & (~va4 | va4 & ~va3 & ~va2 |
|
||||
always @(negedge sysclk) begin
|
||||
if (n_res) begin
|
||||
vshft <= @(posedge sysclk)
|
||||
~(s1 & ~vclk & snddma); // one pulse on the falling edge of `vclk`
|
||||
vsync <= @(posedge sysclk)
|
||||
~(reslin
|
||||
| ~vsync & ~l28);
|
||||
// hsync <= @(posedge sysclk)
|
||||
// ~(viapb6 & va4 & ~va3 & ~va2 & va1 // begins in 29 (VA5)
|
||||
// | /*~ ???*/resnyb
|
||||
// | ~hsync & viapb6); // ends in 0F
|
||||
hsync <= @(posedge sysclk)
|
||||
~(~viapb6 & ~va4 & ~va3 & va2 & va1 // begins in 29 (VA5)
|
||||
| ~hsync & ~va4
|
||||
| ~hsync & ~viapb6); // ends in 0F
|
||||
s1 <= @(posedge sysclk)
|
||||
~(~p0q2 // 0 for processor and 1 for video
|
||||
| ~vclk
|
||||
| ~vsync & hsync
|
||||
| ~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));
|
||||
viapb6 <= ~(~hsync & resnyb // 1 indicates horizontal retrace (pseudo VA6)
|
||||
| va1 & ~viapb6
|
||||
| va2 & ~viapb6
|
||||
| ~hsync & ~viapb6
|
||||
| resnyb & ~viapb6
|
||||
| vshft & ~viapb6);
|
||||
snddma <= ~(viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 in this output
|
||||
| ~snddma & vclk); // ... indicates sound cycle
|
||||
reslin <= ~(0); // ??? try to generate line 370
|
||||
resnyb <= ~(vclk // increment VA5:VA14 in 0F and 2B
|
||||
| viapb6 // ???
|
||||
| va1
|
||||
| va2
|
||||
| ~viapb6 & va3
|
||||
| hsync
|
||||
| viapb6 & ~va3
|
||||
| ~hsync & va3 & ~va4
|
||||
| ~hsync & ~va3 & va4);
|
||||
// viapb6 <= @(posedge sysclk)
|
||||
// ~(~hsync & resnyb // 1 indicates horizontal retrace (pseudo VA6)
|
||||
// | va1 & ~viapb6
|
||||
// | va2 & ~viapb6
|
||||
// | ~hsync & ~viapb6
|
||||
// | resnyb & ~viapb6
|
||||
// | vshft & ~viapb6);
|
||||
viapb6 <= @(posedge sysclk)
|
||||
~(hsync & ~va4 & ~va3 & va2 & va1 // 1 indicates horizontal retrace (pseudo VA6)
|
||||
| ~viapb6 & snddma
|
||||
| ~viapb6 & vclk);
|
||||
snddma <= @(posedge sysclk)
|
||||
~(viapb6 & va4 & ~va3 & va2 & va1 & p0q2 & vclk & ~hsync // 0 in this output
|
||||
| ~snddma & vclk); // ... indicates sound cycle
|
||||
reslin <= @(posedge sysclk) // try to generate line 370
|
||||
~(l28
|
||||
| ~vsync
|
||||
| hsync
|
||||
| ~viapb6
|
||||
| ~vclk);
|
||||
resnyb <= @(posedge sysclk)
|
||||
~(vclk // increment VA5:VA14 in 0F and 2B
|
||||
| viapb6 // ???
|
||||
| va1
|
||||
| va2
|
||||
| ~viapb6 & va3
|
||||
| hsync
|
||||
| viapb6 & ~va3
|
||||
| ~hsync & va3 & ~va4
|
||||
| ~hsync & ~va3 & va4);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
@ -184,12 +214,13 @@ module bmu1(simclk, n_res,
|
|||
// 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;
|
||||
csiwm <= 1; rd <= 1; cescc <= 1; vpa <= 1; romen <= 1;
|
||||
ramen <= 1; io1 <= 1; l28 <= 1;
|
||||
end
|
||||
|
||||
// Simulate combinatorial logic sub-cycles.
|
||||
always @(posedge simclk) begin
|
||||
if (n_res) begin
|
||||
csiwm <= ~(a23 & a22 & ~a21 & ~as); // DFE1FF
|
||||
rd <= ~(a23 & ~a22 & ~a21 & ~as); // 9FFFF8
|
||||
cescc <= ~(a23 & ~a22 & ~as); // 9FFFF8(R) or BFFFF9(W)
|
||||
|
@ -205,6 +236,7 @@ module bmu1(simclk, n_res,
|
|||
| ~l28 & ~va9
|
||||
| ~l28 & ~va8
|
||||
| ~l28 & ~va7);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
@ -227,26 +259,32 @@ module bmu0(simclk, n_res,
|
|||
// We must implement RESET for simulation or else this will never
|
||||
// stabilize.
|
||||
always @(negedge n_res) begin
|
||||
g244 <= 0; we <= 0;
|
||||
g244 <= 1; we <= 1;
|
||||
|
||||
ava14 <= 0; l15 <= 0; vid <= 0; ava13 <= 0;
|
||||
ava14 <= 1; l15 <= 1; vid <= 1; ava13 <= 1;
|
||||
end
|
||||
|
||||
// Simulate combinatorial logic sub-cycles.
|
||||
always @(posedge simclk) begin
|
||||
if (n_res) begin
|
||||
g244 <= ~(~ramen & rw
|
||||
| ~g244 & ~ramen);
|
||||
we <= ~(~ramen & ~rw
|
||||
| ~we & ~dtack); // or `dtack` is shorter before the video cycle
|
||||
end
|
||||
end
|
||||
|
||||
// Simulate registered logic.
|
||||
always @(posedge sysclk) begin
|
||||
ava14 <= ~(~va14 & ~va13); // + 1
|
||||
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
|
||||
always @(negedge sysclk) begin
|
||||
if (n_res) begin
|
||||
ava14 <= @(posedge sysclk) ~(~va14 & ~va13); // + 1
|
||||
l15 <= @(posedge sysclk)
|
||||
~(~va14 & ~va13 & ~va12 & ~va11 & ~va10 // we haven't passed line 15
|
||||
| va14 & ~va13 & va12 & va11 & va10); // passed by 368
|
||||
vid <= @(posedge sysclk)
|
||||
~(servid); // here we invert: blanking is in `vshft`
|
||||
ava13 <= @(posedge sysclk) ~(va13); // + 1
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
@ -267,34 +305,40 @@ module tsg(simclk, n_res,
|
|||
// We must implement RESET for simulation or else this will never
|
||||
// stabilize.
|
||||
always @(negedge n_res) begin
|
||||
d0 <= 0; ipl0 <= 0;
|
||||
d0 <= 1; ipl0 <= 1;
|
||||
|
||||
q6 <= 0; clkscc <= 0; q4 <= 0; q3 <= 0; viacb1 <= 0;
|
||||
pclk <= 0;
|
||||
q6 <= 1; clkscc <= 1; q4 <= 1; q3 <= 1; viacb1 <= 1;
|
||||
pclk <= 1;
|
||||
end
|
||||
|
||||
// Simulate combinatorial logic sub-cycles.
|
||||
always @(posedge simclk) begin
|
||||
if (n_res) begin
|
||||
ipl0 <= ~intscc | intvia; // CORRECTION
|
||||
// ipl0 <= ~(0); // ??? /M nanda
|
||||
d0 <= ~(~vpa & ~a19 & e); // F00000 sample the phase with 0 /n e' + usado
|
||||
end
|
||||
end
|
||||
|
||||
// Simulate registered logic.
|
||||
always @(posedge sysclk) begin
|
||||
always @(negedge sysclk) begin
|
||||
if (n_res) begin
|
||||
// TODO VERIFY: q6 missing?
|
||||
q6 <= ~(0);
|
||||
clkscc <= ~(clkscc & ~pclk & ~q4
|
||||
| clkscc & ~pclk & ~q3
|
||||
| clkscc & ~pclk & vclk
|
||||
| ~clkscc & pclk
|
||||
| ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
|
||||
viacb1 <= ~(0); // ??? /M nanda
|
||||
pclk <= ~(pclk); // divide SYSCLK by 2 (8MHz)
|
||||
q3 <= ~(~vclk); // `sysclk` / 16
|
||||
q4 <= ~(q4 & q3 & ~vclk // `sysclk` / 32
|
||||
| ~q4 & ~q3 // } J for generating CLKSCC
|
||||
| ~q4 & vclk);
|
||||
q6 <= @(posedge sysclk) ~(0);
|
||||
clkscc <= @(posedge sysclk)
|
||||
~(clkscc & ~pclk & ~q4
|
||||
| clkscc & ~pclk & ~q3
|
||||
| clkscc & ~pclk & vclk
|
||||
| ~clkscc & pclk
|
||||
| ~clkscc & q4 & q3 & ~vclk); // skip one inversion every 32 cycles
|
||||
viacb1 <= @(posedge sysclk) ~(0); // ??? /M nanda
|
||||
pclk <= @(posedge sysclk) ~(pclk); // divide SYSCLK by 2 (8MHz)
|
||||
q3 <= @(posedge sysclk) ~(~vclk); // `sysclk` / 16
|
||||
q4 <= @(posedge sysclk)
|
||||
~(q4 & q3 & ~vclk // `sysclk` / 32
|
||||
| ~q4 & ~q3 // } J for generating CLKSCC
|
||||
| ~q4 & vclk);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// Here's how we initialize ROM in the simulation with hex bytes (yes,
|
||||
// text input) from a file:
|
||||
|
||||
// $readmemh("hex_memory_file.mem", memory_array, [start_address], [end_address])
|
|
@ -140,7 +140,7 @@ module ls161(n_clr, clk, a, b, c, d, enp, gnd,
|
|||
wire [3:0] loadvec = { d, c, b, a };
|
||||
reg [3:0] outvec;
|
||||
|
||||
assign rco = (outvec == 4'hf);
|
||||
assign rco = (ent & (outvec == 4'hf));
|
||||
assign { q_d, q_c, q_b, q_a } = outvec;
|
||||
|
||||
// Clear is asynchronous, so it is not dependent on the clock.
|
||||
|
@ -179,6 +179,16 @@ module ls165(sh_n_ld, clk, e, f, g, h, n_q_h, gnd,
|
|||
assign q_h = int_reg[7];
|
||||
assign n_q_h = ~q_h;
|
||||
|
||||
// N.B. The '165 chips use asynchronous data loading. Don't
|
||||
// confuse with '166! This is actuallly a continuous
|
||||
// assignment... but the behavior is externally imperceptible until
|
||||
// we change to shift mode, so we simply act on the rising edge of
|
||||
// SH/*LD.
|
||||
|
||||
always @(posedge sh_n_ld) begin
|
||||
int_reg <= { h, g, f, e, d, c, b, a };
|
||||
end
|
||||
|
||||
// N.B. As soon as the falling edge of the clock is detected under
|
||||
// the proper conditions, we propagate the shifted value to the
|
||||
// output pins. We do not wait until the next falling edge of the
|
||||
|
@ -187,7 +197,7 @@ module ls165(sh_n_ld, clk, e, f, g, h, n_q_h, gnd,
|
|||
if (sh_n_ld)
|
||||
int_reg <= { int_reg[6:0], ser };
|
||||
else
|
||||
int_reg <= { h, g, f, e, d, c, b, a };
|
||||
; // Nothing to be done.
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
@ -210,6 +220,9 @@ module ls166(ser, a, b, c, d, clk_inh, clk, gnd,
|
|||
always @(negedge n_clr)
|
||||
int_reg <= 0;
|
||||
|
||||
// N.B. The '166 chips uses synchronous data loading. Don't
|
||||
// confuse with '165!
|
||||
|
||||
// N.B. As soon as the falling edge of the clock is detected under
|
||||
// the proper conditions, we propagate the shifted value to the
|
||||
// output pins. We do not wait until the next falling edge of the
|
||||
|
@ -383,13 +396,23 @@ module ls393(s1a, s1clr, s1q_a, s1q_b, s1q_c, s1q_d, gnd,
|
|||
assign { s1q_d, s1q_c, s1q_b, s1q_a } = s1reg;
|
||||
assign { s2q_d, s2q_c, s2q_b, s2q_a } = s2reg;
|
||||
|
||||
always @(posedge s1clr)
|
||||
// N.B. These counters propagate the incremented value to the
|
||||
// output pins on the negative edge of the A input, unlike the '161
|
||||
// counter.
|
||||
|
||||
// Also, for the sake of simulating the Macintosh 128K Main Logic
|
||||
// Board signals correctly, we must continuously evaluate the RESET
|
||||
// signals (not edge evaluate), due to the fact that we can have
|
||||
// glitches on the counter input while RESET is still being
|
||||
// held,and the fact that we need to assert the correct RESET value
|
||||
// early on.
|
||||
always @(s1clr)
|
||||
s1reg <= 0;
|
||||
always @(posedge s1a)
|
||||
always @(negedge s1a)
|
||||
s1reg <= s1reg + 1;
|
||||
always @(posedge s2clr)
|
||||
always @(s2clr)
|
||||
s2reg <= 0;
|
||||
always @(posedge s2a)
|
||||
always @(negedge s2a)
|
||||
s2reg <= s2reg + 1;
|
||||
|
||||
endmodule
|
||||
|
@ -397,10 +420,10 @@ endmodule
|
|||
// LS595: 8-bit serial input, parallel output shift register, with
|
||||
// output latch.
|
||||
module ls595(q_b, q_c, q_d, q_e, q_f, q_g, q_h, gnd,
|
||||
n_q_h, n_srclr, srclk, rclk, n_oe, ser, vcc);
|
||||
q_h_p, n_srclr, srclk, rclk, n_oe, ser, q_a, vcc);
|
||||
output wire q_b, q_c, q_d, q_e, q_f, q_g, q_h;
|
||||
`power wire gnd;
|
||||
output wire n_q_h;
|
||||
output wire q_h_p;
|
||||
input wire n_srclr, srclk, rclk, n_oe, ser;
|
||||
output wire q_a;
|
||||
`power wire vcc;
|
||||
|
@ -410,20 +433,20 @@ module ls595(q_b, q_c, q_d, q_e, q_f, q_g, q_h, gnd,
|
|||
|
||||
assign { q_h, q_g, q_f, q_e, q_d, q_c, q_b, q_a }
|
||||
= (n_oe) ? 8'bz : int_reg;
|
||||
assign n_q_h = q_h;
|
||||
assign q_h_p = q_h;
|
||||
|
||||
always @(negedge n_srclr) begin
|
||||
int_reg <= 0;
|
||||
end
|
||||
|
||||
always @(posedge srclk) begin
|
||||
int_reg = { int_reg[7:1], ser };
|
||||
end
|
||||
|
||||
// N.B. As soon as the rising edge of the clock is detected under
|
||||
// the proper conditions, we propagate the shifted value to the
|
||||
// output pins. We do not wait until the next rising edge of the
|
||||
// clock.
|
||||
always @(posedge srclk) begin
|
||||
int_reg <= { int_reg[6:0], ser };
|
||||
end
|
||||
|
||||
always @(posedge rclk) begin
|
||||
out_reg <= int_reg;
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue