From 7e8f5679e64ca736ef400118552b085bfbf274c3 Mon Sep 17 00:00:00 2001 From: ikari Date: Sun, 13 Feb 2011 00:52:14 +0100 Subject: [PATCH] FPGA: RTC fixes + calculate day of week --- verilog/sd2snes/bsx.v | 28 ++- verilog/sd2snes/main.v | 22 ++- verilog/sd2snes/rtc.v | 381 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 419 insertions(+), 12 deletions(-) create mode 100644 verilog/sd2snes/rtc.v diff --git a/verilog/sd2snes/bsx.v b/verilog/sd2snes/bsx.v index 62cd0cc..a2ec578 100644 --- a/verilog/sd2snes/bsx.v +++ b/verilog/sd2snes/bsx.v @@ -32,7 +32,8 @@ module bsx( input [14:0] regs_in, input use_bsx, output data_ovr, - output flash_writable + output flash_writable, + input [59:0] rtc_data ); wire [3:0] reg_addr = snes_addr[19:16]; // 00-0f:5000-5fff @@ -54,6 +55,7 @@ wire is_flash_special_address = (flash_addr == 16'h0002 || flash_addr == 16'h2aaa || flash_addr == 16'h0000 || (flash_addr >= 16'hff00 && flash_addr <= 16'hff13)); + wire flash_ovr = (use_bsx) && (flash_enable & flash_ovr_r) && is_flash_special_address; assign flash_writable = (use_bsx) && flash_enable && flash_we_r && !is_flash_special_address; @@ -83,6 +85,13 @@ reg [7:0] flash_vendor_data[7:0]; assign regs_out = regs_outr; assign reg_data_out = reg_data_outr; +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); +wire [7:0] rtc_month = rtc_data[35:32] + (rtc_data[39:36] << 3) + (rtc_data[39:36] << 1); +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); initial begin regs_tmpr <= 16'b0_000000100000000; @@ -140,11 +149,11 @@ always @(posedge clkin) begin 6: reg_data_outr <= 8'h1; 10: - reg_data_outr <= 8'd42; + reg_data_outr <= rtc_sec; 11: - reg_data_outr <= 8'd30; + reg_data_outr <= rtc_min; 12: - reg_data_outr <= 8'd18; + reg_data_outr <= rtc_hour; default: reg_data_outr <= 8'h0; endcase @@ -180,13 +189,16 @@ 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'b10001: begin + 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; + end + 5'h11: begin bsx_counter <= 0; base_regs[base_addr] <= reg_data_in; end - 5'b01111: 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'h12: begin + base_regs[8'h10] <= 8'h80; end default: base_regs[base_addr] <= reg_data_in; diff --git a/verilog/sd2snes/main.v b/verilog/sd2snes/main.v index 0e6c09a..80e8475 100644 --- a/verilog/sd2snes/main.v +++ b/verilog/sd2snes/main.v @@ -112,6 +112,10 @@ wire [7:0] BSX_SNES_DATA_OUT; wire [7:0] bsx_regs_reset_bits; 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 SD_DMA_EN; //SPI_DMA_CTRL; @@ -128,8 +132,8 @@ sd_dma snes_sd_dma(.CLK(CLK2), .SD_DMA_PARTIAL_START(SD_DMA_PARTIAL_START), .SD_DMA_PARTIAL_END(SD_DMA_PARTIAL_END) ); - -dac_test snes_dac_test(.clkin(CLK2), + +dac snes_dac(.clkin(CLK2), .sysclk(SNES_SYSCLK), .mclk(DAC_MCLK), .lrck(DAC_LRCK), @@ -144,6 +148,13 @@ dac_test snes_dac_test(.clkin(CLK2), .reset(dac_reset) ); +rtc snes_rtc ( + .clkin(CLKIN), + .rtc_data(rtc_data), + .rtc_data_in(rtc_data_in), + .pgm_we(rtc_pgm_we) + ); + msu snes_msu ( .clkin(CLK2), .enable(msu_enable), @@ -179,7 +190,8 @@ bsx snes_bsx(.clkin(CLK2), .reg_reset_bits(bsx_regs_reset_bits), .reg_set_bits(bsx_regs_set_bits), .data_ovr(bsx_data_ovr), - .flash_writable(IS_FLASHWR) + .flash_writable(IS_FLASHWR), + .rtc_data(rtc_data) ); spi snes_spi(.clk(CLK2), @@ -246,7 +258,9 @@ mcu_cmd snes_mcu_cmd( .msu_reset_out(msu_addr_reset), .bsx_regs_set_out(bsx_regs_set_bits), .bsx_regs_reset_out(bsx_regs_reset_bits), - .bsx_regs_reset_we(bsx_regs_reset_we) + .bsx_regs_reset_we(bsx_regs_reset_we), + .rtc_data_out(rtc_data_in), + .rtc_pgm_we(rtc_pgm_we) ); // dcm1: dfs 4x diff --git a/verilog/sd2snes/rtc.v b/verilog/sd2snes/rtc.v new file mode 100644 index 0000000..9b162fa --- /dev/null +++ b/verilog/sd2snes/rtc.v @@ -0,0 +1,381 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 23:32:12 01/08/2011 +// Design Name: +// Module Name: rtc_srtc +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module rtc ( + input clkin, + input pgm_we, + input [59:0] rtc_data_in, + output [59:0] rtc_data + ); + +reg [59:0] rtc_data_r; +reg [59:0] rtc_data_out_r; + +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 [31:0] tick_cnt; + +always @(posedge clkin) begin + tick_cnt <= tick_cnt + 1; + if(tick_cnt == 23000000) tick_cnt <= 0; +end + +assign rtc_data = rtc_data_out_r; + +reg [21:0] rtc_state; +reg [21:0] next_state; +reg carry; + +reg [3:0] dom1[11:0]; +reg [3:0] dom10[11:0]; +reg [3:0] month; +reg [1:0] year; + +reg [4:0] dow_day; +reg [3:0] dow_month; +reg [13:0] dow_year; +reg [6:0] dow_year1; +reg [6:0] dow_year100; +reg [15:0] dow_tmp; + +parameter [21:0] + STATE_SEC1 = 22'b0000000000000000000001, + STATE_SEC10 = 22'b0000000000000000000010, + STATE_MIN1 = 22'b0000000000000000000100, + STATE_MIN10 = 22'b0000000000000000001000, + STATE_HOUR1 = 22'b0000000000000000010000, + STATE_HOUR10 = 22'b0000000000000000100000, + STATE_DAY1 = 22'b0000000000000001000000, + STATE_DAY10 = 22'b0000000000000010000000, + STATE_MON1 = 22'b0000000000000100000000, + STATE_MON10 = 22'b0000000000001000000000, + STATE_YEAR1 = 22'b0000000000010000000000, + STATE_YEAR10 = 22'b0000000000100000000000, + STATE_YEAR100 = 22'b0000000001000000000000, + STATE_YEAR1000 = 22'b0000000010000000000000, + STATE_DOW0 = 22'b0000000100000000000000, + STATE_DOW1 = 22'b0000001000000000000000, + STATE_DOW2 = 22'b0000010000000000000000, + STATE_DOW3 = 22'b0000100000000000000000, + STATE_DOW4 = 22'b0001000000000000000000, + STATE_DOW5 = 22'b0010000000000000000000, + STATE_LATCH = 22'b0100000000000000000000, + STATE_IDLE = 22'b1000000000000000000000; + +initial begin + rtc_state = STATE_IDLE; + next_state = STATE_IDLE; + dom1[0] <= 1; dom10[0] <= 3; + dom1[1] <= 8; dom10[1] <= 2; + dom1[2] <= 1; dom10[2] <= 3; + dom1[3] <= 0; dom10[3] <= 3; + dom1[4] <= 1; dom10[4] <= 3; + dom1[5] <= 0; dom10[5] <= 3; + dom1[6] <= 1; dom10[6] <= 3; + dom1[7] <= 1; dom10[7] <= 3; + dom1[8] <= 0; dom10[8] <= 3; + dom1[9] <= 1; dom10[9] <= 3; + dom1[10] <= 0; dom10[10] <= 3; + dom1[11] <= 1; dom10[11] <= 3; + month <= 0; + rtc_data_r <= 60'h019900101000000; + tick_cnt <= 0; +end + +wire is_leapyear_feb = (month == 1) && (year[1:0] == 2'b00); + +always @(posedge clkin) begin + + if(!tick_cnt) begin + rtc_state <= STATE_SEC1; + end else begin + case (rtc_state) + STATE_SEC1: + rtc_state <= STATE_SEC10; + STATE_SEC10: + rtc_state <= STATE_MIN1; + STATE_MIN1: + rtc_state <= STATE_MIN10; + STATE_MIN10: + rtc_state <= STATE_HOUR1; + STATE_HOUR1: + rtc_state <= STATE_HOUR10; + STATE_HOUR10: + rtc_state <= STATE_DAY1; + STATE_DAY1: + rtc_state <= STATE_DAY10; + STATE_DAY10: + rtc_state <= STATE_MON1; + STATE_MON1: + rtc_state <= STATE_MON10; + STATE_MON10: + rtc_state <= STATE_YEAR1; + STATE_YEAR1: + rtc_state <= STATE_YEAR10; + STATE_YEAR10: + rtc_state <= STATE_YEAR100; + STATE_YEAR100: + rtc_state <= STATE_YEAR1000; + STATE_YEAR1000: + rtc_state <= STATE_DOW0; + STATE_DOW0: + rtc_state <= STATE_DOW1; + STATE_DOW1: + rtc_state <= STATE_DOW2; + STATE_DOW2: + rtc_state <= STATE_DOW3; + STATE_DOW3: + rtc_state <= STATE_DOW4; + STATE_DOW4: + if(dow_tmp > 13) + rtc_state <= STATE_DOW4; + else + rtc_state <= STATE_DOW5; + STATE_DOW5: + rtc_state <= STATE_LATCH; + STATE_LATCH: + rtc_state <= STATE_IDLE; + default: + rtc_state <= STATE_IDLE; + endcase + end +end + +always @(posedge clkin) begin + if(pgm_we_rising) begin + rtc_data_r <= rtc_data_in; + end else begin + case(rtc_state) + STATE_SEC1: begin + if(rtc_data_r[3:0] == 9) begin + rtc_data_r[3:0] <= 0; + carry <= 1; + end else begin + rtc_data_r[3:0] <= rtc_data_r[3:0] + 1; + carry <= 0; + end + end + STATE_SEC10: begin + if(carry) begin + if(rtc_data_r[7:4] == 5) begin + rtc_data_r[7:4] <= 0; + carry <= 1; + end else begin + rtc_data_r[7:4] <= rtc_data_r[7:4] + 1; + carry <= 0; + end + end + end + STATE_MIN1: begin + if(carry) begin + if(rtc_data_r[11:8] == 9) begin + rtc_data_r[11:8] <= 0; + carry <= 1; + end else begin + rtc_data_r[11:8] <= rtc_data_r[11:8] + 1; + carry <= 0; + end + end + end + STATE_MIN10: begin + if(carry) begin + if(rtc_data_r[15:12] == 5) begin + rtc_data_r[15:12] <= 0; + carry <= 1; + end else begin + rtc_data_r[15:12] <= rtc_data_r[15:12] + 1; + carry <= 0; + end + end + end + STATE_HOUR1: begin + if(carry) begin + if(rtc_data_r[23:20] == 2 && rtc_data_r[19:16] == 3) begin + rtc_data_r[19:16] <= 0; + carry <= 1; + end else if (rtc_data_r[19:16] == 9) begin + rtc_data_r[19:16] <= 0; + carry <= 1; + end else begin + rtc_data_r[19:16] <= rtc_data_r[19:16] + 1; + carry <= 0; + end + end + end + STATE_HOUR10: begin + if(carry) begin + if(rtc_data_r[23:20] == 2) begin + rtc_data_r[23:20] <= 0; + carry <= 1; + end else begin + rtc_data_r[23:20] <= rtc_data_r[23:20] + 1; + carry <= 0; + end + end + end + STATE_DAY1: begin + if(carry) begin + if(rtc_data_r[31:28] == dom10[month] && rtc_data_r[27:24] == dom1[month] + is_leapyear_feb) begin + rtc_data_r[27:24] <= 0; + carry <= 1; + end else if (rtc_data_r[27:24] == 9) begin + rtc_data_r[27:24] <= 0; + carry <= 1; + end else begin + rtc_data_r[27:24] <= rtc_data_r[27:24] + 1; + carry <= 0; + end + end + end + STATE_DAY10: begin + if(carry) begin + if(rtc_data_r[31:28] == dom10[month]) begin + rtc_data_r[31:28] <= 0; + rtc_data_r[27:24] <= 1; + carry <= 1; + end else begin + rtc_data_r[31:28] <= rtc_data_r[31:28] + 1; + carry <= 0; + end + end + end + STATE_MON1: begin + if(carry) begin + if(rtc_data_r[39:36] == 1 && rtc_data_r[35:32] == 2) begin + rtc_data_r[35:32] <= 1; + carry <= 1; + end else if (rtc_data_r[35:32] == 9) begin + rtc_data_r[35:32] <= 0; + carry <= 1; + end else begin + rtc_data_r[35:32] <= rtc_data_r[35:32] + 1; + carry <= 0; + end + end + end + STATE_MON10: begin + if(carry) begin + if(rtc_data_r[39:36] == 1) begin + rtc_data_r[39:36] <= 0; + carry <= 1; + end else begin + rtc_data_r[39:36] <= rtc_data_r[39:36] + 1; + carry <= 0; + end + end + end + STATE_YEAR1: begin + month <= rtc_data_r[35:32] + (rtc_data_r[36] ? 10 : 0) - 1; + if(carry) begin + if(rtc_data_r[43:40] == 9) begin + rtc_data_r[43:40] <= 0; + carry <= 1; + end else begin + rtc_data_r[43:40] <= rtc_data_r[43:40] + 1; + carry <= 0; + end + end + end + STATE_YEAR10: begin + if(carry) begin + if(rtc_data_r[47:44] == 9) begin + rtc_data_r[47:44] <= 0; + carry <= 1; + end else begin + rtc_data_r[47:44] <= rtc_data_r[47:44] + 1; + carry <= 0; + end + end + end + STATE_YEAR100: begin + if(carry) begin + if(rtc_data_r[51:48] == 9) begin + rtc_data_r[51:48] <= 0; + carry <= 1; + end else begin + rtc_data_r[51:48] <= rtc_data_r[51:48] + 1; + carry <= 0; + end + end + end + STATE_YEAR1000: begin + if(carry) begin + if(rtc_data_r[55:52] == 9) begin + rtc_data_r[55:52] <= 0; + carry <= 1; + end else begin + rtc_data_r[55:52] <= rtc_data_r[55:52] + 1; + carry <= 0; + end + end + end + STATE_DOW0: begin + dow_year1 <= rtc_data_r[43:40] + +(rtc_data_r[47:44] << 1) + (rtc_data_r[47:44] << 3); + + dow_year100 <= rtc_data_r[51:48] + +(rtc_data_r[55:52] << 1) + (rtc_data_r[55:52] << 3); + + dow_month <= month + 1; + dow_day <= rtc_data_r[27:24] + (rtc_data_r[31:28] << 1) + (rtc_data_r[31:28] << 3); + end + STATE_DOW1: begin + year <= dow_year1[1:0]; + if(dow_month <= 2) begin + dow_month <= dow_month + 10; + dow_year <= dow_year1 + (dow_year100 << 2) + (dow_year100 << 5) + (dow_year100 << 6) - 1; + if(dow_year1) + dow_year1 <= dow_year1 - 1; + else begin + dow_year1 <= 99; + dow_year100 <= dow_year100 - 1; + end + end else begin + dow_month <= dow_month - 2; + dow_year <= dow_year1 + (dow_year100 << 2) + (dow_year100 << 5) + (dow_year100 << 6); + end + end + STATE_DOW2: begin + dow_tmp <= (83 * dow_month); + end + STATE_DOW3: begin + dow_tmp <= (dow_tmp >> 5) + + dow_day + + dow_year + + (dow_year >> 2) + - (dow_year100) + + (dow_year100 >> 2); + end + STATE_DOW4: begin + dow_tmp <= dow_tmp - 7; + end + STATE_DOW5: begin + rtc_data_r[59:56] <= {1'b0, dow_tmp[2:0]}; + end + STATE_LATCH: begin + rtc_data_out_r <= rtc_data_r; + end + endcase + end +end + +endmodule