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 210

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
--            :   seconds, and tenths of a second. Module is doubled buffered
28
--            :   to ensure time consistency during accesses. Also provides
29
--            :   a programmable periodic interrupt timer, as well as a uSec
30
--            :    tick for external use.
31 191 jshamlet
--
32 168 jshamlet
-- Register Map:
33
-- Offset  Bitfield Description                        Read/Write
34
--   0x0   AAAAAAAA Periodic Interval Timer in uS      (RW)
35 189 jshamlet
--   0x1   -AAAAAAA Tenths  (0x00 - 0x63)              (RW)
36
--   0x2   --AAAAAA Seconds (0x00 - 0x3B)              (RW)
37
--   0x3   --AAAAAA Minutes (0x00 - 0x3B)              (RW)
38
--   0x4   ---AAAAA Hours   (0x00 - 0x17)              (RW)
39 168 jshamlet
--   0x5   -----AAA Day of Week (0x00 - 0x06)          (RW)
40
--   0x6   -------- Update RTC regs from Shadow Regs   (WO)
41
--   0x7   A------- Update Shadow Regs from RTC regs   (RW)
42
--                  A = Update is Busy
43
 
44
library ieee;
45
use ieee.std_logic_1164.all;
46
  use ieee.std_logic_unsigned.all;
47
  use ieee.std_logic_arith.all;
48
  use ieee.std_logic_misc.all;
49
 
50
library work;
51
  use work.open8_pkg.all;
52
 
53
entity o8_rtc is
54
generic(
55 210 jshamlet
  Sys_Freq                   : real;
56
  Reset_Level                : std_logic;
57
  Address                    : ADDRESS_TYPE
58 168 jshamlet
);
59
port(
60 210 jshamlet
  Clock                      : in  std_logic;
61
  Reset                      : in  std_logic;
62
  uSec_Tick                  : out std_logic;
63 168 jshamlet
  --
64 210 jshamlet
  Bus_Address                : in  ADDRESS_TYPE;
65
  Wr_Enable                  : in  std_logic;
66
  Wr_Data                    : in  DATA_TYPE;
67
  Rd_Enable                  : in  std_logic;
68
  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 210 jshamlet
  constant User_Addr         : std_logic_vector(15 downto 3)
78
                               := Address(15 downto 3);
79
  alias  Comp_Addr           is Bus_Address(15 downto 3);
80
  signal Addr_Match          : std_logic;
81 168 jshamlet
 
82 210 jshamlet
  alias  Reg_Addr            is Bus_Address(2 downto 0);
83
  signal Reg_Addr_q          : std_logic_vector(2 downto 0);
84 168 jshamlet
 
85 210 jshamlet
  signal Wr_En               : std_logic;
86
  signal Wr_Data_q           : DATA_TYPE;
87
  signal Rd_En               : std_logic;
88 168 jshamlet
 
89 210 jshamlet
  constant DLY_1USEC_VAL     : integer := integer(Sys_Freq / 1000000.0);
90
  constant DLY_1USEC_WDT     : integer := ceil_log2(DLY_1USEC_VAL - 1);
91
  constant DLY_1USEC         : std_logic_vector :=
92
                     conv_std_logic_vector( DLY_1USEC_VAL - 1, DLY_1USEC_WDT);
93 168 jshamlet
 
94 210 jshamlet
  signal uSec_Cntr           : std_logic_vector( DLY_1USEC_WDT - 1 downto 0 )
95
                               := (others => '0');
96
  signal uSec_Tick_i         : std_logic;
97 168 jshamlet
 
98
  type PIT_TYPE is record
99
    timer_cnt           : DATA_TYPE;
100
    timer_ro            : std_logic;
101
  end record;
102
 
103
  signal pit            : PIT_TYPE;
104
 
105
  type RTC_TYPE is record
106
    frac                : std_logic_vector(15 downto 0);
107
    frac_ro             : std_logic;
108
 
109
    tens_l              : std_logic_vector(3 downto 0);
110
    tens_l_ro           : std_logic;
111
 
112
    tens_u              : std_logic_vector(3 downto 0);
113
    tens_u_ro           : std_logic;
114
 
115
    secs_l              : std_logic_vector(3 downto 0);
116
    secs_l_ro           : std_logic;
117
 
118
    secs_u              : std_logic_vector(3 downto 0);
119
    secs_u_ro           : std_logic;
120
 
121
    mins_l              : std_logic_vector(3 downto 0);
122
    mins_l_ro           : std_logic;
123
 
124
    mins_u              : std_logic_vector(3 downto 0);
125
    mins_u_ro           : std_logic;
126
 
127
    hours_l             : std_logic_vector(3 downto 0);
128
    hours_l_ro          : std_logic;
129
 
130
    hours_u             : std_logic_vector(3 downto 0);
131
    hours_u_ro          : std_logic;
132
 
133
    dow                 : std_logic_vector(2 downto 0);
134
  end record;
135
 
136
  constant DECISEC      : std_logic_vector(15 downto 0) :=
137
                           conv_std_logic_vector(10000,16);
138
 
139
  signal rtc            : RTC_TYPE;
140
 
141
  signal interval       : DATA_TYPE;
142 210 jshamlet
  signal update_interval: std_logic;
143
  signal new_interval   : DATA_TYPE;
144 168 jshamlet
 
145
  signal shd_tens       : DATA_TYPE;
146
  signal shd_secs       : DATA_TYPE;
147
  signal shd_mins       : DATA_TYPE;
148
  signal shd_hours      : DATA_TYPE;
149
  signal shd_dow        : DATA_TYPE;
150
 
151
  signal update_rtc     : std_logic;
152
  signal update_shd     : std_logic;
153
  signal update_ctmr    : std_logic_vector(3 downto 0);
154
 
155
begin
156
 
157 210 jshamlet
  uSec_Tick                  <= uSec_Tick_i;
158
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
159 168 jshamlet
 
160 210 jshamlet
  Interrupt_PIT              <= pit.timer_ro;
161
  Interrupt_RTC              <= rtc.frac_ro;
162 168 jshamlet
 
163
  io_reg: process( Clock, Reset )
164
  begin
165
    if( Reset = Reset_Level )then
166 210 jshamlet
      uSec_Cntr              <= (others => '0');
167
      uSec_Tick_i            <= '0';
168 168 jshamlet
 
169 210 jshamlet
      pit.timer_cnt          <= x"00";
170
      pit.timer_ro           <= '0';
171 168 jshamlet
 
172 210 jshamlet
      rtc.frac               <= DECISEC;
173
      rtc.frac_ro            <= '0';
174 168 jshamlet
 
175 210 jshamlet
      rtc.tens_l             <= (others => '0');
176
      rtc.tens_l_ro          <= '0';
177 168 jshamlet
 
178 210 jshamlet
      rtc.tens_u             <= (others => '0');
179
      rtc.tens_u_ro          <= '0';
180 168 jshamlet
 
181 210 jshamlet
      rtc.secs_l             <= (others => '0');
182
      rtc.secs_l_ro          <= '0';
183 168 jshamlet
 
184 210 jshamlet
      rtc.secs_u             <= (others => '0');
185
      rtc.secs_u_ro          <= '0';
186 168 jshamlet
 
187 210 jshamlet
      rtc.mins_l             <= (others => '0');
188
      rtc.mins_l_ro          <= '0';
189 168 jshamlet
 
190 210 jshamlet
      rtc.mins_u             <= (others => '0');
191
      rtc.mins_u_ro          <= '0';
192 168 jshamlet
 
193 210 jshamlet
      rtc.hours_l            <= (others => '0');
194
      rtc.hours_l_ro         <= '0';
195 168 jshamlet
 
196 210 jshamlet
      rtc.hours_u            <= (others => '0');
197
      rtc.hours_u_ro         <= '0';
198 168 jshamlet
 
199 210 jshamlet
      rtc.dow                <= (others => '0');
200 168 jshamlet
 
201 210 jshamlet
      shd_tens               <= (others => '0');
202
      shd_secs               <= (others => '0');
203
      shd_mins               <= (others => '0');
204
      shd_hours              <= (others => '0');
205
      shd_dow                <= (others => '0');
206 168 jshamlet
 
207 210 jshamlet
      update_rtc             <= '0';
208
      update_shd             <= '0';
209
      update_ctmr            <= (others => '0');
210 168 jshamlet
 
211 210 jshamlet
      interval               <= x"00";
212
      update_interval        <= '0';
213
      new_interval           <= x"00";
214 168 jshamlet
 
215 210 jshamlet
      Wr_Data_q              <= (others => '0');
216
      Reg_Addr_q             <= (others => '0');
217
      Wr_En                  <= '0';
218
      Rd_En                  <= '0';
219
      Rd_Data                <= OPEN8_NULLBUS;
220 168 jshamlet
 
221
    elsif( rising_edge( Clock ) )then
222
 
223 210 jshamlet
      uSec_Cntr              <= uSec_Cntr - 1;
224
      uSec_Tick_i            <= '0';
225 168 jshamlet
      if( uSec_Cntr = 0 )then
226 210 jshamlet
        uSec_Cntr            <= DLY_1USEC;
227
        uSec_Tick_i          <= '1';
228 168 jshamlet
      end if;
229
 
230
      -- Periodic Interval Timer
231 210 jshamlet
      pit.timer_cnt          <= pit.timer_cnt - uSec_Tick_i;
232
      pit.timer_ro           <= '0';
233
      if( update_interval = '1' )then
234
        pit.timer_cnt        <= new_interval;
235
      elsif( or_reduce(pit.timer_cnt) = '0' )then
236
        pit.timer_cnt        <= interval;
237
        pit.timer_ro         <= or_reduce(interval);
238
 
239 168 jshamlet
      end if;
240
 
241
      -- Fractional decisecond counter - cycles every 10k microseconds
242 210 jshamlet
      rtc.frac               <= rtc.frac - uSec_Tick_i;
243
      rtc.frac_ro            <= '0';
244 168 jshamlet
      if( or_reduce(rtc.frac) = '0' or update_rtc = '1' )then
245 210 jshamlet
        rtc.frac             <= DECISEC;
246
        rtc.frac_ro          <= not update_rtc;
247 168 jshamlet
      end if;
248
 
249
      -- Decisecond counter (lower)
250 210 jshamlet
      rtc.tens_l             <= rtc.tens_l + rtc.frac_ro;
251
      rtc.tens_l_ro          <= '0';
252 168 jshamlet
      if( update_rtc = '1' )then
253 210 jshamlet
        rtc.tens_l           <= shd_tens(3 downto 0);
254 168 jshamlet
      elsif( rtc.tens_l > x"9")then
255 210 jshamlet
        rtc.tens_l           <= (others => '0');
256
        rtc.tens_l_ro        <= '1';
257 168 jshamlet
      end if;
258
 
259
      -- Decisecond counter (upper)
260 210 jshamlet
      rtc.tens_u             <= rtc.tens_u + rtc.tens_l_ro;
261
      rtc.tens_u_ro          <= '0';
262 168 jshamlet
      if( update_rtc = '1' )then
263 210 jshamlet
        rtc.tens_u           <= shd_tens(7 downto 4);
264 168 jshamlet
      elsif( rtc.tens_u > x"9")then
265 210 jshamlet
        rtc.tens_u           <= (others => '0');
266
        rtc.tens_u_ro        <= '1';
267 168 jshamlet
      end if;
268
 
269
      -- Second counter (lower)
270 210 jshamlet
      rtc.secs_l             <= rtc.secs_l + rtc.tens_u_ro;
271
      rtc.secs_l_ro          <= '0';
272 168 jshamlet
      if( update_rtc = '1' )then
273 210 jshamlet
        rtc.secs_l           <= shd_secs(3 downto 0);
274 168 jshamlet
      elsif( rtc.secs_l > x"9")then
275 210 jshamlet
        rtc.secs_l           <= (others => '0');
276
        rtc.secs_l_ro        <= '1';
277 168 jshamlet
      end if;
278
 
279
      -- Second counter (upper)
280 210 jshamlet
      rtc.secs_u             <= rtc.secs_u + rtc.secs_l_ro;
281
      rtc.secs_u_ro          <= '0';
282 168 jshamlet
      if( update_rtc = '1' )then
283 210 jshamlet
        rtc.secs_u           <= shd_secs(7 downto 4);
284 168 jshamlet
      elsif( rtc.secs_u > x"5")then
285 210 jshamlet
        rtc.secs_u           <= (others => '0');
286
        rtc.secs_u_ro        <= '1';
287 168 jshamlet
      end if;
288
 
289
      -- Minutes counter (lower)
290 210 jshamlet
      rtc.mins_l             <= rtc.mins_l + rtc.secs_u_ro;
291
      rtc.mins_l_ro          <= '0';
292 168 jshamlet
      if( update_rtc = '1' )then
293 210 jshamlet
        rtc.mins_l           <= shd_mins(3 downto 0);
294 168 jshamlet
      elsif( rtc.mins_l > x"9")then
295 210 jshamlet
        rtc.mins_l           <= (others => '0');
296
        rtc.mins_l_ro        <= '1';
297 168 jshamlet
      end if;
298
 
299
      -- Minutes counter (upper)
300 210 jshamlet
      rtc.mins_u             <= rtc.mins_u + rtc.mins_l_ro;
301
      rtc.mins_u_ro          <= '0';
302 168 jshamlet
      if( update_rtc = '1' )then
303 210 jshamlet
        rtc.mins_u           <= shd_mins(7 downto 4);
304 168 jshamlet
      elsif( rtc.mins_u > x"5")then
305 210 jshamlet
        rtc.mins_u           <= (others => '0');
306
        rtc.mins_u_ro        <= '1';
307 168 jshamlet
      end if;
308
 
309
      -- Hour counter (lower)
310 210 jshamlet
      rtc.hours_l            <= rtc.hours_l + rtc.mins_u_ro;
311
      rtc.hours_l_ro         <= '0';
312 168 jshamlet
      if( update_rtc = '1' )then
313 210 jshamlet
        rtc.hours_l          <= shd_hours(3 downto 0);
314 168 jshamlet
      elsif( rtc.hours_l > x"9")then
315 210 jshamlet
        rtc.hours_l          <= (others => '0');
316
        rtc.hours_l_ro       <= '1';
317 168 jshamlet
      end if;
318
 
319
      -- Hour counter (upper)
320 210 jshamlet
      rtc.hours_u            <= rtc.hours_u + rtc.hours_l_ro;
321 168 jshamlet
      if( update_rtc = '1' )then
322 210 jshamlet
        rtc.hours_u          <= shd_hours(7 downto 4);
323 168 jshamlet
      end if;
324
 
325 210 jshamlet
      rtc.hours_u_ro         <= '0';
326 168 jshamlet
      if( rtc.hours_u >= x"2" and rtc.hours_l > x"3" )then
327 210 jshamlet
        rtc.hours_l          <= (others => '0');
328
        rtc.hours_u          <= (others => '0');
329
        rtc.hours_u_ro       <= '1';
330 168 jshamlet
      end if;
331
 
332
      -- Day of Week counter
333 210 jshamlet
      rtc.dow                <= rtc.dow + rtc.hours_u_ro;
334 168 jshamlet
      if( update_rtc = '1' )then
335 210 jshamlet
        rtc.dow              <= shd_dow(2 downto 0);
336 168 jshamlet
      elsif( rtc.dow = x"07")then
337 210 jshamlet
        rtc.dow              <= (others => '0');
338 168 jshamlet
      end if;
339
 
340
      -- Copy the RTC registers to the shadow registers when the coherency
341
      --  timer is zero (RTC registers are static)
342
      if( update_shd = '1' and or_reduce(update_ctmr) = '0' )then
343 210 jshamlet
        shd_tens             <= rtc.tens_u & rtc.tens_l;
344
        shd_secs             <= rtc.secs_u & rtc.secs_l;
345
        shd_mins             <= rtc.mins_u & rtc.mins_l;
346
        shd_hours            <= rtc.hours_u & rtc.hours_l;
347
        shd_dow              <= "00000" & rtc.dow;
348
        update_shd           <= '0';
349 168 jshamlet
      end if;
350
 
351 210 jshamlet
      update_interval        <= '0';
352 209 jshamlet
 
353 210 jshamlet
      Reg_Addr_q             <= Reg_Addr;
354
      Wr_Data_q              <= Wr_Data;
355 168 jshamlet
 
356 210 jshamlet
      Wr_En                  <= Addr_Match and Wr_Enable;
357
      update_rtc             <= '0';
358 168 jshamlet
      if( Wr_En = '1' )then
359
        case( Reg_Addr_q )is
360
          when "000" =>
361 210 jshamlet
            new_interval     <= Wr_Data_q;
362
            update_interval  <= '1';
363 168 jshamlet
 
364
          when "001" =>
365 210 jshamlet
            shd_tens         <= Wr_Data_q;
366 168 jshamlet
 
367
          when "010" =>
368 210 jshamlet
            shd_secs         <= Wr_Data_q;
369 168 jshamlet
 
370
          when "011" =>
371 210 jshamlet
            shd_mins         <= Wr_Data_q;
372 168 jshamlet
 
373
          when "100" =>
374 210 jshamlet
            shd_hours        <= Wr_Data_q;
375 168 jshamlet
 
376
          when "101" =>
377 210 jshamlet
            shd_dow          <= Wr_Data_q;
378 168 jshamlet
 
379
          when "110" =>
380 210 jshamlet
            update_rtc       <= '1';
381 168 jshamlet
 
382
          when "111" =>
383
            update_shd  <= '1';
384
 
385
          when others => null;
386
        end case;
387
      end if;
388
 
389
      -- Coherency timer - ensures that the shadow registers are updated with
390
      --  valid time data by delaying updates until the rtc registers have
391
      --  finished cascading.
392 210 jshamlet
      update_ctmr            <= update_ctmr - or_reduce(update_ctmr);
393 168 jshamlet
      if( rtc.frac_ro = '1' )then
394 210 jshamlet
        update_ctmr          <= (others => '1');
395 168 jshamlet
      end if;
396
 
397 210 jshamlet
      Rd_Data                <= OPEN8_NULLBUS;
398
      Rd_En                  <= Addr_Match and Rd_Enable;
399 168 jshamlet
      if( Rd_En = '1' )then
400
        case( Reg_Addr_q )is
401
          when "000" =>
402 210 jshamlet
            Rd_Data          <= interval;
403 168 jshamlet
          when "001" =>
404 210 jshamlet
            Rd_Data          <= shd_tens;
405 168 jshamlet
          when "010" =>
406 210 jshamlet
            Rd_Data          <= shd_secs;
407 168 jshamlet
          when "011" =>
408 210 jshamlet
            Rd_Data          <= shd_mins;
409 168 jshamlet
          when "100" =>
410 210 jshamlet
            Rd_Data          <= shd_hours;
411 168 jshamlet
          when "101" =>
412 210 jshamlet
            Rd_Data          <= shd_dow;
413 168 jshamlet
          when "110" =>
414
            null;
415
          when "111" =>
416 210 jshamlet
            Rd_Data          <= update_shd & "0000000";
417 168 jshamlet
          when others => null;
418
        end case;
419
      end if;
420
 
421
    end if;
422
  end process;
423
 
424
end architecture;

powered by: WebSVN 2.1.0

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