From 04bc32de86e04b6df904b1b016c4925189afc96d Mon Sep 17 00:00:00 2001 From: ikari Date: Mon, 14 Mar 2011 01:53:18 +0100 Subject: [PATCH] FPGA: fix BS-X mapping, S-RTC interface --- verilog/sd2snes/address.v | 9 +- verilog/sd2snes/clk_test.v | 2 +- verilog/sd2snes/data.v | 9 +- verilog/sd2snes/main.ucf | 6 +- verilog/sd2snes/main.v | 40 ++++++-- verilog/sd2snes/mcu_cmd.v | 17 +++- verilog/sd2snes/rtc.v | 12 ++- verilog/sd2snes/sd2snes.xise | 20 ++-- verilog/sd2snes/srtc.v | 186 +++++++++++++++++++++++++++++++++++ 9 files changed, 272 insertions(+), 29 deletions(-) create mode 100644 verilog/sd2snes/srtc.v diff --git a/verilog/sd2snes/address.v b/verilog/sd2snes/address.v index a6f7b40..a7413c2 100644 --- a/verilog/sd2snes/address.v +++ b/verilog/sd2snes/address.v @@ -36,6 +36,7 @@ module address( input [23:0] ROM_MASK, input use_msu, output msu_enable, + output srtc_enable, output use_bsx, input [14:0] bsx_regs ); @@ -126,13 +127,13 @@ assign SRAM_ADDR_FULL = (MODE) ? MCU_ADDR : ({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)) + : IS_WRITABLE ? (24'h400000 + (SNES_ADDR & 24'h0FFFFF /*7ffff*/)) : ((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])))) + + 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]}) @@ -151,4 +152,6 @@ assign ROM_ADDR0 = SRAM_ADDR_FULL[0]; assign msu_enable = (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfff8) == 16'h2000)); assign use_bsx = (MAPPER == 3'b011); +assign srtc_enable = (!SNES_ADDR[22] && ((SNES_ADDR[15:0] & 16'hfffe) == 16'h2800)); + endmodule diff --git a/verilog/sd2snes/clk_test.v b/verilog/sd2snes/clk_test.v index 2298062..c0051e7 100644 --- a/verilog/sd2snes/clk_test.v +++ b/verilog/sd2snes/clk_test.v @@ -39,7 +39,7 @@ always @(posedge clk) sysclk_sreg <= {sysclk_sreg[0], sysclk}; wire sysclk_rising = (sysclk_sreg == 2'b01); always @(posedge clk) begin - if(sysclk_counter < 92000000) begin + if(sysclk_counter < 96000000) begin sysclk_counter <= sysclk_counter + 1; if(sysclk_rising) sysclk_value <= sysclk_value + 1; end else begin diff --git a/verilog/sd2snes/data.v b/verilog/sd2snes/data.v index ae12ebf..86ef904 100644 --- a/verilog/sd2snes/data.v +++ b/verilog/sd2snes/data.v @@ -39,8 +39,11 @@ module data( input [7:0] MSU_DATA_OUT, output [7:0] BSX_DATA_IN, input [7:0] BSX_DATA_OUT, + output [7:0] SRTC_DATA_IN, + input [7:0] SRTC_DATA_OUT, input msu_enable, - input bsx_data_ovr + input bsx_data_ovr, + input srtc_enable ); reg [7:0] SNES_IN_MEM; @@ -52,9 +55,11 @@ wire [7:0] FROM_ROM_BYTE; assign MSU_DATA_IN = SNES_DATA; assign BSX_DATA_IN = SNES_DATA; +assign SRTC_DATA_IN = SNES_DATA; assign SNES_DATA = SNES_READ ? 8'bZ : (!MCU_OVR ? 8'h00 : (msu_enable ? MSU_DATA_OUT : - bsx_data_ovr ? BSX_DATA_OUT : SNES_OUT_MEM)); + bsx_data_ovr ? BSX_DATA_OUT : + srtc_enable ? SRTC_DATA_OUT : SNES_OUT_MEM)); assign FROM_ROM_BYTE = (ROM_ADDR0 ? ROM_DATA[7:0] : ROM_DATA[15:8]); diff --git a/verilog/sd2snes/main.ucf b/verilog/sd2snes/main.ucf index 7d8c046..a818ae3 100644 --- a/verilog/sd2snes/main.ucf +++ b/verilog/sd2snes/main.ucf @@ -1,5 +1,5 @@ NET "CLKIN" TNM_NET = "CLKIN"; -TIMESPEC TS_CLKIN = PERIOD "CLKIN" 23 MHz HIGH 50 %; +TIMESPEC TS_CLKIN = PERIOD "CLKIN" 24 MHz HIGH 50 %; //TIMESPEC TS_CLKIN = PERIOD "CLKIN" 21.5 MHz HIGH 50 %; NET "SNES_CS" IOSTANDARD = LVCMOS33; NET "SNES_READ" IOSTANDARD = LVCMOS33; @@ -416,7 +416,7 @@ NET "SNES_ADDR[9]" IOSTANDARD = LVCMOS33; NET "SNES_ADDR[9]" DRIVE = 8; -NET "SNES_CPU_CLK" LOC = P94; +NET "SNES_CPU_CLK" LOC = P95; NET "SNES_CS" LOC = P116; NET "SNES_DATABUS_DIR" LOC = P111; NET "SNES_DATABUS_OE" LOC = P109; @@ -443,7 +443,7 @@ NET "SNES_DATA[7]" DRIVE = 8; NET "SNES_IRQ" LOC = P114; NET "SNES_READ" LOC = P115; NET "SNES_REFRESH" LOC = P155; -NET "SNES_WRITE" LOC = P95; +NET "SNES_WRITE" LOC = P94; NET "SPI_MISO" LOC = P72; diff --git a/verilog/sd2snes/main.v b/verilog/sd2snes/main.v index 80e8475..5cf37ad 100644 --- a/verilog/sd2snes/main.v +++ b/verilog/sd2snes/main.v @@ -114,8 +114,9 @@ wire [7:0] bsx_regs_set_bits; wire [59:0] rtc_data; wire [59:0] rtc_data_in; -wire [7:0] RTC_SNES_DATA_IN; -wire [7:0] RTC_SNES_DATA_OUT; +wire [59:0] srtc_rtc_data_out; +wire [7:0] SRTC_SNES_DATA_IN; +wire [7:0] SRTC_SNES_DATA_OUT; //wire SD_DMA_EN; //SPI_DMA_CTRL; @@ -148,11 +149,28 @@ dac snes_dac(.clkin(CLK2), .reset(dac_reset) ); +srtc snes_srtc ( + .clkin(CLK2), + /*XXX*/.reg_addr(srtc_reg_addr), + .addr_in(SNES_ADDR[0]), + .data_in(SRTC_SNES_DATA_IN), + .data_out(SRTC_SNES_DATA_OUT), + .rtc_data_in(rtc_data), + .reg_we(SNES_WRITE), + .reg_oe(SNES_READ), + .enable(srtc_enable), + .rtc_data_out(srtc_rtc_data_out), + .rtc_we(srtc_rtc_we), + .reset(srtc_reset) + ); + rtc snes_rtc ( .clkin(CLKIN), .rtc_data(rtc_data), .rtc_data_in(rtc_data_in), - .pgm_we(rtc_pgm_we) + .pgm_we(rtc_pgm_we), + .rtc_data_in1(srtc_rtc_data_out), + .we1(srtc_rtc_we) ); msu snes_msu ( @@ -260,7 +278,8 @@ mcu_cmd snes_mcu_cmd( .bsx_regs_reset_out(bsx_regs_reset_bits), .bsx_regs_reset_we(bsx_regs_reset_we), .rtc_data_out(rtc_data_in), - .rtc_pgm_we(rtc_pgm_we) + .rtc_pgm_we(rtc_pgm_we), + .srtc_reset(srtc_reset) ); // dcm1: dfs 4x @@ -368,7 +387,9 @@ address snes_addr( .msu_enable(msu_enable), //BS-X .use_bsx(use_bsx), - .bsx_regs(bsx_regs) + .bsx_regs(bsx_regs), + //SRTC + .srtc_enable(srtc_enable) ); wire SNES_READ_CYCLEw; @@ -396,8 +417,11 @@ data snes_data(.CLK(CLK2), .MSU_DATA_OUT(MSU_SNES_DATA_OUT), .BSX_DATA_IN(BSX_SNES_DATA_IN), .BSX_DATA_OUT(BSX_SNES_DATA_OUT), + .SRTC_DATA_IN(SRTC_SNES_DATA_IN), + .SRTC_DATA_OUT(SRTC_SNES_DATA_OUT), .msu_enable(msu_enable), - .bsx_data_ovr(bsx_data_ovr) + .bsx_data_ovr(bsx_data_ovr), + .srtc_enable(srtc_enable) ); parameter MODE_SNES = 1'b0; @@ -515,6 +539,7 @@ always @(posedge CLK2) begin end else begin case (STATE) STATE_0: begin + SNES_WRITE_CYCLE <= SNES_WRITE; STATE <= STATE_1; STATEIDX <= 11; end STATE_1: begin @@ -634,7 +659,8 @@ assign ROM_BLE = !ROM_WE ? !ROM_ADDR0 : 1'b0; //assign SNES_DATABUS_OE = (!IS_SAVERAM & SNES_CS) | (SNES_READ & SNES_WRITE); assign SNES_DATABUS_OE = msu_enable ? 1'b0 : - bsx_data_ovr ? 1'b0 : ((IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM & !IS_WRITABLE & !IS_FLASHWR) | (SNES_READ & SNES_WRITE)); + bsx_data_ovr ? 1'b0 : + srtc_enable ? 1'b0 : ((IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM & !IS_WRITABLE & !IS_FLASHWR) | (SNES_READ & SNES_WRITE)); assign SNES_DATABUS_DIR = !SNES_READ ? 1'b1 : 1'b0; assign SNES_DATA_TO_MEM = SNES_DATA_TO_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX]; diff --git a/verilog/sd2snes/mcu_cmd.v b/verilog/sd2snes/mcu_cmd.v index 6119110..c335a67 100644 --- a/verilog/sd2snes/mcu_cmd.v +++ b/verilog/sd2snes/mcu_cmd.v @@ -80,6 +80,9 @@ module mcu_cmd( output [55:0] rtc_data_out, output rtc_pgm_we, + // S-RTC + output srtc_reset, + // SNES sync/clk input snes_sysclk ); @@ -118,6 +121,8 @@ reg bsx_regs_reset_we_buf; reg [55:0] rtc_data_out_buf; reg rtc_pgm_we_buf; +reg srtc_reset_buf; + reg [31:0] SNES_SYSCLK_FREQ_BUF; reg [7:0] MCU_DATA_OUT_BUF; @@ -332,7 +337,15 @@ always @(posedge clk) begin 32'h4: bsx_regs_reset_we_buf <= 1'b0; endcase - + 8'he7: + case (spi_byte_cnt) + 32'h2: begin + srtc_reset_buf <= 1'b1; + end + 32'h3: begin + srtc_reset_buf <= 1'b0; + end + endcase endcase end if (SD_DMA_NEXTADDR | (mcu_nextaddr & (cmd_data[7:5] == 3'h4) && (cmd_data[3]) && (spi_byte_cnt > (32'h1+cmd_data[4])))) begin @@ -447,6 +460,8 @@ assign bsx_regs_set_out = bsx_regs_set_out_buf; assign rtc_data_out = rtc_data_out_buf; assign rtc_pgm_we = rtc_pgm_we_buf; +assign srtc_reset = srtc_reset_buf; + assign mcu_data_out = SD_DMA_STATUS ? SD_DMA_SRAM_DATA : MCU_DATA_OUT_BUF; assign mcu_mapper = MAPPER_BUF; assign mcu_sram_size = SRAM_SIZE_BUF; diff --git a/verilog/sd2snes/rtc.v b/verilog/sd2snes/rtc.v index 9b162fa..08adfe2 100644 --- a/verilog/sd2snes/rtc.v +++ b/verilog/sd2snes/rtc.v @@ -22,6 +22,8 @@ module rtc ( input clkin, input pgm_we, input [59:0] rtc_data_in, + input we1, + input [59:0] rtc_data_in1, output [59:0] rtc_data ); @@ -32,11 +34,15 @@ reg [1:0] pgm_we_sreg; always @(posedge clkin) pgm_we_sreg <= {pgm_we_sreg[0], pgm_we}; wire pgm_we_rising = (pgm_we_sreg[1:0] == 2'b01); +reg [2:0] we1_sreg; +always @(posedge clkin) we1_sreg <= {we1_sreg[1:0], we1}; +wire we1_rising = (we1_sreg[2:1] == 2'b01); + reg [31:0] tick_cnt; always @(posedge clkin) begin tick_cnt <= tick_cnt + 1; - if(tick_cnt == 23000000) tick_cnt <= 0; + if((tick_cnt == 24000000) || pgm_we_rising) tick_cnt <= 0; end assign rtc_data = rtc_data_out_r; @@ -97,7 +103,7 @@ initial begin dom1[10] <= 0; dom10[10] <= 3; dom1[11] <= 1; dom10[11] <= 3; month <= 0; - rtc_data_r <= 60'h019900101000000; + rtc_data_r <= 60'h220110301000000; tick_cnt <= 0; end @@ -163,6 +169,8 @@ end always @(posedge clkin) begin if(pgm_we_rising) begin rtc_data_r <= rtc_data_in; + end else if (we1_rising) begin + rtc_data_r <= rtc_data_in1; end else begin case(rtc_state) STATE_SEC1: begin diff --git a/verilog/sd2snes/sd2snes.xise b/verilog/sd2snes/sd2snes.xise index 0b967fe..ee2438c 100644 --- a/verilog/sd2snes/sd2snes.xise +++ b/verilog/sd2snes/sd2snes.xise @@ -113,7 +113,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -216,7 +216,7 @@ - + @@ -267,7 +267,7 @@ - + @@ -309,7 +309,7 @@ - + @@ -337,8 +337,8 @@ - - + + @@ -372,7 +372,7 @@ - + @@ -395,7 +395,7 @@ - + @@ -487,7 +487,7 @@ - + diff --git a/verilog/sd2snes/srtc.v b/verilog/sd2snes/srtc.v new file mode 100644 index 0000000..9ad26c4 --- /dev/null +++ b/verilog/sd2snes/srtc.v @@ -0,0 +1,186 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 13:33:14 02/09/2011 +// Design Name: +// Module Name: srtc +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module srtc( + input clkin, + input [4:0] reg_addr, + input addr_in, + input [7:0] data_in, + output [7:0] data_out, + input [59:0] rtc_data_in, + output [59:0] rtc_data_out, + input reg_we, + input reg_oe, + input enable, + output rtc_we, + input reset + ); + +reg rtc_dirty_r; +assign rtc_dirty = rtc_dirty_r; + +reg [59:0] rtc_data_r; +reg [59:0] rtc_data_out_r; +assign rtc_data_out = rtc_data_out_r; + +reg [3:0] rtc_ptr; + +reg [7:0] data_out_r; +reg [7:0] data_in_r; +reg [4:0] mode_r; +reg [3:0] command_r; +reg rtc_we_r; +assign rtc_we = rtc_we_r; +assign data_out = data_out_r; + +reg [5:0] reg_oe_sreg; +always @(posedge clkin) reg_oe_sreg <= {reg_oe_sreg[4:0], reg_oe}; +wire reg_oe_falling = (reg_oe_sreg[5:0] == 6'b100000); +wire reg_oe_rising = (reg_oe_sreg[5:0] == 6'b000001); + +reg [1:0] reg_we_sreg; +always @(posedge clkin) reg_we_sreg <= {reg_we_sreg[0], reg_we}; +wire reg_we_rising = (reg_we_sreg[1:0] == 2'b01); + +reg [1:0] reset_sreg; +always @(posedge clkin) reset_sreg <= {reset_sreg[0], reset}; +wire reset_rising = (reset_sreg[1:0] == 2'b01); + +reg[2:0] we_countdown_r; + +parameter SRTC_IDLE = 5'b00001; +parameter SRTC_READ = 5'b00010; +parameter SRTC_COMMAND = 5'b00100; +parameter SRTC_WRITE = 5'b01000; +parameter SRTC_WRITE2 = 5'b10000; + +initial begin + rtc_we_r = 0; + mode_r <= SRTC_READ; + rtc_ptr <= 4'hf; +end + +always @(posedge clkin) begin + if(reset_rising) begin + mode_r <= SRTC_READ; + rtc_ptr <= 4'hf; + end else if(mode_r == SRTC_WRITE2) begin + we_countdown_r <= we_countdown_r - 1; + if (we_countdown_r == 3'b000) begin + mode_r <= SRTC_WRITE; + rtc_we_r <= 0; + end + end else if(reg_we_rising && enable) begin + case (addr_in) +// 1'b0: // data register is read only + + 1'b1: // control register + case (data_in[3:0]) + 4'hd: begin + mode_r <= SRTC_READ; + rtc_ptr <= 4'hf; + end + 4'he: begin + mode_r <= SRTC_COMMAND; + end + 4'hf: begin + end + default: begin + if(mode_r == SRTC_COMMAND) begin + case (data_in[3:0]) + 4'h0: begin + mode_r <= SRTC_WRITE; + rtc_data_out_r <= rtc_data_in; + rtc_ptr <= 4'h0; + end + 4'h4: begin + mode_r <= SRTC_IDLE; + rtc_ptr <= 4'hf; + end + default: + mode_r <= SRTC_IDLE; + endcase + end else if(mode_r == SRTC_WRITE) begin + rtc_ptr <= rtc_ptr + 1; + case(rtc_ptr) + 0: rtc_data_out_r[3:0] <= data_in[3:0]; + 1: rtc_data_out_r[7:4] <= data_in[3:0]; + 2: rtc_data_out_r[11:8] <= data_in[3:0]; + 3: rtc_data_out_r[15:12] <= data_in[3:0]; + 4: rtc_data_out_r[19:16] <= data_in[3:0]; + 5: rtc_data_out_r[23:20] <= data_in[3:0]; + 6: rtc_data_out_r[27:24] <= data_in[3:0]; + 7: rtc_data_out_r[31:28] <= data_in[3:0]; + 8: begin + rtc_data_out_r[35:32] <= data_in[3:0] < 10 ? data_in[3:0] + : data_in[3:0] - 10; + rtc_data_out_r[39:36] <= data_in[3:0] < 10 ? 0 : 1; + end + 9: rtc_data_out_r[43:40] <= data_in[3:0]; + 10: rtc_data_out_r[47:44] <= data_in[3:0]; + 11: begin + rtc_data_out_r[51:48] <= data_in[3:0] < 10 ? data_in[3:0] + : data_in[3:0] - 10; + rtc_data_out_r[55:52] <= data_in[3:0] < 10 ? 1 : 2; + end + default: + rtc_dirty_r <= 1; + endcase + mode_r <= SRTC_WRITE2; + we_countdown_r <= 5; + rtc_we_r <= 1; + end + end + endcase + endcase + end else if(reg_oe_falling && enable) begin + case (addr_in) + 1'b0: // read data register + if(mode_r == SRTC_READ) begin + case(rtc_ptr) + 0: data_out_r <= rtc_data_r[3:0]; + 1: data_out_r <= rtc_data_r[7:4]; + 2: data_out_r <= rtc_data_r[11:8]; + 3: data_out_r <= rtc_data_r[15:12]; + 4: data_out_r <= rtc_data_r[19:16]; + 5: data_out_r <= rtc_data_r[23:20]; + 6: data_out_r <= rtc_data_r[27:24]; + 7: data_out_r <= rtc_data_r[31:28]; + 8: data_out_r <= rtc_data_r[35:32] + (rtc_data_r[39:36] << 1) + (rtc_data_r[39:36] << 3); + 9: data_out_r <= rtc_data_r[43:40]; + 10: data_out_r <= rtc_data_r[47:44]; + 11: data_out_r <= rtc_data_r[51:48] + (rtc_data_r[55:52] << 1) + (rtc_data_r[55:52] << 3) - 10; + 12: data_out_r <= rtc_data_r[59:56]; + 15: begin + rtc_data_r <= rtc_data_in; + data_out_r <= 8'h0f; + end + default: data_out_r <= 8'h0f; + endcase + rtc_ptr <= rtc_ptr == 13 ? 15 : rtc_ptr + 1; + end else begin + data_out_r <= 8'h00; + end +// 1'b1: // control register is write only + endcase + end +end + +endmodule