OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_rtc.vhd] - Diff between revs 167 and 168

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 167 Rev 168
Line 1... Line 1...
-- Copyright (c)2013 Jeremy Seth Henry
 
-- All rights reserved.
 
--
 
-- Redistribution and use in source and binary forms, with or without
 
-- modification, are permitted provided that the following conditions are met:
 
--     * Redistributions of source code must retain the above copyright
 
--       notice, this list of conditions and the following disclaimer.
 
--     * 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,
 
--       where applicable (as part of a user interface, debugging port, etc.)
 
--
 
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``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 JEREMY SETH HENRY 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.
 
--
 
-- VHDL Units :  realtime_clock
-- VHDL Units :  realtime_clock
-- Description:  Provides automatically updated registers that maintain the
-- Description:  Provides automatically updated registers that maintain the
--            :   time of day. Keeps track of the day of week, hours, minutes
--            :   time of day. Keeps track of the day of week, hours, minutes
--            :   seconds, and tenths of a second. Module is doubled buffered
--            :   seconds, and tenths of a second. Module is doubled buffered
--            :   to ensure time consistency during accesses. Also provides
--            :   to ensure time consistency during accesses. Also provides
Line 105... Line 82...
 
 
  signal uSec_Cntr      : std_logic_vector( DLY_1USEC_WDT - 1 downto 0 )
  signal uSec_Cntr      : std_logic_vector( DLY_1USEC_WDT - 1 downto 0 )
                          := (others => '0');
                          := (others => '0');
  signal uSec_Tick_i      : std_logic;
  signal uSec_Tick_i      : std_logic;
 
 
  signal interval       : DATA_TYPE;
  type PIT_TYPE is record
  signal timer_cnt      : DATA_TYPE;
    timer_cnt           : DATA_TYPE;
  signal timer_ro       : std_logic;
    timer_ro            : std_logic;
 
  end record;
 
 
 
  signal pit            : PIT_TYPE;
 
 
 
  type RTC_TYPE is record
 
    frac                : std_logic_vector(15 downto 0);
 
    frac_ro             : std_logic;
 
 
 
    tens_l              : std_logic_vector(3 downto 0);
 
    tens_l_ro           : std_logic;
 
 
  signal rtc_frac       : std_logic_vector(15 downto 0);
    tens_u              : std_logic_vector(3 downto 0);
  signal frac_ro        : std_logic;
    tens_u_ro           : std_logic;
 
 
  signal rtc_tens       : DATA_TYPE;
    secs_l              : std_logic_vector(3 downto 0);
  signal tens_ro        : std_logic;
    secs_l_ro           : std_logic;
 
 
  signal rtc_secs       : DATA_TYPE;
    secs_u              : std_logic_vector(3 downto 0);
  signal secs_ro        : std_logic;
    secs_u_ro           : std_logic;
 
 
  signal rtc_mins       : DATA_TYPE;
    mins_l              : std_logic_vector(3 downto 0);
  signal mins_ro        : std_logic;
    mins_l_ro           : std_logic;
 
 
  signal rtc_hours      : DATA_TYPE;
    mins_u              : std_logic_vector(3 downto 0);
  signal hours_ro       : std_logic;
    mins_u_ro           : std_logic;
 
 
  signal rtc_dow        : DATA_TYPE;
    hours_l             : std_logic_vector(3 downto 0);
 
    hours_l_ro          : std_logic;
 
 
 
    hours_u             : std_logic_vector(3 downto 0);
 
    hours_u_ro          : std_logic;
 
 
 
    dow                 : std_logic_vector(2 downto 0);
 
  end record;
 
 
 
  constant DECISEC      : std_logic_vector(15 downto 0) :=
 
                           conv_std_logic_vector(10000,16);
 
 
 
  signal rtc            : RTC_TYPE;
 
 
 
  signal interval       : DATA_TYPE;
 
 
  signal shd_tens       : DATA_TYPE;
  signal shd_tens       : DATA_TYPE;
  signal shd_secs       : DATA_TYPE;
  signal shd_secs       : DATA_TYPE;
  signal shd_mins       : DATA_TYPE;
  signal shd_mins       : DATA_TYPE;
  signal shd_hours      : DATA_TYPE;
  signal shd_hours      : DATA_TYPE;
Line 141... Line 142...
begin
begin
 
 
  uSec_Tick             <= uSec_Tick_i;
  uSec_Tick             <= uSec_Tick_i;
  Addr_Match            <= '1' when Comp_Addr = User_Addr else '0';
  Addr_Match            <= '1' when Comp_Addr = User_Addr else '0';
 
 
  Interrupt_PIT         <= timer_ro;
  Interrupt_PIT         <= pit.timer_ro;
  Interrupt_RTC         <= frac_ro;
  Interrupt_RTC         <= rtc.frac_ro;
 
 
  io_reg: process( Clock, Reset )
  io_reg: process( Clock, Reset )
  begin
  begin
    if( Reset = Reset_Level )then
    if( Reset = Reset_Level )then
      uSec_Cntr         <= (others => '0');
      uSec_Cntr         <= (others => '0');
      uSec_Tick_i       <= '0';
      uSec_Tick_i       <= '0';
 
 
      interval          <= x"00";
      pit.timer_cnt     <= x"00";
      timer_cnt         <= x"00";
      pit.timer_ro      <= '0';
      timer_ro          <= '0';
 
 
      rtc.frac          <= DECISEC;
 
      rtc.frac_ro       <= '0';
 
 
 
      rtc.tens_l        <= (others => '0');
 
      rtc.tens_l_ro     <= '0';
 
 
      rtc_frac          <= (others => '0');
      rtc.tens_u        <= (others => '0');
      frac_ro           <= '0';
      rtc.tens_u_ro     <= '0';
 
 
      rtc_tens          <= (others => '0');
      rtc.secs_l        <= (others => '0');
      tens_ro           <= '0';
      rtc.secs_l_ro     <= '0';
 
 
      rtc_secs          <= (others => '0');
      rtc.secs_u        <= (others => '0');
      secs_ro           <= '0';
      rtc.secs_u_ro     <= '0';
 
 
      rtc_mins          <= (others => '0');
      rtc.mins_l        <= (others => '0');
      mins_ro           <= '0';
      rtc.mins_l_ro     <= '0';
 
 
      rtc_hours         <= (others => '0');
      rtc.mins_u        <= (others => '0');
      hours_ro          <= '0';
      rtc.mins_u_ro     <= '0';
 
 
      rtc_dow           <= (others => '0');
      rtc.hours_l       <= (others => '0');
 
      rtc.hours_l_ro    <= '0';
 
 
 
      rtc.hours_u       <= (others => '0');
 
      rtc.hours_u_ro    <= '0';
 
 
 
      rtc.dow           <= (others => '0');
 
 
      shd_tens          <= (others => '0');
      shd_tens          <= (others => '0');
      shd_secs          <= (others => '0');
      shd_secs          <= (others => '0');
      shd_mins          <= (others => '0');
      shd_mins          <= (others => '0');
      shd_hours         <= (others => '0');
      shd_hours         <= (others => '0');
Line 181... Line 193...
 
 
      update_rtc        <= '0';
      update_rtc        <= '0';
      update_shd        <= '0';
      update_shd        <= '0';
      update_ctmr       <= (others => '0');
      update_ctmr       <= (others => '0');
 
 
 
      interval          <= x"00";
 
 
      Wr_Data_q         <= (others => '0');
      Wr_Data_q         <= (others => '0');
      Reg_Addr_q        <= (others => '0');
      Reg_Addr_q        <= (others => '0');
      Wr_En             <= '0';
      Wr_En             <= '0';
      Rd_En             <= '0';
      Rd_En             <= '0';
      Rd_Data           <= x"00";
      Rd_Data           <= x"00";
Line 196... Line 210...
      if( uSec_Cntr = 0 )then
      if( uSec_Cntr = 0 )then
        uSec_Cntr       <= DLY_1USEC;
        uSec_Cntr       <= DLY_1USEC;
        uSec_Tick_i     <= or_reduce(Interval);
        uSec_Tick_i     <= or_reduce(Interval);
      end if;
      end if;
 
 
      timer_ro          <= '0';
      pit.timer_ro      <= '0';
      frac_ro           <= '0';
 
      tens_ro           <= '0';
      rtc.frac_ro       <= '0';
      secs_ro           <= '0';
      rtc.tens_l_ro     <= '0';
      mins_ro           <= '0';
      rtc.tens_u_ro     <= '0';
      hours_ro          <= '0';
      rtc.secs_l_ro     <= '0';
 
      rtc.secs_u_ro     <= '0';
 
      rtc.mins_l_ro     <= '0';
 
      rtc.mins_u_ro     <= '0';
 
      rtc.hours_l_ro    <= '0';
 
      rtc.hours_u_ro    <= '0';
 
 
      -- Periodic Interval Timer
      -- Periodic Interval Timer
      timer_cnt         <= timer_cnt - uSec_Tick_i;
      pit.timer_cnt     <= pit.timer_cnt - uSec_Tick_i;
      if( or_reduce(timer_cnt) = '0' )then
      if( or_reduce(pit.timer_cnt) = '0' )then
        timer_cnt       <= interval;
        pit.timer_cnt   <= interval;
        timer_ro        <= or_reduce(interval); -- Only issue output on Int > 0
        pit.timer_ro    <= or_reduce(interval); -- Only issue output on Int > 0
      end if;
      end if;
 
 
      -- Fractional decisecond counter - cycles every 10k microseconds
      -- Fractional decisecond counter - cycles every 10k microseconds
      rtc_frac          <= rtc_frac - uSec_Tick_i;
      rtc.frac          <= rtc.frac - uSec_Tick_i;
      if( or_reduce(rtc_frac) = '0' or update_rtc = '1' )then
      if( or_reduce(rtc.frac) = '0' or update_rtc = '1' )then
        rtc_frac        <= x"2710";
        rtc.frac        <= DECISEC;
        frac_ro         <= not update_rtc;
        rtc.frac_ro     <= not update_rtc;
      end if;
      end if;
 
 
      -- Decisecond counter
      -- Decisecond counter (lower)
      rtc_tens          <= rtc_tens + frac_ro;
      rtc.tens_l        <= rtc.tens_l + rtc.frac_ro;
      if( update_rtc = '1' )then
      if( update_rtc = '1' )then
        rtc_tens        <= shd_tens;
        rtc.tens_l      <= shd_tens(3 downto 0);
      elsif( rtc_tens = x"64")then
      elsif( rtc.tens_l > x"9")then
        rtc_tens        <= (others => '0');
        rtc.tens_l      <= (others => '0');
        tens_ro         <= '1';
        rtc.tens_l_ro   <= '1';
      end if;
      end if;
 
 
      -- Second counter
      -- Decisecond counter (upper)
      rtc_secs          <= rtc_secs + tens_ro;
      rtc.tens_u        <= rtc.tens_u + rtc.tens_l_ro;
      if( update_rtc = '1' )then
      if( update_rtc = '1' )then
        rtc_secs        <= shd_secs;
        rtc.tens_u      <= shd_tens(7 downto 4);
      elsif( rtc_secs = x"3C")then
      elsif( rtc.tens_u > x"9")then
        rtc_secs        <= (others => '0');
        rtc.tens_u      <= (others => '0');
        secs_ro         <= '1';
        rtc.tens_u_ro   <= '1';
      end if;
      end if;
 
 
      -- Minute counter
      -- Second counter (lower)
      rtc_mins          <= rtc_mins + secs_ro;
      rtc.secs_l        <= rtc.secs_l + rtc.tens_u_ro;
      if( update_rtc = '1' )then
      if( update_rtc = '1' )then
        rtc_mins        <= shd_mins;
        rtc.secs_l      <= shd_secs(3 downto 0);
      elsif( rtc_mins = x"3C")then
      elsif( rtc.secs_l > x"9")then
        rtc_mins        <= (others => '0');
        rtc.secs_l      <= (others => '0');
        mins_ro         <= '1';
        rtc.secs_l_ro   <= '1';
      end if;
      end if;
 
 
      -- Hour counter
      -- Second counter (upper)
      rtc_hours         <= rtc_hours + mins_ro;
      rtc.secs_u        <= rtc.secs_u + rtc.secs_l_ro;
      if( update_rtc = '1' )then
      if( update_rtc = '1' )then
        rtc_hours       <= shd_hours;
        rtc.secs_u      <= shd_secs(7 downto 4);
      elsif( rtc_hours = x"18")then
      elsif( rtc.secs_u > x"5")then
        rtc_hours       <= (others => '0');
        rtc.secs_u      <= (others => '0');
        hours_ro        <= '1';
        rtc.secs_u_ro   <= '1';
      end if;
      end if;
 
 
      -- Day of Week counter
      -- Minutes counter (lower)
      rtc_dow           <= rtc_dow + hours_ro;
      rtc.mins_l        <= rtc.mins_l + rtc.secs_u_ro;
      if( update_rtc = '1' )then
      if( update_rtc = '1' )then
        rtc_dow        <= shd_dow;
        rtc.mins_l      <= shd_mins(3 downto 0);
      elsif( rtc_dow = x"07")then
      elsif( rtc.mins_l > x"9")then
        rtc_dow         <= (others => '0');
        rtc.mins_l      <= (others => '0');
 
        rtc.mins_l_ro   <= '1';
      end if;
      end if;
 
 
      -- Coherency timer - ensures that the shadow registers are updated with
      -- Minutes counter (upper)
      --  valid time data by delaying updates until the rtc registers have
      rtc.mins_u        <= rtc.mins_u + rtc.mins_l_ro;
      --  finished cascading.
      if( update_rtc = '1' )then
      update_rtc        <= '0';
        rtc.mins_u      <= shd_mins(7 downto 4);
      update_ctmr       <= update_ctmr - or_reduce(update_ctmr);
      elsif( rtc.mins_u > x"5")then
      if( frac_ro = '1' )then
        rtc.mins_u      <= (others => '0');
        update_ctmr     <= x"9";
        rtc.mins_u_ro   <= '1';
 
      end if;
 
 
 
      -- Hour counter (lower)
 
      rtc.hours_l       <= rtc.hours_l + rtc.mins_u_ro;
 
      if( update_rtc = '1' )then
 
        rtc.hours_l     <= shd_hours(3 downto 0);
 
      elsif( rtc.hours_l > x"9")then
 
        rtc.hours_l     <= (others => '0');
 
        rtc.hours_l_ro  <= '1';
 
      end if;
 
 
 
      -- Hour counter (upper)
 
      rtc.hours_u       <= rtc.hours_u + rtc.hours_l_ro;
 
      if( update_rtc = '1' )then
 
        rtc.hours_u     <= shd_hours(7 downto 4);
 
      end if;
 
 
 
      if( rtc.hours_u >= x"2" and rtc.hours_l > x"3" )then
 
        rtc.hours_l     <= (others => '0');
 
        rtc.hours_u     <= (others => '0');
 
        rtc.hours_u_ro  <= '1';
 
      end if;
 
 
 
      -- Day of Week counter
 
      rtc.dow           <= rtc.dow + rtc.hours_u_ro;
 
      if( update_rtc = '1' )then
 
        rtc.dow        <= shd_dow(2 downto 0);
 
      elsif( rtc.dow = x"07")then
 
        rtc.dow         <= (others => '0');
      end if;
      end if;
 
 
      -- Copy the RTC registers to the shadow registers when the coherency
      -- Copy the RTC registers to the shadow registers when the coherency
      --  timer is zero (RTC registers are static)
      --  timer is zero (RTC registers are static)
      if( update_shd = '1' and or_reduce(update_ctmr) = '0' )then
      if( update_shd = '1' and or_reduce(update_ctmr) = '0' )then
        shd_tens        <= rtc_tens;
        shd_tens        <= rtc.tens_u & rtc.tens_l;
        shd_secs        <= rtc_secs;
        shd_secs        <= rtc.secs_u & rtc.secs_l;
        shd_mins        <= rtc_mins;
        shd_mins        <= rtc.mins_u & rtc.mins_l;
        shd_hours       <= rtc_hours;
        shd_hours       <= rtc.hours_u & rtc.hours_l;
        shd_dow         <= rtc_dow;
        shd_dow         <= "00000" & rtc.dow;
        update_shd      <= '0';
        update_shd      <= '0';
      end if;
      end if;
 
 
      Reg_Addr_q        <= Reg_Addr;
      Reg_Addr_q        <= Reg_Addr;
      Wr_Data_q         <= Wr_Data;
      Wr_Data_q         <= Wr_Data;
 
 
      Wr_En             <= Addr_Match and Wr_Enable;
      Wr_En             <= Addr_Match and Wr_Enable;
 
      update_rtc        <= '0';
      if( Wr_En = '1' )then
      if( Wr_En = '1' )then
        case( Reg_Addr_q )is
        case( Reg_Addr_q )is
          when "000" =>
          when "000" =>
            interval    <= Wr_Data_q;
            interval    <= Wr_Data_q;
 
 
          when "001" =>
          when "001" =>
            shd_tens    <= '0' & Wr_Data_q(6 downto 0);
            shd_tens    <= Wr_Data_q;
 
 
          when "010" =>
          when "010" =>
            shd_secs    <= "00" & Wr_Data_q(5 downto 0);
            shd_secs    <= Wr_Data_q;
 
 
          when "011" =>
          when "011" =>
            shd_mins    <= "00" & Wr_Data_q(5 downto 0);
            shd_mins    <= Wr_Data_q;
 
 
          when "100" =>
          when "100" =>
            shd_hours   <= "000" & Wr_Data_q(4 downto 0);
            shd_hours   <= Wr_Data_q;
 
 
          when "101" =>
          when "101" =>
            shd_dow     <= "00000" & Wr_Data_q(2 downto 0);
            shd_dow     <= Wr_Data_q;
 
 
          when "110" =>
          when "110" =>
            update_rtc  <= '1';
            update_rtc  <= '1';
 
 
          when "111" =>
          when "111" =>
 
 
            update_shd  <= '1';
            update_shd  <= '1';
 
 
          when others => null;
          when others => null;
        end case;
        end case;
      end if;
      end if;
 
 
 
      -- Coherency timer - ensures that the shadow registers are updated with
 
      --  valid time data by delaying updates until the rtc registers have
 
      --  finished cascading.
 
      update_ctmr       <= update_ctmr - or_reduce(update_ctmr);
 
      if( rtc.frac_ro = '1' )then
 
        update_ctmr     <= (others => '1');
 
      end if;
 
 
      Rd_Data           <= (others => '0');
      Rd_Data           <= (others => '0');
      Rd_En             <= Addr_Match and Rd_Enable;
      Rd_En             <= Addr_Match and Rd_Enable;
      if( Rd_En = '1' )then
      if( Rd_En = '1' )then
        case( Reg_Addr_q )is
        case( Reg_Addr_q )is
          when "000" =>
          when "000" =>
Line 344... Line 401...
 
 
    end if;
    end if;
  end process;
  end process;
 
 
end architecture;
end architecture;
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.