From 37a309fd0e7641e7e8b11c1b74d6fb4b7912e427 Mon Sep 17 00:00:00 2001 From: Maximilian Rehkopf Date: Wed, 2 May 2012 10:42:46 +0200 Subject: [PATCH] FPGA: improve BS support (more date fields, initial download data support) --- verilog/sd2snes/address.v | 9 +- verilog/sd2snes/bsx.v | 174 +++++++++++++++++++++++++------------- verilog/sd2snes/main.v | 22 +++-- 3 files changed, 140 insertions(+), 65 deletions(-) diff --git a/verilog/sd2snes/address.v b/verilog/sd2snes/address.v index c833d97..900f41f 100644 --- a/verilog/sd2snes/address.v +++ b/verilog/sd2snes/address.v @@ -37,7 +37,10 @@ module address( output dspx_enable, output dspx_dp_enable, output dspx_a0, - output r213f_enable + output r213f_enable, + input [8:0] bs_page_offset, + input [9:0] bs_page, + input bs_page_enable ); parameter [2:0] @@ -141,7 +144,9 @@ assign SRAM_SNES_ADDR = ((MAPPER == 3'b000) ? 24'hE00000 + {SNES_ADDR[18:16], SNES_ADDR[11:0]} : IS_WRITABLE ? (24'h400000 + (SNES_ADDR & 24'h07FFFF)) - : ((bsx_regs[7] && SNES_ADDR[23:21] == 3'b000) + : 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]} diff --git a/verilog/sd2snes/bsx.v b/verilog/sd2snes/bsx.v index a776e0e..3b9e6b6 100644 --- a/verilog/sd2snes/bsx.v +++ b/verilog/sd2snes/bsx.v @@ -32,7 +32,10 @@ module bsx( input use_bsx, output data_ovr, output flash_writable, - input [55:0] rtc_data + input [59:0] rtc_data, + output [9:0] bs_page_out, // support only page 0000-03ff + output bs_page_enable, + output [8:0] bs_page_offset ); wire [3:0] reg_addr = snes_addr[19:16]; // 00-0f:5000-5fff @@ -67,11 +70,40 @@ assign flash_writable = (use_bsx) && flash_we_r && !is_flash_special_address; -assign data_ovr = cart_enable | base_enable | flash_ovr; +assign data_ovr = (cart_enable | base_enable | flash_ovr) & ~bs_page_enable; + + +reg [9:0] bs_page0; +reg [9:0] bs_page1; + +reg [8:0] bs_page0_offset; +reg [8:0] bs_page1_offset; +reg [4:0] bs_stb0_offset; +reg [4:0] bs_stb1_offset; + +wire bs_sta0_en = base_addr == 5'h0a; +wire bs_stb0_en = base_addr == 5'h0b; +wire bs_page0_en = base_addr == 5'h0c; + +wire bs_sta1_en = base_addr == 5'h10; +wire bs_stb1_en = base_addr == 5'h11; +wire bs_page1_en = base_addr == 5'h12; + +assign bs_page_enable = base_enable & ((|bs_page0 & (bs_page0_en | bs_sta0_en | bs_stb0_en)) + |(|bs_page1 & (bs_page1_en | bs_sta1_en | bs_stb1_en))); + +assign bs_page_out = (bs_page0_en | bs_sta0_en | bs_stb0_en) ? bs_page0 : bs_page1; + +assign bs_page_offset = bs_sta0_en ? 9'h032 + : bs_stb0_en ? (9'h034 + bs_stb0_offset) + : bs_sta1_en ? 9'h032 + : bs_stb1_en ? (9'h034 + bs_stb1_offset) + : (9'h048 + (bs_page0_en ? bs_page0_offset : bs_page1_offset)); reg [3:0] reg_oe_sreg; always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[2:0], reg_oe}; wire reg_oe_falling = (reg_oe_sreg[3:0] == 4'b1000); +wire reg_oe_rising = (reg_oe_sreg[3:0] == 4'b0001); reg [1:0] reg_we_sreg; always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[0], reg_we}; @@ -96,40 +128,40 @@ wire [7:0] rtc_sec = rtc_data[3:0] + (rtc_data[7:4] << 3) + (rtc_data[7:4] << 1) wire [7:0] rtc_min = rtc_data[11:8] + (rtc_data[15:12] << 3) + (rtc_data[15:12] << 1); wire [7:0] rtc_hour = rtc_data[19:16] + (rtc_data[23:20] << 3) + (rtc_data[23:20] << 1); wire [7:0] rtc_day = rtc_data[27:24] + (rtc_data[31:28] << 3) + (rtc_data[31:28] << 1); -/* The following signals are currently unused. - They are kept in case more Satellaview date registers are discovered. */ wire [7:0] rtc_month = rtc_data[35:32] + (rtc_data[39:36] << 3) + (rtc_data[39:36] << 1); +wire [7:0] rtc_dow = {4'b0,rtc_data[59:56]}; wire [7:0] rtc_year1 = rtc_data[43:40] + (rtc_data[47:44] << 3) + (rtc_data[47:44] << 1); wire [7:0] rtc_year100 = rtc_data[51:48] + (rtc_data[55:52] << 3) + (rtc_data[55:52] << 1); +wire [15:0] rtc_year = (rtc_year100 << 6) + (rtc_year100 << 5) + (rtc_year100 << 2) + rtc_year1; initial begin regs_tmpr <= 15'b000000100000000; regs_outr <= 15'b000000100000000; bsx_counter <= 0; - base_regs[8] <= 0; - base_regs[9] <= 0; - base_regs[10] <= 0; - base_regs[11] <= 8'h9f; - base_regs[12] <= 8'h10; - base_regs[13] <= 8'h9f; - base_regs[14] <= 0; - base_regs[15] <= 0; - base_regs[16] <= 0; - base_regs[17] <= 8'h9f; - base_regs[18] <= 8'h01; - base_regs[19] <= 8'h9f; - base_regs[20] <= 0; - base_regs[21] <= 0; - base_regs[22] <= 8'h02; - base_regs[23] <= 8'hff; - base_regs[24] <= 8'h80; - base_regs[25] <= 8'h01; - base_regs[26] <= 0; - base_regs[27] <= 0; - base_regs[28] <= 0; - base_regs[29] <= 0; - base_regs[30] <= 0; - base_regs[31] <= 0; + base_regs[5'h08] <= 0; + base_regs[5'h09] <= 0; + base_regs[5'h0a] <= 8'h01; + base_regs[5'h0b] <= 0; + base_regs[5'h0c] <= 0; + base_regs[5'h0d] <= 0; + base_regs[5'h0e] <= 0; + base_regs[5'h0f] <= 0; + base_regs[5'h10] <= 8'h01; + base_regs[5'h11] <= 0; + base_regs[5'h12] <= 0; + base_regs[5'h13] <= 0; + base_regs[5'h14] <= 0; + base_regs[5'h15] <= 0; + base_regs[5'h16] <= 0; + base_regs[5'h17] <= 0; + base_regs[5'h18] <= 0; + base_regs[5'h19] <= 0; + base_regs[5'h1a] <= 0; + base_regs[5'h1b] <= 0; + base_regs[5'h1c] <= 0; + base_regs[5'h1d] <= 0; + base_regs[5'h1e] <= 0; + base_regs[5'h1f] <= 0; flash_vendor_data[3'h0] <= 8'h4d; flash_vendor_data[3'h1] <= 8'h00; flash_vendor_data[3'h2] <= 8'h50; @@ -140,39 +172,54 @@ initial begin flash_vendor_data[3'h7] <= 8'h00; flash_ovr_r <= 1'b0; flash_we_r <= 1'b0; + bs_page0 <= 10'h0; + bs_page1 <= 10'h0; + bs_page0_offset <= 9'h0; + bs_page1_offset <= 9'h0; + bs_stb0_offset <= 5'h00; + bs_stb1_offset <= 5'h00; end always @(posedge clkin) begin + if(reg_oe_rising) begin + if(base_enable) begin + case(base_addr) + 5'h0b: bs_stb0_offset <= bs_stb0_offset + 1; + 5'h0c: bs_page0_offset <= bs_page0_offset + 1; + 5'h11: bs_stb1_offset <= bs_stb1_offset + 1; + 5'h12: bs_page1_offset <= bs_page1_offset + 1; + endcase + end + end if(reg_oe_falling) begin if(cart_enable) reg_data_outr <= {regs_outr[reg_addr], 7'b0}; else if(base_enable) begin case(base_addr) - 5'b10010: begin - if(bsx_counter < 18) begin - bsx_counter <= bsx_counter + 1; - case (bsx_counter) - 5: - reg_data_outr <= 8'h1; - 6: - reg_data_outr <= 8'h1; - 10: - reg_data_outr <= rtc_sec; - 11: - reg_data_outr <= rtc_min; - 12: - reg_data_outr <= rtc_hour; - default: - reg_data_outr <= 8'h0; - endcase - end else begin - reg_data_outr <= 8'h0; - bsx_counter <= 0; - end + 5'h0b, 5'h11: begin + base_regs[base_addr+5'h02] <= base_regs[base_addr+5'h02] | reg_data_in; + end + 5'h0c, 5'h12: begin + case (bs_page1_offset) + 4: reg_data_outr <= 8'h3; + 5: reg_data_outr <= 8'h1; + 6: reg_data_outr <= 8'h1; + 10: reg_data_outr <= rtc_sec; + 11: reg_data_outr <= rtc_min; + 12: reg_data_outr <= rtc_hour; + 13: reg_data_outr <= rtc_dow; + 14: reg_data_outr <= rtc_day; + 15: reg_data_outr <= rtc_month; + 16: reg_data_outr <= rtc_year[7:0]; + 17: reg_data_outr <= rtc_year[15:8]; + default: reg_data_outr <= 8'h0; + endcase + end + 5'h0d, 5'h13: begin + reg_data_outr <= base_regs[base_addr]; + base_regs[base_addr] <= 8'h00; end - 5'b10011: - reg_data_outr <= base_regs[base_addr] & 8'h3f; default: reg_data_outr <= base_regs[base_addr]; endcase @@ -190,7 +237,7 @@ always @(posedge clkin) begin end end else if(pgm_we_rising) begin regs_tmpr[8:1] <= (regs_tmpr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0]; - regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0]; + regs_outr[8:1] <= (regs_outr[8:1] | reg_set_bits[7:0]) & ~reg_reset_bits[7:0]; end else if(reg_we_rising && cart_enable) begin if(reg_addr == 4'he && reg_data_in[7]) regs_outr <= regs_tmpr | 15'b100000000000000; @@ -198,16 +245,27 @@ always @(posedge clkin) begin regs_tmpr[reg_addr] <= reg_data_in[7]; end else if(reg_we_rising && base_enable) begin case(base_addr) - 5'h0f: begin - base_regs[base_addr-1] <= base_regs[base_addr]-(base_regs[base_addr-1] >> 1); - base_regs[base_addr] <= base_regs[base_addr] >> 1; + 5'h09: begin + base_regs[8'h09] <= reg_data_in; + bs_page0 <= {reg_data_in[1:0], base_regs[8'h08]}; + bs_page0_offset <= 9'h00; + end + 5'h0b: begin + bs_stb0_offset <= 5'h00; + end + 5'h0c: begin + bs_page0_offset <= 9'h00; + end + 5'h0f: begin + base_regs[8'h0f] <= reg_data_in; + bs_page1 <= {reg_data_in[1:0], base_regs[8'h0e]}; + bs_page1_offset <= 9'h00; end 5'h11: begin - bsx_counter <= 0; - base_regs[base_addr] <= reg_data_in; + bs_stb1_offset <= 5'h00; end 5'h12: begin - base_regs[8'h10] <= 8'h80; + bs_page1_offset <= 9'h00; end default: base_regs[base_addr] <= reg_data_in; diff --git a/verilog/sd2snes/main.v b/verilog/sd2snes/main.v index 027c7df..dd613a4 100644 --- a/verilog/sd2snes/main.v +++ b/verilog/sd2snes/main.v @@ -133,6 +133,10 @@ wire [7:0] featurebits; wire [23:0] MAPPED_SNES_ADDR; wire ROM_ADDR0; +wire [9:0] bs_page; +wire [8:0] bs_page_offset; +wire bs_page_enable; + sd_dma snes_sd_dma( .CLK(CLK2), .SD_DAT(SD_DAT), @@ -227,7 +231,11 @@ bsx snes_bsx( .reg_set_bits(bsx_regs_set_bits), .data_ovr(bsx_data_ovr), .flash_writable(IS_FLASHWR), - .rtc_data(rtc_data[55:0]) + .rtc_data(rtc_data[59:0]), + .bs_page_out(bs_page), // support only page 0000-03ff + .bs_page_enable(bs_page_enable), + .bs_page_offset(bs_page_offset) + ); spi snes_spi( @@ -390,6 +398,9 @@ address snes_addr( //BS-X .use_bsx(use_bsx), .bsx_regs(bsx_regs), + .bs_page_offset(bs_page_offset), + .bs_page(bs_page), + .bs_page_enable(bs_page_enable), //SRTC .srtc_enable(srtc_enable), //uPD77C25 @@ -429,13 +440,13 @@ parameter ROM_WR_WAIT_MCU = 4'h6; reg [17:0] STATE; initial STATE = ST_IDLE; +reg [7:0] SNES_DINr; +reg [7:0] ROM_DOUTr; + assign DSPX_SNES_DATA_IN = SNES_DATA; assign SRTC_SNES_DATA_IN = SNES_DATA[3:0]; assign MSU_SNES_DATA_IN = SNES_DATA; -assign BSX_SNES_DATA_IN = SNES_DATA; - -reg [7:0] SNES_DINr; -reg [7:0] ROM_DOUTr; +assign BSX_SNES_DATA_IN = bs_page_enable ? SNES_DINr : SNES_DATA; reg [7:0] r213fr; reg r213f_forceread; @@ -645,6 +656,7 @@ assign SNES_DATABUS_OE = (dspx_enable | dspx_dp_enable) ? 1'b0 : msu_enable ? 1'b0 : bsx_data_ovr ? (SNES_READ & SNES_WRITE) : srtc_enable ? (SNES_READ & SNES_WRITE) : + bs_page_enable ? (SNES_READ) : r213f_enable & !SNES_PARD ? 1'b0 : ((IS_ROM & SNES_CS) |(!IS_ROM & !IS_SAVERAM & !IS_WRITABLE & !IS_FLASHWR)