Skip to content

Commit

Permalink
IFR: add MegaBit 128 support (1Mb internal function ROM)
Browse files Browse the repository at this point in the history
  • Loading branch information
eriks5 committed Dec 20, 2023
1 parent f2cf893 commit 234bbde
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 28 deletions.
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -18,6 +18,7 @@ Based on FPGA64 by Peter Wendrich with heavy later modifications by different pe
- **VIC register $D030 video manipulation tricks** (used in some demos, e.g. RfO part 1)
- **VDC with 16k or 64k RAM and multiple colour palettes**.
- Almost all C64 **and C128** cartridge formats (\*.CRT).
- **Internal Function ROM support for ROMs up to 1Mb with MegaBit 128 support**
- Direct file injection (\*.PRG) **with detection of C128 or C64 mode**.
- Dual SID with several degree of mixing 6581/8580 from stereo to mono.
- Similar to 6581 and 8580 SID filters.
Expand Down Expand Up @@ -62,8 +63,8 @@ To boot using rom files, a `boot0.rom` and `boot1.rom` file need to be placed in
Each drive's ROM is repeated twice in `boot1.rom`. The first ROM is used for drive 8, the second for drive 9. This makes it possible to use different ROMs in the two drives. The 1541 ROM is 16k and needs to be repeated 4 times to fill the 64k space.

There are two optional boot roms:
* `boot2.rom` for the optional Internal Function ROM (16 or 32k)
* `boot3.rom` for the optional External Function ROM (16 or 32k)
* `boot2.rom` for the optional Internal Function ROM (up to 1Mb with MegaBit 128 support)
* `boot3.rom` for the optional External Function ROM (16 or 32k)
* This is different from a cartridge (`.CRT`) file, it should be a plain ROM image without the cartridge headers

#### Using MRA files
Expand Down
51 changes: 32 additions & 19 deletions c128.sv
Expand Up @@ -498,7 +498,7 @@ hps_io #(.CONF_STR(CONF_STR), .VDNUM(2), .BLKSZ(1)) hps_io
.status(status),
.status_menumask({
/* C */ |cart_int_rom,
/* B */ cart_attached,
/* B */ |{cart_attached, cart_ext_rom},
/* A */ cfg_force64,
/* 9 */ ~status[69],
/* 8 */ ~status[66],
Expand Down Expand Up @@ -640,6 +640,7 @@ cartridge #(
.cart_bank_type(cart_bank_type),
.cart_bank_raddr(ioctl_load_addr),
.cart_bank_wr(cart_hdr_wr),
.cart_bank_int(d7port[4:0]),

.sysRom(sysRom),
.sysRomBank(sysRomBank),
Expand Down Expand Up @@ -780,7 +781,7 @@ reg io_cycle_we;
reg [24:0] io_cycle_addr;
reg [7:0] io_cycle_data;

reg [1:0] cart_int_rom = 0;
reg [6:0] cart_int_rom = 0;
reg [1:0] cart_ext_rom = 0;
reg rom_loading, rom_loaded = 0;
reg drv_loading, drv_loaded = 0;
Expand All @@ -794,23 +795,24 @@ wire drv_download = drv_loading & ioctl_download;
localparam RAM_ADDR = 25'h0000000; // System RAM: 256k
localparam CRM_ADDR = 25'h0040000; // Cartridge RAM: 64k
localparam ROM_ADDR = 25'h0060000; // System ROM: 96k (align on 128k) loaded from boot0.rom or MRA (required)
localparam IFR_ADDR = 25'h0078000; // Internal function ROM: 32k can be loaded from boot0.rom, boot2.rom or MRA (optional)
localparam DRV_ADDR = 25'h0080000; // Drive ROM: 512k loaded from boot0.rom, boot1.rom or MRA (required)
localparam CRT_ADDR = 25'h0100000; // Cartridge: 1M can be loaded from boot0.rom, boot3.rom or MRA (first 32k, optional)
localparam TAP_ADDR = 25'h0200000; // Tape buffer (not aligned)
localparam IFR_ADDR = 25'h0200000; // Internal function ROM: 1M can be loaded from boot2.rom or MRA (optional)
localparam TAP_ADDR = 25'h0300000; // Tape buffer (not aligned)
localparam GEO_ADDR = 25'h0C00000; // GeoRAM: 4M
localparam REU_ADDR = 25'h1000000; // REU: 16M

localparam ROM_SIZE = 25'h0012000; // min size of boot0.rom
localparam DRV_SIZE = 25'h0030000; // exact size of boot1.rom
localparam FRM_SIZE = 25'h0008000; // max size of function roms
localparam DRV_SIZE = 25'h0030000; // max size of boot1.rom
localparam EFR_SIZE = 25'h0008000; // max size of external function rom
localparam IFR_SIZE = 25'h0100000; // max size of internal function rom

wire skip_rom = bootrom ? (
( ioctl_addr < ROM_SIZE && rom_loaded)
|| (ioctl_addr >= IFR_ADDR-ROM_ADDR && ioctl_addr < IFR_ADDR-ROM_ADDR+FRM_SIZE && |cart_int_rom)
// || (ioctl_addr >= IFR_ADDR-ROM_ADDR && ioctl_addr < IFR_ADDR-ROM_ADDR+EFR_SIZE && |cart_int_rom)
|| (ioctl_addr >= DRV_ADDR-ROM_ADDR && ioctl_addr < DRV_ADDR-ROM_ADDR+DRV_SIZE && drv_loaded)
|| (ioctl_addr >= CRT_ADDR-ROM_ADDR && ioctl_addr < CRT_ADDR-ROM_ADDR+FRM_SIZE && (cart_attached || |cart_ext_rom))
|| (ioctl_addr >= CRT_ADDR-ROM_ADDR+FRM_SIZE)
|| (ioctl_addr >= CRT_ADDR-ROM_ADDR && ioctl_addr < CRT_ADDR-ROM_ADDR+EFR_SIZE && (cart_attached || |cart_ext_rom))
|| (ioctl_addr >= CRT_ADDR-ROM_ADDR+EFR_SIZE)
) : (ioctl_addr >= ROM_SIZE);

always @(posedge clk_sys) begin
Expand Down Expand Up @@ -869,9 +871,6 @@ always @(posedge clk_sys) begin
if (ioctl_addr == ROM_SIZE-1)
rom_loaded <= 1;

if (ioctl_addr == IFR_ADDR-ROM_ADDR)
cart_int_rom <= 0;

if (ioctl_addr == DRV_ADDR-ROM_ADDR) begin
drv_loading <= 1;
drv_loaded <= 0;
Expand All @@ -888,7 +887,6 @@ always @(posedge clk_sys) begin
end

if (|ioctl_data && ~&ioctl_data) begin
if (ioctl_addr[24:15] == {10'((IFR_ADDR-ROM_ADDR)>>15)}) cart_int_rom[ioctl_addr[14]] <= 1;
if (ioctl_addr[24:15] == {10'((CRT_ADDR-ROM_ADDR)>>15)}) cart_ext_rom[ioctl_addr[14]] <= 1;
end

Expand All @@ -913,10 +911,17 @@ always @(posedge clk_sys) begin
if (load_ifr) begin
if (ioctl_addr == 0) begin
ioctl_load_addr <= IFR_ADDR;
cart_int_rom <= 0;
cart_int_rom <= 7'h1;
end
if (ioctl_addr < FRM_SIZE) begin
if (|ioctl_data && ~&ioctl_data) cart_int_rom[ioctl_addr[14]] <= 1;
if (ioctl_addr < IFR_SIZE) begin
if (|ioctl_data && ~&ioctl_data) begin
if (ioctl_addr[14]) cart_int_rom[1] <= 1;
if (ioctl_addr[15]) cart_int_rom[2] <= 1;
if (ioctl_addr[16]) cart_int_rom[3] <= 1;
if (ioctl_addr[17]) cart_int_rom[4] <= 1;
if (ioctl_addr[18]) cart_int_rom[5] <= 1;
if (ioctl_addr[19]) cart_int_rom[6] <= 1;
end
ioctl_req_wr <= 1;
end
end
Expand All @@ -925,12 +930,14 @@ always @(posedge clk_sys) begin
if (ioctl_addr == 0) begin
ioctl_load_addr <= CRT_ADDR;
cart_attached <= 0;
cart_ext_rom <= 0;
cart_ext_rom <= 2'h1;
cart_c128 <= 1;
cart_id <= 0;
end
if (ioctl_addr < FRM_SIZE) begin
if (|ioctl_data && ~&ioctl_data) cart_ext_rom[ioctl_addr[14]] <= 1;
if (ioctl_addr < EFR_SIZE) begin
if (|ioctl_data && ~&ioctl_data) begin
if (ioctl_addr[14]) cart_ext_rom[1] <= 1;
end
ioctl_req_wr <= 1;
end
end
Expand Down Expand Up @@ -1267,6 +1274,9 @@ wire romL;
wire romH;
wire UMAXromH;

wire [7:0] d7port;
wire d7port_trig;

wire [17:0] audio_l,audio_r;

wire ntsc = status[2];
Expand Down Expand Up @@ -1442,6 +1452,9 @@ fpga64_sid_iec #(
.cass_sense(~tape_adc_act & (use_tape ? cass_sense : cass_rtc)),
.cass_read(tape_adc_act ? ~tape_adc : cass_read),

.d7port(d7port),
.d7port_trig(d7port_trig),

.c128_n(c128_n),
.z80_n(z80_n)
);
Expand Down
11 changes: 6 additions & 5 deletions rtl/cartridge.sv
Expand Up @@ -22,8 +22,8 @@ module cartridge
input cart_loading,
input cart_c128, // C128 cart
input [15:0] cart_id, // cart ID or cart type
input [1:0] cart_int_rom, // Internal function rom loaded during boot
input [1:0] cart_ext_rom, // External function rom loaded during boot
input [6:0] cart_int_rom, // internal function rom size mask: 00h=none 01h=16k, 03h=32k, 07h=64k, 0Fh=128k, 1Fh=256k, 3Fh=512k, 7Fh=1M
input [1:0] cart_ext_rom, // external function rom size mask: 0=none, 1=16k, 3=32k
input [7:0] cart_exrom, // CRT file EXROM status
input [7:0] cart_game, // CRT file GAME status
input [15:0] cart_bank_laddr, // bank loading address
Expand All @@ -32,6 +32,7 @@ module cartridge
input [7:0] cart_bank_type,
input [24:0] cart_bank_raddr, // chip packet address
input cart_bank_wr,
input [4:0] cart_bank_int, // Internal function ROM bank number (MegaBit128)

output exrom, // exrom line output (from cartridge)
input exrom_in, // exrom line input (to cartridge)
Expand Down Expand Up @@ -840,7 +841,7 @@ wire cs_iof = IOF && (mem_write ? IOF_wr_ena : IOF_ena);
assign mem_ce_out = mem_ce | (cs_ioe & stb_ioe) | (cs_iof & stb_iof);

//RAM banks are mapped to 0x040000 (64K max)
//ROM banks are mapped to 0x100000 (1MB max)
//CRT/EFR banks are mapped to 0x100000 (1MB max)
function [11:0] get_bank;
input [6:0] bank;
input ram;
Expand All @@ -865,11 +866,11 @@ always begin
if(sysRom) addr_out[24:12] = {8'(ROM_ADDR>>17), sysRomBank};

if(romFL && !mem_write) begin
addr_out[24:14] = {10'(IFR_ADDR>>15), 1'b0};
addr_out[24:14] = {5'(IFR_ADDR>>20), cart_bank_int & cart_int_rom[6:2], 1'b0};
data_floating = ~cart_int_rom[0];
end
if(romFH && !mem_write) begin
addr_out[24:14] = {10'(IFR_ADDR>>15), 1'b1};
addr_out[24:14] = {5'(IFR_ADDR>>20), cart_bank_int & cart_int_rom[6:2], 1'b1};
data_floating = ~cart_int_rom[1];
end
if(romH && (romH_we || !mem_write)) begin
Expand Down
11 changes: 10 additions & 1 deletion rtl/fpga64_buslogic.vhd
Expand Up @@ -93,6 +93,7 @@ entity fpga64_buslogic is
cs_cia1 : out std_logic;
cs_cia2 : out std_logic;
cs_ram : out std_logic;
cs_io7 : out std_logic;

-- To cartridge port
cs_ioE : out std_logic;
Expand Down Expand Up @@ -125,6 +126,7 @@ architecture rtl of fpga64_buslogic is
signal cs_colorLoc : std_logic;
signal cs_cia1Loc : std_logic;
signal cs_cia2Loc : std_logic;
signal cs_io7Loc : std_logic;
signal cs_ioELoc : std_logic;
signal cs_ioFLoc : std_logic;
signal cs_romLLoc : std_logic;
Expand Down Expand Up @@ -216,6 +218,7 @@ begin
cs_mmuHLoc <= '0';
cs_mmuLLoc <= '0';
cs_vdcLoc <= '0';
cs_io7Loc <= '0';
cs_ioELoc <= '0';
cs_ioFLoc <= '0';
cs_romLLoc <= '0'; -- external rom L
Expand Down Expand Up @@ -264,6 +267,8 @@ begin
end if;
when X"6" =>
cs_vdcLoc <= not z80m1;
when X"7" =>
cs_io7Loc <= not z80m1;
when X"8" | X"9" | X"A" | X"B" =>
cs_colorLoc <= '1';
when X"C" =>
Expand Down Expand Up @@ -358,10 +363,13 @@ begin
cs_vicLoc <= '1';
when X"4" =>
cs_sidLoc <= not z80m1;
when X"5" =>
cs_sidLoc <= pure64 and not z80m1;
when X"6" =>
cs_vdcLoc <= not pure64 and not z80m1;
cs_sidLoc <= pure64 and not z80m1;
when X"5" | X"7" =>
when X"7" =>
cs_io7Loc <= not z80m1;
cs_sidLoc <= pure64 and not z80m1;
when X"8" | X"9" | X"A" | X"B" =>
cs_colorLoc <= '1';
Expand Down Expand Up @@ -462,6 +470,7 @@ begin
cs_mmuH <= cs_mmuHLoc;
cs_mmuL <= cs_mmuLLoc;
cs_vdc <= cs_vdcLoc;
cs_io7 <= cs_io7Loc;
cs_color <= cs_colorLoc;
cs_cia1 <= cs_cia1Loc;
cs_cia2 <= cs_cia2Loc;
Expand Down
28 changes: 27 additions & 1 deletion rtl/fpga64_sid_iec.vhd
Expand Up @@ -195,6 +195,10 @@ port(
vdcPalette : in unsigned(3 downto 0);
vdcDebug : in std_logic;

-- D7xx port
d7port : out unsigned(7 downto 0);
d7port_trig : out std_logic;

-- System memory size
sys256k : in std_logic;

Expand Down Expand Up @@ -294,6 +298,7 @@ signal cpuM1_T80 : std_logic;
signal cpuIrq_n : std_logic;
signal cpuBusAk_T80_n: std_logic;
signal io_data_i : unsigned(7 downto 0);
signal io7_i : std_logic;
signal ioe_i : std_logic;
signal iof_i : std_logic;

Expand Down Expand Up @@ -702,6 +707,7 @@ port map (
cs_mmuH => cs_mmuH,
cs_mmuL => cs_mmuL,
cs_vdc => cs_vdc,
cs_io7 => io7_i,
cs_color => cs_color,
cs_cia1 => cs_cia1,
cs_cia2 => cs_cia2,
Expand Down Expand Up @@ -1085,6 +1091,26 @@ begin
end if;
end process;

-- -----------------------------------------------------------------------
-- D7xx port
-- -----------------------------------------------------------------------

process(clk32)
begin
if rising_edge(clk32) then
d7port_trig <= '0';

if reset = '1' then
d7port <= X"00";
elsif sysCycle = CYCLE_CPU6 then
if io7_i = '1' and cs_enable = '1' then
d7port <= cpuLastData;
d7port_trig <= cpuWe;
end if;
end if;
end if;
end process;

-- -----------------------------------------------------------------------
-- CPU / DMA
-- -----------------------------------------------------------------------
Expand Down Expand Up @@ -1155,7 +1181,7 @@ t80_cyc <= '1' when
cpuCycT80 <= t80_cyc;

-- I/O access to any of these chips starts a 8502 clock stretched cycle in 2 MHz mode
cs_io <= cs_vic or cs_sid or cs_mmuL or cs_vdc or cs_cia1 or cs_cia2 or ioe_i or iof_i or cpuIO_T80;
cs_io <= cs_vic or cs_sid or cs_mmuL or cs_vdc or cs_cia1 or cs_cia2 or io7_i or ioe_i or iof_i or cpuIO_T80;
cs_enable <= cpuBusAk_T80_n or (io_enable and (baLoc or cpuWe));

-- Last data bus activity of the CPU
Expand Down

0 comments on commit 234bbde

Please sign in to comment.