sd2snes/verilog/sd2snes/address.v
2012-05-02 10:46:01 +02:00

248 lines
9.2 KiB
Verilog

`timescale 1 ns / 1 ns
//////////////////////////////////////////////////////////////////////////////////
// Company: Rehkopf
// Engineer: Rehkopf
//
// Create Date: 01:13:46 05/09/2009
// Design Name:
// Module Name: address
// Project Name:
// Target Devices:
// Tool versions:
// Description: Address logic w/ SaveRAM masking
//
// Dependencies:
//
// Revision:
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module address(
input CLK,
input [7:0] featurebits, // peripheral enable/disable
input [2:0] MAPPER, // MCU detected mapper
input [23:0] SNES_ADDR, // requested address from SNES
input [7:0] SNES_PA, // peripheral address from SNES
output [23:0] ROM_ADDR, // Address to request from SRAM0
output ROM_SEL, // enable SRAM0 (active low)
output IS_SAVERAM, // address/CS mapped as SRAM?
output IS_ROM, // address mapped as ROM?
output IS_WRITABLE, // address somehow mapped as writable area?
input [23:0] SAVERAM_MASK,
input [23:0] ROM_MASK,
output msu_enable,
output srtc_enable,
output use_bsx,
input [14:0] bsx_regs,
output dspx_enable,
output dspx_dp_enable,
output dspx_a0,
output r213f_enable,
input [8:0] bs_page_offset,
input [9:0] bs_page,
input bs_page_enable
);
parameter [2:0]
FEAT_DSPX = 0,
FEAT_ST0010 = 1,
FEAT_SRTC = 2,
FEAT_MSU1 = 3,
FEAT_213F = 4
;
wire [23:0] SRAM_SNES_ADDR;
/* currently supported mappers:
Index Mapper
000 HiROM
001 LoROM
010 ExHiROM (48-64Mbit)
011 BS-X
110 brainfuck interleaved 96MBit Star Ocean =)
111 menu (ROM in upper SRAM)
*/
/* HiROM: SRAM @ Bank 0x30-0x3f, 0xb0-0xbf
Offset 6000-7fff */
assign IS_ROM = ((!SNES_ADDR[22] & SNES_ADDR[15])
|(SNES_ADDR[22]));
assign IS_SAVERAM = SAVERAM_MASK[0]
&(featurebits[FEAT_ST0010]
?((SNES_ADDR[22:19] == 4'b1101)
& &(~SNES_ADDR[15:12])
& SNES_ADDR[11])
:((MAPPER == 3'b000
|| MAPPER == 3'b010
|| MAPPER == 3'b110
|| MAPPER == 3'b111)
? (!SNES_ADDR[22]
& SNES_ADDR[21]
& &SNES_ADDR[14:13]
& !SNES_ADDR[15]
)
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd Offset 0000-7fff
TODO: 0000-ffff for small ROMs? */
:(MAPPER == 3'b001)
? (&SNES_ADDR[22:20]
& (SNES_ADDR[19:16] < 4'b1110)
& !SNES_ADDR[15]
)
/* BS-X: SRAM @ Bank 0x10-0x17 Offset 5000-5fff */
:(MAPPER == 3'b011)
? ((SNES_ADDR[23:19] == 5'b00010)
& (SNES_ADDR[15:12] == 4'b0101)
)
: 1'b0));
/* BS-X has 4 MBits of extra RAM that can be mapped to various places */
assign IS_WRITABLE = IS_SAVERAM
|((MAPPER == 3'b011)
?((bsx_regs[3] && SNES_ADDR[23:20]==4'b0110)
|(!bsx_regs[5] && SNES_ADDR[23:20]==4'b0100)
|(!bsx_regs[6] && SNES_ADDR[23:20]==4'b0101)
|(SNES_ADDR[23:19] == 5'b01110)
|(SNES_ADDR[23:21] == 3'b001
&& SNES_ADDR[15:13] == 3'b011)
)
: 1'b0);
/* BSX regs:
Index Function
1 0=map flash to ROM area; 1=map PRAM to ROM area
2 1=HiROM; 0=LoROM
3 1=Mirror PRAM @60-6f:0000-ffff
5 1=DO NOT mirror PRAM @40-4f:0000-ffff
6 1=DO NOT mirror PRAM @50-5f:0000-ffff
7 1=map BSX cartridge ROM @00-1f:8000-ffff
8 1=map BSX cartridge ROM @80-9f:8000-ffff
*/
assign SRAM_SNES_ADDR = ((MAPPER == 3'b000)
?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK)
: ({1'b0, SNES_ADDR[22:0]} & ROM_MASK))
:(MAPPER == 3'b001)
?(IS_SAVERAM
? 24'hE00000 + (SNES_ADDR[14:0] & SAVERAM_MASK)
: ({2'b00, SNES_ADDR[22:16], SNES_ADDR[14:0]}
& ROM_MASK))
:(MAPPER == 3'b010)
?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK)
: ({1'b0, !SNES_ADDR[23], SNES_ADDR[21:0]}
& ROM_MASK))
:(MAPPER == 3'b011)
?(IS_SAVERAM
? 24'hE00000 + {SNES_ADDR[18:16], SNES_ADDR[11:0]}
: IS_WRITABLE
? (24'h400000 + (SNES_ADDR & 24'h07FFFF))
: bs_page_enable
? (24'h900000 + {bs_page,bs_page_offset})
:((bsx_regs[7] && SNES_ADDR[23:21] == 3'b000)
|(bsx_regs[8] && SNES_ADDR[23:21] == 3'b100))
?(24'h800000
+ ({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]}
& 24'h0FFFFF)
)
:((bsx_regs[1]
? 24'h400000
: 24'h000000
)
+ bsx_regs[2]
?({2'b00, SNES_ADDR[21:0]}
& (ROM_MASK /* >> bsx_regs[1] */)
)
:({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]}
& (ROM_MASK /* >> bsx_regs[1] */)
)
)
)
:(MAPPER == 3'b110)
?(IS_SAVERAM
? 24'hE00000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK)
:(SNES_ADDR[15]
?({1'b0, SNES_ADDR[23:16], SNES_ADDR[14:0]})
:({2'b10,
SNES_ADDR[23],
SNES_ADDR[21:16],
SNES_ADDR[14:0]}
)
)
)
:(MAPPER == 3'b111)
?(IS_SAVERAM
? 24'hFF0000 + ((SNES_ADDR[14:0] - 15'h6000)
& SAVERAM_MASK)
: (({1'b0, SNES_ADDR[22:0]} & ROM_MASK)
+ 24'hE00000)
)
: 24'b0);
assign ROM_ADDR = SRAM_SNES_ADDR;
assign ROM_SEL = 1'b0;
assign msu_enable_w = featurebits[FEAT_MSU1] & (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000));
reg [5:0] msu_enable_r;
initial msu_enable_r = 6'b000000;
always @(posedge CLK) msu_enable_r <= {msu_enable_r[4:0], msu_enable_w};
assign msu_enable = &msu_enable_r[5:2];
assign use_bsx = (MAPPER == 3'b011);
assign srtc_enable = featurebits[FEAT_SRTC] & (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfffe) == 16'h2800));
// DSP1 LoROM: DR=30-3f:8000-bfff; SR=30-3f:c000-ffff
// or DR=60-6f:0000-3fff; SR=60-6f:4000-7fff
// DSP1 HiROM: DR=00-0f:6000-6fff; SR=00-0f:7000-7fff
wire dspx_enable_w =
featurebits[FEAT_DSPX]
?((MAPPER == 3'b001)
?(ROM_MASK[20]
?(SNES_ADDR[22] & SNES_ADDR[21] & ~SNES_ADDR[20] & ~SNES_ADDR[15])
:(~SNES_ADDR[22] & SNES_ADDR[21] & SNES_ADDR[20] & SNES_ADDR[15])
)
:(MAPPER == 3'b000)
?(~SNES_ADDR[22] & ~SNES_ADDR[21] & ~SNES_ADDR[20] & ~SNES_ADDR[15]
& &SNES_ADDR[14:13])
:1'b0)
:featurebits[FEAT_ST0010]
?(SNES_ADDR[22] & SNES_ADDR[21] & ~SNES_ADDR[20] & &(~SNES_ADDR[19:16]) & ~SNES_ADDR[15])
:1'b0;
wire dspx_dp_enable_w = featurebits[FEAT_ST0010]
&(SNES_ADDR[22:19] == 4'b1101
&& SNES_ADDR[15:11] == 5'b00000);
assign dspx_a0 = featurebits[FEAT_DSPX]
?((MAPPER == 3'b001) ? SNES_ADDR[14]
:(MAPPER == 3'b000) ? SNES_ADDR[12]
:1'b1)
:featurebits[FEAT_ST0010]
?SNES_ADDR[0]
:1'b1;
assign dspx_dp_enable = dspx_dp_enable_w;
reg [5:0] dspx_enable_r;
initial dspx_enable_r = 6'b000000;
always @(posedge CLK) dspx_enable_r <= {dspx_enable_r[4:0], dspx_enable_w};
assign dspx_enable = &dspx_enable_r[5:2];
wire r213f_enable_w = (SNES_PA == 8'h3f);
reg [5:0] r213f_enable_r;
initial r213f_enable_r = 6'b000000;
always @(posedge CLK) r213f_enable_r <= {r213f_enable_r[4:0], r213f_enable_w};
assign r213f_enable = &r213f_enable_r[5:2] & featurebits[FEAT_213F];
endmodule