BBU: Add DRAM sim, almost done with mac128k.
This commit is contained in:
parent
600f120c85
commit
602a9b564d
|
@ -1,4 +1,4 @@
|
|||
TARGETS = bbu.vvp test_stdlogic.vvp test_mac128pal.vvp
|
||||
TARGETS = bbu.vvp test_stdlogic.vvp test_mac128pal.vvp dram.vvp
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/* Simulate asynchronous DRAM using Verilog SRAM constructs.
|
||||
|
||||
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/>.
|
||||
|
||||
*/
|
||||
|
||||
`ifndef DRAM_V
|
||||
`define DRAM_V
|
||||
|
||||
// NOTE: The reset and clock inputs are solely for simulation
|
||||
// purposes, namely for implementing DRAM row expiry. WARNING: Row
|
||||
// expiry will make simulation slow!
|
||||
// `define ROW_EXPIRY
|
||||
|
||||
/* Important! Restrictions on real DRAM that are currently not
|
||||
simulated:
|
||||
|
||||
* Minimum hold times on *RAS and *CAS
|
||||
|
||||
* Maximum hold times, though maximum hold time is somewhat
|
||||
implemented by virtue of row expiry.
|
||||
|
||||
* Timing between asserting *RAS and *CAS.
|
||||
|
||||
* DRAM initialization pulses before use
|
||||
*/
|
||||
|
||||
// 64kbyte DRAM SIMM
|
||||
module dram64kbyte(n_res, clk,
|
||||
n_we, n_ras, n_cas,
|
||||
ra, rdq);
|
||||
parameter RASBITS = 8;
|
||||
parameter ROWSIZE = 2**RASBITS;
|
||||
parameter WORDBITS = 8;
|
||||
|
||||
// Used to replicate hardware constructs that simulate DRAM expiry.
|
||||
integer i, j;
|
||||
|
||||
input wire n_res, clk;
|
||||
input wire n_we, n_ras, n_cas;
|
||||
input wire [RASBITS-1:0] ra;
|
||||
inout wire [WORDBITS-1:0] rdq;
|
||||
|
||||
reg n_we_l; // Write-enable latched value
|
||||
reg [RASBITS-1:0] rowaddr, coladdr;
|
||||
|
||||
reg [WORDBITS-1:0] rows[0:ROWSIZE-1][0:ROWSIZE-1];
|
||||
`ifdef ROW_EXPIRY
|
||||
reg [15:0] rowexpire[0:ROWSIZE-1];
|
||||
`endif
|
||||
|
||||
assign rdq = (~n_ras & ~n_cas) ? rows[rowaddr][ra] : 'bz;
|
||||
|
||||
always @(negedge n_res) begin
|
||||
// Initialize essential internal state to some sane values.
|
||||
end
|
||||
|
||||
always @(negedge n_ras) begin
|
||||
rowaddr <= ra;
|
||||
end
|
||||
|
||||
always @(negedge n_cas) begin
|
||||
coladdr <= ra;
|
||||
n_we_l <= n_we;
|
||||
end
|
||||
|
||||
always @(posedge n_cas) begin
|
||||
if (~n_we_l)
|
||||
rows[rowaddr][coladdr] <= rdq;
|
||||
end
|
||||
|
||||
`ifdef ROW_EXPIRY
|
||||
always @(posedge n_ras) begin
|
||||
rowexpire[rowaddr] <= 65535;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
for (i = 0; i <= ROWSIZE-1; i = i + 1) begin
|
||||
rowexpire[i] <= rowexpire[i] - 1;
|
||||
if (rowexpire[i] == 0) begin
|
||||
for (j = 0; j <= ROWSIZE-1; j = j + 1)
|
||||
rows[i][j] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
`endif // ROW_EXPIRY
|
||||
endmodule
|
||||
|
||||
// 256kbyte DRAM SIMM
|
||||
module dram256kbyte(n_res, clk,
|
||||
n_we, n_ras, n_cas,
|
||||
ra, rdq);
|
||||
input wire n_res, clk;
|
||||
input wire n_we, n_ras, n_cas;
|
||||
input wire [8:0] ra;
|
||||
inout wire [7:0] rdq;
|
||||
|
||||
dram64kbyte #(9, 2**9)
|
||||
u0(n_res, clk, n_we, n_ras, n_cas, ra, rdq);
|
||||
endmodule
|
||||
|
||||
// 1Mbyte DRAM SIMM
|
||||
module dram1mbyte(n_res, clk,
|
||||
n_we, n_ras, n_cas,
|
||||
ra, rdq);
|
||||
input wire n_res, clk;
|
||||
input wire n_we, n_ras, n_cas;
|
||||
input wire [9:0] ra;
|
||||
inout wire [7:0] rdq;
|
||||
|
||||
dram64kbyte #(10, 2**10)
|
||||
u0(n_res, clk, n_we, n_ras, n_cas, ra, rdq);
|
||||
endmodule
|
||||
|
||||
`endif // not DRAM_V
|
|
@ -279,17 +279,19 @@ module palcl();
|
|||
// TODO: Also implement dual video address counter ICs as part of
|
||||
// the PAL cluster.
|
||||
// Video address signals, comes from video counter IC
|
||||
input wire va14, va13, va12, va11, va10, va9, va8, va7,
|
||||
va4, va3, va2, va1;
|
||||
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_vshft, n_vsync, n_hsync, n_snddma, vid;
|
||||
input wire servid;
|
||||
output wire n_vsync, n_hsync, vid;
|
||||
|
||||
// MC68000 CPU address signals
|
||||
input wire a23, a22, a21, a20, a19, a17, a9;
|
||||
input wire a23, a22, a21, a20, a19, a17, a16,
|
||||
a15, a14, a13, a12, a11, a10, a9,
|
||||
a8, a7, a6, a5, a4, a3, a2, a1;
|
||||
// not used: a18
|
||||
input wire n_as, n_uds, n_lds;
|
||||
output wire n_dtack;
|
||||
input wire r_n_w;
|
||||
|
@ -311,11 +313,15 @@ module palcl();
|
|||
|
||||
// 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;
|
||||
|
||||
// Internal video signals
|
||||
wire n_vshft, n_snddma, servid;
|
||||
|
||||
// Address multiplexer signals?
|
||||
output wire s0, s1, l28, l15, g244;
|
||||
wire s0, s1, l28, l15, n_245oe;
|
||||
|
||||
// PAL chip-select and unknown "IO" signals
|
||||
wire tsm_oe1, lag_oe2, bmu0_oe1, tsg_oe3;
|
||||
|
@ -326,7 +332,6 @@ module palcl();
|
|||
|
||||
// Wires to/from standard logic chips.
|
||||
wire sysclk, snddma, n_a20, n_sndres, sndres, n_snd, snd, wr, n_wr;
|
||||
wire n_245oe;
|
||||
|
||||
// N.B.: *WR comes from IWM chip, WR goes to floppy drives. *A20
|
||||
// goes to VIA.CS1. *SNDDMA comes from the LAG. *SYSCLK comes
|
||||
|
@ -337,11 +342,14 @@ module palcl();
|
|||
wire c8mf, c16mf, n_dmald, u12f_tc, ram_r_n_w_f;
|
||||
wire vmsh; // video mid-shift, connect two register chips together
|
||||
wire n_lermd; // ???
|
||||
wire n_ldps;
|
||||
wire n_ldps; // => n_vshft
|
||||
wire s5;
|
||||
wire ra8, ra9;
|
||||
|
||||
wire vid_n_a4; // ???
|
||||
wire vid_n_a4; // => 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
|
||||
|
@ -359,27 +367,46 @@ module palcl();
|
|||
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,
|
||||
n_sndres, sndres, n_snd, snd, wr, n_wr, vcc);
|
||||
|
||||
// Dual PWM disk drive counters
|
||||
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);
|
||||
// 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);
|
||||
ls166 u11f(s5, rdq0, rdq1, rdq2, rdq3, 1'b0, c16mf, gnd,
|
||||
s5, rdq4, rdq5, rdq6, vmsh, rdq7, n_ldps, 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);
|
||||
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);
|
||||
f253 u10g(snddma, vid_n_a4, va7, s5, a9, a17, ra8, gnd,
|
||||
// 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);
|
||||
|
||||
// asg u11e(c16mf, rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, n_dma, vclk, gnd,
|
||||
// tsen2, n_dmald, pwm, , , , , , , 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);
|
||||
// RAM row/column video/CPU address multiplexers
|
||||
f257 u2f(p0q2/*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,
|
||||
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);
|
||||
f253 u3g(snddma, s1, va5, va13, a5, a13, ra4, gnd,
|
||||
ra5, a14, a6, va14, va6, p0q2/*c2m*/, snddma, vcc);
|
||||
f253 u4f(snddma, s1, va1, s5, a1, a9, ra0, gnd,
|
||||
ra1, a10, a2, va10, va2, p0q2/*c2m*/, snddma, vcc);
|
||||
f253 u4g(snddma, s1, va7, n_vidpg2, a7, a15, ra6, gnd,
|
||||
ra7, a16, a8, s5, va8, p0q2/*c2m*/, snddma, vcc);
|
||||
|
||||
tsm pal0(simclk, 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);
|
||||
|
@ -390,11 +417,15 @@ module palcl();
|
|||
bmu1 pal2(simclk, 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,
|
||||
r_n_w, gnd, bmu0_oe1, g244, we, ava14, l15, vid, ava13,
|
||||
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_intvia, gnd, tsg_oe3, d0, q6, clkscc, q4, q3, viacb1,
|
||||
pclk, n_ipl0, vcc);
|
||||
|
||||
// TODO FIXME: ASG not implemented.
|
||||
// asg u11e(c16mf, rdq0, rdq1, rdq2, rdq3, rdq4, rdq5, n_dma, vclk, gnd,
|
||||
// tsen2, n_dmald, pwm, , , , , , , vcc);
|
||||
endmodule
|
||||
|
||||
`endif // not MAC128PAL_V
|
||||
|
|
Loading…
Reference in New Issue