mirror of
https://github.com/MiSTer-devel/MSX_MiSTer.git
synced 2026-05-24 03:03:50 +00:00
599 lines
24 KiB
VHDL
599 lines
24 KiB
VHDL
--
|
|
-- rtc.vhd
|
|
-- REAL TIME CLOCK (MSX2 CLOCK-IC)
|
|
-- Version 1.00
|
|
--
|
|
-- Copyright (c) 2008 Takayuki Hara
|
|
-- All rights reserved.
|
|
--
|
|
-- Redistribution and use of this source code or any derivative works, are
|
|
-- permitted provided that the following conditions are met:
|
|
--
|
|
-- 1. Redistributions of source code must retain the above copyright notice,
|
|
-- this list of conditions and the following disclaimer.
|
|
-- 2. Redistributions in binary form must reproduce the above copyright
|
|
-- notice, this list of conditions and the following disclaimer in the
|
|
-- documentation and/or other materials provided with the distribution.
|
|
-- 3. Redistributions may not be sold, nor may they be used in a commercial
|
|
-- product or activity without specific prior written permission.
|
|
--
|
|
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
-- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
-- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
--
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
entity rtc is
|
|
port(
|
|
clk21m : in std_logic;
|
|
reset : in std_logic;
|
|
|
|
setup : in std_logic;
|
|
rt : in std_logic_vector( 64 downto 0 );
|
|
|
|
clkena : in std_logic; -- 10Hz
|
|
req : in std_logic;
|
|
ack : out std_logic;
|
|
wrt : in std_logic;
|
|
adr : in std_logic_vector( 15 downto 0 );
|
|
dbi : out std_logic_vector( 7 downto 0 );
|
|
dbo : in std_logic_vector( 7 downto 0 )
|
|
);
|
|
end rtc;
|
|
|
|
architecture rtl of rtc is
|
|
|
|
-- ff
|
|
signal ff_req : std_logic;
|
|
signal ff_1sec_cnt : std_logic_vector( 3 downto 0 );
|
|
|
|
-- register ff
|
|
signal reg_ptr : std_logic_vector( 3 downto 0 );
|
|
signal reg_mode : std_logic_vector( 3 downto 0 ); -- te, ae(not supported), m1, m0
|
|
signal reg_sec_l : std_logic_vector( 3 downto 0 ); -- hl = x"00" ... x"59"
|
|
signal reg_sec_h : std_logic_vector( 6 downto 4 );
|
|
signal reg_min_l : std_logic_vector( 3 downto 0 ); -- hl = x"00" ... x"59"
|
|
signal reg_min_h : std_logic_vector( 6 downto 4 );
|
|
signal reg_hou_l : std_logic_vector( 3 downto 0 ); -- hl = x"00" ... x"23"
|
|
signal reg_hou_h : std_logic_vector( 5 downto 4 ); -- hl = x"00" ... x"23"
|
|
signal reg_wee : std_logic_vector( 2 downto 0 ); -- x"0" ... x"6"
|
|
signal reg_day_l : std_logic_vector( 3 downto 0 ); -- hl = x"00" ... x"31"
|
|
signal reg_day_h : std_logic_vector( 5 downto 4 ); --
|
|
signal reg_mon_l : std_logic_vector( 3 downto 0 ); -- hl = x"01" ... x"12"
|
|
signal reg_mon_h : std_logic;
|
|
signal reg_yea_l : std_logic_vector( 3 downto 0 ); -- hl = x"00" ... x"99"
|
|
signal reg_yea_h : std_logic_vector( 7 downto 4 );
|
|
signal reg_1224 : std_logic; -- '0' = 12hour mode, '1' = 24hour mode
|
|
signal reg_leap : std_logic_vector( 1 downto 0 ); -- "00" leap year, "01" ... "11" other year
|
|
|
|
-- wire
|
|
signal w_adr_dec : std_logic_vector( 15 downto 0 );
|
|
signal w_bank_dec : std_logic_vector( 2 downto 0 );
|
|
signal w_wrt : std_logic;
|
|
signal w_mem_we : std_logic;
|
|
signal w_mem_addr : std_logic_vector( 7 downto 0 );
|
|
signal w_mem_q : std_logic_vector( 7 downto 0 );
|
|
signal w_1sec : std_logic;
|
|
signal w_10sec : std_logic;
|
|
signal w_60sec : std_logic;
|
|
signal w_10min : std_logic;
|
|
signal w_60min : std_logic;
|
|
signal w_10hour : std_logic;
|
|
signal w_1224hour : std_logic;
|
|
signal w_10day : std_logic;
|
|
signal w_next_mon : std_logic;
|
|
signal w_10mon : std_logic;
|
|
signal w_1year : std_logic;
|
|
signal w_10year : std_logic;
|
|
signal w_100year : std_logic;
|
|
signal w_enable : std_logic;
|
|
begin
|
|
|
|
----------------------------------------------------------------
|
|
-- address decoder
|
|
----------------------------------------------------------------
|
|
with reg_ptr select w_adr_dec <=
|
|
"0000000000000001" when "0000",
|
|
"0000000000000010" when "0001",
|
|
"0000000000000100" when "0010",
|
|
"0000000000001000" when "0011",
|
|
"0000000000010000" when "0100",
|
|
"0000000000100000" when "0101",
|
|
"0000000001000000" when "0110",
|
|
"0000000010000000" when "0111",
|
|
"0000000100000000" when "1000",
|
|
"0000001000000000" when "1001",
|
|
"0000010000000000" when "1010",
|
|
"0000100000000000" when "1011",
|
|
"0001000000000000" when "1100",
|
|
"0010000000000000" when "1101",
|
|
"0100000000000000" when "1110",
|
|
"1000000000000000" when "1111",
|
|
"XXXXXXXXXXXXXXXX" when others;
|
|
|
|
with reg_mode( 1 downto 0 ) select w_bank_dec <=
|
|
"001" when "00",
|
|
"010" when "01",
|
|
"100" when "10",
|
|
"100" when "11",
|
|
"XXX" when others;
|
|
|
|
w_wrt <= req and wrt;
|
|
|
|
----------------------------------------------------------------
|
|
-- rtc register read
|
|
----------------------------------------------------------------
|
|
dbi <= "1111" & reg_mode when( w_adr_dec(13) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_sec_l when( w_bank_dec(0) = '1' and w_adr_dec( 0) = '1' and adr(0) = '1' )else
|
|
"11110" & reg_sec_h when( w_bank_dec(0) = '1' and w_adr_dec( 1) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_min_l when( w_bank_dec(0) = '1' and w_adr_dec( 2) = '1' and adr(0) = '1' )else
|
|
"11110" & reg_min_h when( w_bank_dec(0) = '1' and w_adr_dec( 3) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_hou_l when( w_bank_dec(0) = '1' and w_adr_dec( 4) = '1' and adr(0) = '1' )else
|
|
"111100" & reg_hou_h when( w_bank_dec(0) = '1' and w_adr_dec( 5) = '1' and adr(0) = '1' )else
|
|
"11110" & reg_wee when( w_bank_dec(0) = '1' and w_adr_dec( 6) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_day_l when( w_bank_dec(0) = '1' and w_adr_dec( 7) = '1' and adr(0) = '1' )else
|
|
"111100" & reg_day_h when( w_bank_dec(0) = '1' and w_adr_dec( 8) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_mon_l when( w_bank_dec(0) = '1' and w_adr_dec( 9) = '1' and adr(0) = '1' )else
|
|
"1111000" & reg_mon_h when( w_bank_dec(0) = '1' and w_adr_dec(10) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_yea_l when( w_bank_dec(0) = '1' and w_adr_dec(11) = '1' and adr(0) = '1' )else
|
|
"1111" & reg_yea_h when( w_bank_dec(0) = '1' and w_adr_dec(12) = '1' and adr(0) = '1' )else
|
|
"111100" & reg_leap when( w_bank_dec(1) = '1' and w_adr_dec(11) = '1' and adr(0) = '1' )else
|
|
"1111" & w_mem_q(3 downto 0) when( w_bank_dec(2) = '1' and adr(0) = '1' )else
|
|
(others => '1');
|
|
|
|
----------------------------------------------------------------
|
|
-- request and ack
|
|
----------------------------------------------------------------
|
|
process( reset, clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( reset = '1' )then
|
|
ff_req <= '0';
|
|
else
|
|
ff_req <= req;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
ack <= ff_req;
|
|
|
|
----------------------------------------------------------------
|
|
-- mode register [te bit]
|
|
----------------------------------------------------------------
|
|
w_enable <= clkena and reg_mode(3);
|
|
|
|
----------------------------------------------------------------
|
|
-- 1sec timer
|
|
----------------------------------------------------------------
|
|
process( reset, clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( reset = '1' )then
|
|
ff_1sec_cnt <= "1001";
|
|
else
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(1) = '1' and w_adr_dec(15) = '1' )then
|
|
-- reset register [cr bit]
|
|
if( dbo(1) = '1' )then
|
|
ff_1sec_cnt <= "1001";
|
|
end if;
|
|
elsif( w_1sec = '1' )then
|
|
ff_1sec_cnt <= "1001";
|
|
elsif( w_enable = '1' )then
|
|
ff_1sec_cnt <= ff_1sec_cnt - 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_1sec <= w_enable when( ff_1sec_cnt = "0000" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 10sec timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 0) = '1' )then
|
|
reg_sec_l <= dbo(3 downto 0);
|
|
elsif( w_1sec = '1' )then
|
|
if( w_10sec = '1' )then
|
|
reg_sec_l <= "0000";
|
|
else
|
|
reg_sec_l <= reg_sec_l + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_sec_l <= rt(3 downto 0);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_10sec <= '1' when( reg_sec_l = "1001" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 60sec timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 1) = '1' )then
|
|
reg_sec_h <= dbo(2 downto 0);
|
|
elsif( (w_1sec and w_10sec) = '1' )then
|
|
if( w_60sec = '1' )then
|
|
reg_sec_h <= "000";
|
|
else
|
|
reg_sec_h <= reg_sec_h + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_sec_h <= rt(6 downto 4);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_60sec <= '1' when( reg_sec_h = "101" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 10min timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 2) = '1' )then
|
|
reg_min_l <= dbo(3 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec) = '1' )then
|
|
if( w_10min = '1' )then
|
|
reg_min_l <= "0000";
|
|
else
|
|
reg_min_l <= reg_min_l + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_min_l <= rt(11 downto 8);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_10min <= '1' when( reg_min_l = "1001" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 60min timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 3) = '1' )then
|
|
reg_min_h <= dbo(2 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min) = '1' )then
|
|
if( w_60min = '1' )then
|
|
reg_min_h <= "000";
|
|
else
|
|
reg_min_h <= reg_min_h + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_min_h <= rt(14 downto 12);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_60min <= '1' when( reg_min_h = "101" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 10hour timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 4) = '1' )then
|
|
reg_hou_l <= dbo(3 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min) = '1' )then
|
|
if( (w_10hour or w_1224hour) = '1' )then
|
|
reg_hou_l <= "0000";
|
|
else
|
|
reg_hou_l <= reg_hou_l + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_hou_l <= rt(19 downto 16);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 5) = '1' )then
|
|
reg_hou_h <= dbo(1 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min) = '1' )then
|
|
if( w_10hour = '1' )then
|
|
reg_hou_h <= reg_hou_h + 1;
|
|
elsif( w_1224hour = '1' )then
|
|
reg_hou_h(5) <= not reg_hou_h(5);
|
|
reg_hou_h(4) <= '0';
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_hou_h <= rt(21 downto 20);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_10hour <= '1' when( reg_hou_l = "1001" )else -- 09 --> 10
|
|
'0';
|
|
|
|
w_1224hour <= '1' when( (reg_1224 = '0' and reg_hou_h(4) = '1' and reg_hou_l = "0001") or -- 11 --> 00
|
|
(reg_1224 = '1' and reg_hou_h = "10" and reg_hou_l = "0011") )else -- 23 --> 00
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- week day timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 6) = '1' )then
|
|
reg_wee <= dbo(2 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour) = '1' )then
|
|
if( reg_wee = "110" )then
|
|
reg_wee <= (others => '0');
|
|
else
|
|
reg_wee <= reg_wee + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_wee <= rt(50 downto 48);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
----------------------------------------------------------------
|
|
-- 10day timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 7) = '1' )then
|
|
reg_day_l <= dbo(3 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour) = '1' )then
|
|
if( w_10day = '1' )then
|
|
reg_day_l <= "0000";
|
|
elsif( w_next_mon = '1' )then
|
|
reg_day_l <= "0001";
|
|
else
|
|
reg_day_l <= reg_day_l + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_day_l <= rt(27 downto 24);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_10day <= '1' when( reg_day_l = "1001" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 1month timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 8) = '1' )then
|
|
reg_day_h <= dbo(1 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour) = '1' )then
|
|
if( w_next_mon = '1' )then
|
|
reg_day_h <= "00";
|
|
elsif( w_10day = '1' )then
|
|
reg_day_h <= reg_day_h + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_day_h <= rt(29 downto 28);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_next_mon <= '1' when( ( reg_day_h = "11" and reg_day_l = "0001" ) or -- xx/31
|
|
(reg_mon_h = '0' and reg_mon_l = "0010" and reg_day_h = "10" and reg_day_l = "1001" and reg_leap = "00" ) or -- 02/29 (leap year)
|
|
(reg_mon_h = '0' and reg_mon_l = "0010" and reg_day_h = "10" and reg_day_l = "1000" and reg_leap /= "00" ) or -- 02/28
|
|
(reg_mon_h = '0' and reg_mon_l = "0100" and reg_day_h = "11" and reg_day_l = "0000" ) or -- 04/30
|
|
(reg_mon_h = '0' and reg_mon_l = "0110" and reg_day_h = "11" and reg_day_l = "0000" ) or -- 06/30
|
|
(reg_mon_h = '0' and reg_mon_l = "1001" and reg_day_h = "11" and reg_day_l = "0000" ) or -- 09/30
|
|
(reg_mon_h = '1' and reg_mon_l = "0001" and reg_day_h = "11" and reg_day_l = "0000" ) )else -- 11/30
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 10month timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec( 9) = '1' )then
|
|
reg_mon_l <= dbo(3 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour and w_next_mon) = '1' )then
|
|
if( w_10mon = '1' )then
|
|
reg_mon_l <= "0000";
|
|
elsif( w_1year = '1' )then
|
|
reg_mon_l <= "0001";
|
|
else
|
|
reg_mon_l <= reg_mon_l + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_mon_l <= rt(35 downto 32);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_10mon <= '1' when( reg_mon_l = "1001" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 1year timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec(10) = '1' )then
|
|
reg_mon_h <= dbo(0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour and w_next_mon) = '1' )then
|
|
if( w_10mon = '1' )then
|
|
reg_mon_h <= '1';
|
|
elsif( w_1year = '1' )then
|
|
reg_mon_h <= '0';
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_mon_h <= rt(36);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_1year <= '1' when( reg_mon_h = '1' and reg_mon_l = "0010" )else -- x"12"
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 10year timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec(11) = '1' )then
|
|
reg_yea_l <= dbo(3 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour and w_next_mon and w_1year) = '1' )then
|
|
if( w_10year = '1' )then
|
|
reg_yea_l <= "0000";
|
|
else
|
|
reg_yea_l <= reg_yea_l + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_yea_l <= rt(43 downto 40);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_10year <= '1' when( reg_yea_l = "1001" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- 100year timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( clk21m'event and clk21m = '1' )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(0) = '1' and w_adr_dec(12) = '1' )then
|
|
reg_yea_h <= dbo(3 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour and w_next_mon and w_1year and w_10year) = '1' )then
|
|
if( w_100year = '1' )then
|
|
reg_yea_h <= "0000";
|
|
else
|
|
reg_yea_h <= reg_yea_h + 1;
|
|
end if;
|
|
end if;
|
|
if setup = '1' then
|
|
reg_yea_h <= rt(47 downto 44) + "0010";
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
w_100year <= '1' when( reg_yea_h = "1001" )else
|
|
'0';
|
|
|
|
----------------------------------------------------------------
|
|
-- leap year timer
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( clk21m'event and clk21m = '1' )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(1) = '1' and w_adr_dec(11) = '1' )then
|
|
reg_leap <= dbo(1 downto 0);
|
|
elsif( (w_1sec and w_10sec and w_60sec and w_10min and w_60min and w_1224hour and w_next_mon and w_1year) = '1' )then
|
|
reg_leap <= reg_leap + 1;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
----------------------------------------------------------------
|
|
-- 12hour mode/24 hour mode
|
|
----------------------------------------------------------------
|
|
process( clk21m )
|
|
begin
|
|
if( clk21m'event and clk21m = '1' )then
|
|
if( w_wrt = '1' and adr(0) = '1' and w_bank_dec(1) = '1' and w_adr_dec(10) = '1' )then
|
|
reg_1224 <= dbo(0);
|
|
end if;
|
|
if setup = '1' then
|
|
reg_1224 <= '1';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
----------------------------------------------------------------
|
|
-- rtc register pointer
|
|
----------------------------------------------------------------
|
|
process( reset, clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( reset = '1' )then
|
|
reg_ptr <= (others => '0');
|
|
else
|
|
if( w_wrt = '1' and adr(0) = '0' )then
|
|
-- register pointer
|
|
reg_ptr <= dbo(3 downto 0);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
----------------------------------------------------------------
|
|
-- rtc test register
|
|
----------------------------------------------------------------
|
|
process( reset, clk21m )
|
|
begin
|
|
if( rising_edge(clk21m) )then
|
|
if( reset = '1' )then
|
|
reg_mode <= "1000";
|
|
else
|
|
if( w_wrt = '1' and adr(0) = '1' and w_adr_dec(13) = '1' )then
|
|
reg_mode <= dbo(3 downto 0);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
----------------------------------------------------------------
|
|
-- backup memory emulation
|
|
----------------------------------------------------------------
|
|
w_mem_addr <= "00" & reg_mode(1 downto 0) & reg_ptr;
|
|
w_mem_we <= '1' when( w_wrt = '1' and adr(0) = '1' )else
|
|
'0';
|
|
|
|
u_mem: work.ram
|
|
port map (
|
|
adr => w_mem_addr ,
|
|
clk => clk21m ,
|
|
we => w_mem_we ,
|
|
dbo => dbo ,
|
|
dbi => w_mem_q
|
|
);
|
|
|
|
end rtl;
|