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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_rtc.vhd] - Blame information for rev 279

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 191 jshamlet
-- Copyright (c)2020 Jeremy Seth Henry
2
-- All rights reserved.
3
--
4
-- Redistribution and use in source and binary forms, with or without
5
-- modification, are permitted provided that the following conditions are met:
6
--     * Redistributions of source code must retain the above copyright
7
--       notice, this list of conditions and the following disclaimer.
8
--     * Redistributions in binary form must reproduce the above copyright
9
--       notice, this list of conditions and the following disclaimer in the
10
--       documentation and/or other materials provided with the distribution,
11
--       where applicable (as part of a user interface, debugging port, etc.)
12
--
13
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
14
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
17
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 194 jshamlet
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 191 jshamlet
--
24
-- VHDL Units :  o8_rtc
25 168 jshamlet
-- Description:  Provides automatically updated registers that maintain the
26
--            :   time of day. Keeps track of the day of week, hours, minutes
27 213 jshamlet
--            :   seconds, and tenths of a second in packed BCD format.
28
--            :  Module is doubled buffered to ensure time consistency during
29
--            :   accesses.
30
--            :  Also provides an 8-bit programmable periodic interrupt timer
31
--            :   with 1uS resolution, a 10uS fixed interrupt, as well as a
32
--            :   1 uSec tick (1 clock wide) for external use.
33 191 jshamlet
--
34 168 jshamlet
-- Register Map:
35
-- Offset  Bitfield Description                        Read/Write
36
--   0x0   AAAAAAAA Periodic Interval Timer in uS      (RW)
37 213 jshamlet
--   0x1   BBBBAAAA Tenths  (0x00 - 0x99)              (RW)
38
--   0x2   -BBBAAAA Seconds (0x00 - 0x59)              (RW)
39
--   0x3   -BBBAAAA Minutes (0x00 - 0x59)              (RW)
40
--   0x4   --BBAAAA Hours   (0x00 - 0x23)              (RW)
41 168 jshamlet
--   0x5   -----AAA Day of Week (0x00 - 0x06)          (RW)
42
--   0x6   -------- Update RTC regs from Shadow Regs   (WO)
43
--   0x7   A------- Update Shadow Regs from RTC regs   (RW)
44
--                  A = Update is Busy
45 224 jshamlet
--
46
-- Revision History
47
-- Author          Date     Change
48
------------------ -------- ---------------------------------------------------
49
-- Seth Henry      04/16/20 Revision block added
50 244 jshamlet
-- Seth Henry      05/18/20 Added write qualification input
51 168 jshamlet
 
52
library ieee;
53
use ieee.std_logic_1164.all;
54
  use ieee.std_logic_unsigned.all;
55
  use ieee.std_logic_arith.all;
56
  use ieee.std_logic_misc.all;
57
 
58
library work;
59
  use work.open8_pkg.all;
60
 
61
entity o8_rtc is
62
generic(
63 210 jshamlet
  Address                    : ADDRESS_TYPE
64 168 jshamlet
);
65
port(
66 223 jshamlet
  Open8_Bus                  : in  OPEN8_BUS_TYPE;
67 244 jshamlet
  Write_Qual                 : in  std_logic := '1';
68 210 jshamlet
  Rd_Data                    : out DATA_TYPE;
69 168 jshamlet
  --
70 210 jshamlet
  Interrupt_PIT              : out std_logic;
71
  Interrupt_RTC              : out std_logic
72 168 jshamlet
);
73
end entity;
74
 
75
architecture behave of o8_rtc is
76
 
77 224 jshamlet
  alias Clock                is Open8_Bus.Clock;
78
  alias Reset                is Open8_Bus.Reset;
79
  alias uSec_Tick            is Open8_Bus.uSec_Tick;
80
 
81 244 jshamlet
  constant User_Addr         : std_logic_vector(15 downto 3) :=
82
                                Address(15 downto 3);
83
 
84 223 jshamlet
  alias  Comp_Addr           is Open8_Bus.Address(15 downto 3);
85 244 jshamlet
  signal Addr_Match          : std_logic := '0';
86 168 jshamlet
 
87 244 jshamlet
  alias  Reg_Sel_d           is Open8_Bus.Address(2 downto 0);
88
  signal Reg_Sel_q           : std_logic_vector(2 downto 0) := (others => '0');
89
  signal Wr_En_d             : std_logic := '0';
90
  signal Wr_En_q             : std_logic := '0';
91
  alias  Wr_Data_d           is Open8_Bus.Wr_Data;
92
  signal Wr_Data_q           : DATA_TYPE := x"00";
93
  signal Rd_En_d             : std_logic := '0';
94
  signal Rd_En_q             : std_logic := '0';
95 168 jshamlet
 
96
  type PIT_TYPE is record
97 217 jshamlet
    timer_cnt                : DATA_TYPE;
98
    timer_ro                 : std_logic;
99 168 jshamlet
  end record;
100
 
101 217 jshamlet
  signal pit                 : PIT_TYPE;
102 168 jshamlet
 
103
  type RTC_TYPE is record
104 217 jshamlet
    frac                     : std_logic_vector(15 downto 0);
105
    frac_ro                  : std_logic;
106 168 jshamlet
 
107 217 jshamlet
    tens_l                   : std_logic_vector(3 downto 0);
108
    tens_l_ro                : std_logic;
109 168 jshamlet
 
110 217 jshamlet
    tens_u                   : std_logic_vector(3 downto 0);
111
    tens_u_ro                : std_logic;
112 168 jshamlet
 
113 217 jshamlet
    secs_l                   : std_logic_vector(3 downto 0);
114
    secs_l_ro                : std_logic;
115 168 jshamlet
 
116 217 jshamlet
    secs_u                   : std_logic_vector(3 downto 0);
117
    secs_u_ro                : std_logic;
118 168 jshamlet
 
119 217 jshamlet
    mins_l                   : std_logic_vector(3 downto 0);
120
    mins_l_ro                : std_logic;
121 168 jshamlet
 
122 217 jshamlet
    mins_u                   : std_logic_vector(3 downto 0);
123
    mins_u_ro                : std_logic;
124 168 jshamlet
 
125 217 jshamlet
    hours_l                  : std_logic_vector(3 downto 0);
126
    hours_l_ro               : std_logic;
127 168 jshamlet
 
128 217 jshamlet
    hours_u                  : std_logic_vector(3 downto 0);
129
    hours_u_ro               : std_logic;
130 168 jshamlet
 
131 217 jshamlet
    dow                      : std_logic_vector(2 downto 0);
132 168 jshamlet
  end record;
133
 
134 217 jshamlet
  constant DECISEC           : std_logic_vector(15 downto 0) :=
135
                                conv_std_logic_vector(10000,16);
136 168 jshamlet
 
137 217 jshamlet
  signal rtc                 : RTC_TYPE;
138 168 jshamlet
 
139 217 jshamlet
  signal interval            : DATA_TYPE;
140
  signal update_interval     : std_logic;
141 168 jshamlet
 
142 217 jshamlet
  signal shd_tens            : DATA_TYPE;
143
  signal shd_secs            : DATA_TYPE;
144
  signal shd_mins            : DATA_TYPE;
145
  signal shd_hours           : DATA_TYPE;
146
  signal shd_dow             : DATA_TYPE;
147 168 jshamlet
 
148 217 jshamlet
  signal update_rtc          : std_logic;
149
  signal update_shd          : std_logic;
150
  signal update_ctmr         : std_logic_vector(3 downto 0);
151 168 jshamlet
 
152
begin
153
 
154 210 jshamlet
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
155 244 jshamlet
  Wr_En_d                    <= Addr_Match and Open8_Bus.Wr_En and Write_Qual;
156
  Rd_En_d                    <= Addr_Match and Open8_Bus.Rd_En;
157 168 jshamlet
 
158 210 jshamlet
  Interrupt_PIT              <= pit.timer_ro;
159
  Interrupt_RTC              <= rtc.frac_ro;
160 168 jshamlet
 
161
  io_reg: process( Clock, Reset )
162
  begin
163
    if( Reset = Reset_Level )then
164 244 jshamlet
      Reg_Sel_q              <= "000";
165
      Wr_En_q                <= '0';
166
      Wr_Data_q              <= x"00";
167
      Rd_En_q                <= '0';
168
      Rd_Data                <= OPEN8_NULLBUS;
169
 
170 210 jshamlet
      pit.timer_cnt          <= x"00";
171
      pit.timer_ro           <= '0';
172 168 jshamlet
 
173 210 jshamlet
      rtc.frac               <= DECISEC;
174
      rtc.frac_ro            <= '0';
175 168 jshamlet
 
176 210 jshamlet
      rtc.tens_l             <= (others => '0');
177
      rtc.tens_l_ro          <= '0';
178 168 jshamlet
 
179 210 jshamlet
      rtc.tens_u             <= (others => '0');
180
      rtc.tens_u_ro          <= '0';
181 168 jshamlet
 
182 210 jshamlet
      rtc.secs_l             <= (others => '0');
183
      rtc.secs_l_ro          <= '0';
184 168 jshamlet
 
185 210 jshamlet
      rtc.secs_u             <= (others => '0');
186
      rtc.secs_u_ro          <= '0';
187 168 jshamlet
 
188 210 jshamlet
      rtc.mins_l             <= (others => '0');
189
      rtc.mins_l_ro          <= '0';
190 168 jshamlet
 
191 210 jshamlet
      rtc.mins_u             <= (others => '0');
192
      rtc.mins_u_ro          <= '0';
193 168 jshamlet
 
194 210 jshamlet
      rtc.hours_l            <= (others => '0');
195
      rtc.hours_l_ro         <= '0';
196 168 jshamlet
 
197 210 jshamlet
      rtc.hours_u            <= (others => '0');
198
      rtc.hours_u_ro         <= '0';
199 168 jshamlet
 
200 210 jshamlet
      rtc.dow                <= (others => '0');
201 168 jshamlet
 
202 210 jshamlet
      shd_tens               <= (others => '0');
203
      shd_secs               <= (others => '0');
204
      shd_mins               <= (others => '0');
205
      shd_hours              <= (others => '0');
206
      shd_dow                <= (others => '0');
207 168 jshamlet
 
208 210 jshamlet
      update_rtc             <= '0';
209
      update_shd             <= '0';
210
      update_ctmr            <= (others => '0');
211 168 jshamlet
 
212 210 jshamlet
      interval               <= x"00";
213
      update_interval        <= '0';
214 168 jshamlet
 
215
    elsif( rising_edge( Clock ) )then
216
 
217
      -- Periodic Interval Timer
218 224 jshamlet
      pit.timer_cnt          <= pit.timer_cnt - uSec_Tick;
219 210 jshamlet
      pit.timer_ro           <= '0';
220
      if( update_interval = '1' )then
221 211 jshamlet
        pit.timer_cnt        <= interval;
222 210 jshamlet
      elsif( or_reduce(pit.timer_cnt) = '0' )then
223
        pit.timer_cnt        <= interval;
224
        pit.timer_ro         <= or_reduce(interval);
225 168 jshamlet
      end if;
226
 
227
      -- Fractional decisecond counter - cycles every 10k microseconds
228 224 jshamlet
      rtc.frac               <= rtc.frac - uSec_Tick;
229 210 jshamlet
      rtc.frac_ro            <= '0';
230 168 jshamlet
      if( or_reduce(rtc.frac) = '0' or update_rtc = '1' )then
231 210 jshamlet
        rtc.frac             <= DECISEC;
232
        rtc.frac_ro          <= not update_rtc;
233 168 jshamlet
      end if;
234
 
235
      -- Decisecond counter (lower)
236 210 jshamlet
      rtc.tens_l             <= rtc.tens_l + rtc.frac_ro;
237
      rtc.tens_l_ro          <= '0';
238 168 jshamlet
      if( update_rtc = '1' )then
239 210 jshamlet
        rtc.tens_l           <= shd_tens(3 downto 0);
240 168 jshamlet
      elsif( rtc.tens_l > x"9")then
241 210 jshamlet
        rtc.tens_l           <= (others => '0');
242
        rtc.tens_l_ro        <= '1';
243 168 jshamlet
      end if;
244
 
245
      -- Decisecond counter (upper)
246 210 jshamlet
      rtc.tens_u             <= rtc.tens_u + rtc.tens_l_ro;
247
      rtc.tens_u_ro          <= '0';
248 168 jshamlet
      if( update_rtc = '1' )then
249 210 jshamlet
        rtc.tens_u           <= shd_tens(7 downto 4);
250 168 jshamlet
      elsif( rtc.tens_u > x"9")then
251 210 jshamlet
        rtc.tens_u           <= (others => '0');
252
        rtc.tens_u_ro        <= '1';
253 168 jshamlet
      end if;
254
 
255
      -- Second counter (lower)
256 210 jshamlet
      rtc.secs_l             <= rtc.secs_l + rtc.tens_u_ro;
257
      rtc.secs_l_ro          <= '0';
258 168 jshamlet
      if( update_rtc = '1' )then
259 210 jshamlet
        rtc.secs_l           <= shd_secs(3 downto 0);
260 168 jshamlet
      elsif( rtc.secs_l > x"9")then
261 210 jshamlet
        rtc.secs_l           <= (others => '0');
262
        rtc.secs_l_ro        <= '1';
263 168 jshamlet
      end if;
264
 
265
      -- Second counter (upper)
266 210 jshamlet
      rtc.secs_u             <= rtc.secs_u + rtc.secs_l_ro;
267
      rtc.secs_u_ro          <= '0';
268 168 jshamlet
      if( update_rtc = '1' )then
269 210 jshamlet
        rtc.secs_u           <= shd_secs(7 downto 4);
270 168 jshamlet
      elsif( rtc.secs_u > x"5")then
271 210 jshamlet
        rtc.secs_u           <= (others => '0');
272
        rtc.secs_u_ro        <= '1';
273 168 jshamlet
      end if;
274
 
275
      -- Minutes counter (lower)
276 210 jshamlet
      rtc.mins_l             <= rtc.mins_l + rtc.secs_u_ro;
277
      rtc.mins_l_ro          <= '0';
278 168 jshamlet
      if( update_rtc = '1' )then
279 210 jshamlet
        rtc.mins_l           <= shd_mins(3 downto 0);
280 168 jshamlet
      elsif( rtc.mins_l > x"9")then
281 210 jshamlet
        rtc.mins_l           <= (others => '0');
282
        rtc.mins_l_ro        <= '1';
283 168 jshamlet
      end if;
284
 
285
      -- Minutes counter (upper)
286 210 jshamlet
      rtc.mins_u             <= rtc.mins_u + rtc.mins_l_ro;
287
      rtc.mins_u_ro          <= '0';
288 168 jshamlet
      if( update_rtc = '1' )then
289 210 jshamlet
        rtc.mins_u           <= shd_mins(7 downto 4);
290 168 jshamlet
      elsif( rtc.mins_u > x"5")then
291 210 jshamlet
        rtc.mins_u           <= (others => '0');
292
        rtc.mins_u_ro        <= '1';
293 168 jshamlet
      end if;
294
 
295
      -- Hour counter (lower)
296 210 jshamlet
      rtc.hours_l            <= rtc.hours_l + rtc.mins_u_ro;
297
      rtc.hours_l_ro         <= '0';
298 168 jshamlet
      if( update_rtc = '1' )then
299 210 jshamlet
        rtc.hours_l          <= shd_hours(3 downto 0);
300 168 jshamlet
      elsif( rtc.hours_l > x"9")then
301 210 jshamlet
        rtc.hours_l          <= (others => '0');
302
        rtc.hours_l_ro       <= '1';
303 168 jshamlet
      end if;
304
 
305
      -- Hour counter (upper)
306 210 jshamlet
      rtc.hours_u            <= rtc.hours_u + rtc.hours_l_ro;
307 168 jshamlet
      if( update_rtc = '1' )then
308 210 jshamlet
        rtc.hours_u          <= shd_hours(7 downto 4);
309 168 jshamlet
      end if;
310
 
311 210 jshamlet
      rtc.hours_u_ro         <= '0';
312 168 jshamlet
      if( rtc.hours_u >= x"2" and rtc.hours_l > x"3" )then
313 210 jshamlet
        rtc.hours_l          <= (others => '0');
314
        rtc.hours_u          <= (others => '0');
315
        rtc.hours_u_ro       <= '1';
316 168 jshamlet
      end if;
317
 
318
      -- Day of Week counter
319 210 jshamlet
      rtc.dow                <= rtc.dow + rtc.hours_u_ro;
320 168 jshamlet
      if( update_rtc = '1' )then
321 210 jshamlet
        rtc.dow              <= shd_dow(2 downto 0);
322 168 jshamlet
      elsif( rtc.dow = x"07")then
323 210 jshamlet
        rtc.dow              <= (others => '0');
324 168 jshamlet
      end if;
325
 
326
      -- Copy the RTC registers to the shadow registers when the coherency
327
      --  timer is zero (RTC registers are static)
328
      if( update_shd = '1' and or_reduce(update_ctmr) = '0' )then
329 210 jshamlet
        shd_tens             <= rtc.tens_u & rtc.tens_l;
330
        shd_secs             <= rtc.secs_u & rtc.secs_l;
331
        shd_mins             <= rtc.mins_u & rtc.mins_l;
332
        shd_hours            <= rtc.hours_u & rtc.hours_l;
333
        shd_dow              <= "00000" & rtc.dow;
334
        update_shd           <= '0';
335 168 jshamlet
      end if;
336
 
337 210 jshamlet
      update_interval        <= '0';
338 209 jshamlet
 
339 244 jshamlet
      Reg_Sel_q              <= Reg_Sel_d;
340 168 jshamlet
 
341 244 jshamlet
      Wr_En_q                <= Wr_En_d;
342
      Wr_Data_q              <= Wr_Data_d;
343
 
344 210 jshamlet
      update_rtc             <= '0';
345 244 jshamlet
      if( Wr_En_q = '1' )then
346
        case( Reg_Sel_q )is
347 168 jshamlet
          when "000" =>
348 211 jshamlet
            interval         <= Wr_Data_q;
349 210 jshamlet
            update_interval  <= '1';
350 168 jshamlet
 
351
          when "001" =>
352 210 jshamlet
            shd_tens         <= Wr_Data_q;
353 168 jshamlet
 
354
          when "010" =>
355 210 jshamlet
            shd_secs         <= Wr_Data_q;
356 168 jshamlet
 
357
          when "011" =>
358 210 jshamlet
            shd_mins         <= Wr_Data_q;
359 168 jshamlet
 
360
          when "100" =>
361 210 jshamlet
            shd_hours        <= Wr_Data_q;
362 168 jshamlet
 
363
          when "101" =>
364 210 jshamlet
            shd_dow          <= Wr_Data_q;
365 168 jshamlet
 
366
          when "110" =>
367 210 jshamlet
            update_rtc       <= '1';
368 168 jshamlet
 
369
          when "111" =>
370
            update_shd  <= '1';
371
 
372
          when others => null;
373
        end case;
374
      end if;
375
 
376
      -- Coherency timer - ensures that the shadow registers are updated with
377
      --  valid time data by delaying updates until the rtc registers have
378
      --  finished cascading.
379 210 jshamlet
      update_ctmr            <= update_ctmr - or_reduce(update_ctmr);
380 168 jshamlet
      if( rtc.frac_ro = '1' )then
381 210 jshamlet
        update_ctmr          <= (others => '1');
382 168 jshamlet
      end if;
383
 
384 244 jshamlet
      Rd_En_q                <= Rd_En_d;
385 210 jshamlet
      Rd_Data                <= OPEN8_NULLBUS;
386 244 jshamlet
      if( Rd_En_q = '1' )then
387
        case( Reg_Sel_q )is
388 168 jshamlet
          when "000" =>
389 210 jshamlet
            Rd_Data          <= interval;
390 168 jshamlet
          when "001" =>
391 210 jshamlet
            Rd_Data          <= shd_tens;
392 168 jshamlet
          when "010" =>
393 210 jshamlet
            Rd_Data          <= shd_secs;
394 168 jshamlet
          when "011" =>
395 210 jshamlet
            Rd_Data          <= shd_mins;
396 168 jshamlet
          when "100" =>
397 210 jshamlet
            Rd_Data          <= shd_hours;
398 168 jshamlet
          when "101" =>
399 210 jshamlet
            Rd_Data          <= shd_dow;
400 168 jshamlet
          when "110" =>
401
            null;
402
          when "111" =>
403 210 jshamlet
            Rd_Data          <= update_shd & "0000000";
404 168 jshamlet
          when others => null;
405
        end case;
406
      end if;
407
 
408
    end if;
409
  end process;
410
 
411
end architecture;

powered by: WebSVN 2.1.0

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