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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [misc/] [gptimer.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:      gptimer
20
-- File:        gptimer.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Description: This unit implemets a set of general-purpose timers with a 
23
--              common prescaler. Then number of timers and the width of
24
--              the timers is propgrammable through generics
25
------------------------------------------------------------------------------
26
 
27
library ieee;
28
use ieee.std_logic_1164.all;
29
library grlib;
30
use grlib.amba.all;
31
use grlib.stdlib.all;
32
use grlib.devices.all;
33
library gaisler;
34
use gaisler.misc.all;
35
--pragma translate_off
36
use std.textio.all;
37
--pragma translate_on
38
 
39
entity gptimer is
40
  generic (
41
    pindex   : integer := 0;
42
    paddr    : integer := 0;
43
    pmask    : integer := 16#fff#;
44
    pirq     : integer := 0;
45
    sepirq   : integer := 0;     -- use separate interrupts for each timer
46
    sbits    : integer := 16;                   -- scaler bits
47
    ntimers  : integer range 1 to 7 := 1;       -- number of timers
48
    nbits    : integer := 32;                   -- timer bits
49
    wdog     : integer := 0
50
  );
51
  port (
52
    rst    : in  std_ulogic;
53
    clk    : in  std_ulogic;
54
    apbi   : in  apb_slv_in_type;
55
    apbo   : out apb_slv_out_type;
56
    gpti   : in  gptimer_in_type;
57
    gpto   : out gptimer_out_type
58
  );
59
end;
60
 
61
architecture rtl of gptimer is
62
 
63
constant REVISION : integer := 0;
64
 
65
constant pconfig : apb_config_type := (
66
 
67
  1 => apb_iobar(paddr, pmask));
68
 
69
type timer_reg is record
70
  enable        :  std_ulogic;  -- enable counter
71
  load          :  std_ulogic;  -- load counter
72
  restart       :  std_ulogic;  -- restart counter
73
  irqpen        :  std_ulogic;  -- interrupt pending
74
  irqen         :  std_ulogic;  -- interrupt enable
75
  irq           :  std_ulogic;  -- interrupt pulse
76
  chain         :  std_ulogic;  -- chain with previous timer
77
  value         :  std_logic_vector(nbits-1 downto 0);
78
  reload        :  std_logic_vector(nbits-1 downto 0);
79
end record;
80
 
81
type timer_reg_vector is array (Natural range <> ) of timer_reg;
82
 
83
constant TBITS   : integer := log2x(ntimers+1);
84
 
85
type registers is record
86
  scaler        :  std_logic_vector(sbits-1 downto 0);
87
  reload        :  std_logic_vector(sbits-1 downto 0);
88
  tick          :  std_ulogic;
89
  tsel          :  integer range 0 to ntimers;
90
  timers        :  timer_reg_vector(1 to ntimers);
91
  dishlt        :  std_ulogic;
92
  wdogn         :  std_ulogic;
93
  wdog         :  std_ulogic;
94
end record;
95
 
96
signal r, rin : registers;
97
 
98
begin
99
 
100
  comb : process(rst, r, apbi, gpti)
101
  variable scaler : std_logic_vector(sbits downto 0);
102
  variable readdata, timer1 : std_logic_vector(31 downto 0);
103
  variable res, addin : std_logic_vector(nbits-1 downto 0);
104
  variable v : registers;
105
  variable z : std_ulogic;
106
  variable vtimers : timer_reg_vector(0 to ntimers);
107
  variable xirq : std_logic_vector(NAHBIRQ-1 downto 0);
108
  variable nirq : std_logic_vector(0 to ntimers-1);
109
  variable tick : std_logic_vector(1 to 7);
110
  begin
111
 
112
    v := r; v.tick := '0'; tick := (others => '0');
113
    vtimers(0) := ('0', '0', '0', '0', '0', '0', '0',
114
                    zero32(nbits-1 downto 0), zero32(nbits-1 downto 0) );
115
    vtimers(1 to ntimers) := r.timers; xirq := (others => '0');
116
    for i in 1 to ntimers loop
117
      v.timers(i).irq := '0'; v.timers(i).load := '0';
118
      tick(i) := r.timers(i).irq;
119
    end loop;
120
    v.wdogn := not r.timers(ntimers).irqpen; v.wdog := r.timers(ntimers).irqpen;
121
 
122
-- scaler operation
123
 
124
    scaler := ('0' & r.scaler) - 1;      -- decrement scaler
125
 
126
    if (not gpti.dhalt or r.dishlt) = '1' then  -- halt timers in debug mode
127
      if (scaler(sbits) = '1') then
128
        v.scaler := r.reload; v.tick := '1'; -- reload scaler
129
      else v.scaler := scaler(sbits-1 downto 0); end if;
130
    end if;
131
 
132
-- timer operation
133
 
134
    if (r.tick = '1') or (r.tsel /= 0) then
135
      if r.tsel = ntimers then v.tsel := 0;
136
      else v.tsel := r.tsel + 1; end if;
137
    end if;
138
 
139
    res := vtimers(r.tsel).value - 1;   -- decrement selected timer
140
    if (res(nbits-1) = '1') and ((vtimers(r.tsel).value(nbits-1) = '0'))
141
    then z := '1'; else z := '0'; end if; -- undeflow detect
142
 
143
-- update corresponding register and generate irq
144
 
145
    for i in 1 to ntimers-1 loop nirq(i) := r.timers(i).irq; end loop;
146
    nirq(0) := r.timers(ntimers).irq;
147
 
148
    for i in 1 to ntimers loop
149
 
150
      if i = r.tsel then
151
        if (r.timers(i).enable = '1') and
152
           (((r.timers(i).chain and nirq(i-1)) or not (r.timers(i).chain)) = '1')
153
        then
154
          v.timers(i).irq := z and not r.timers(i).load;
155
          if (v.timers(i).irq and r.timers(i).irqen) = '1' then
156
            v.timers(i).irqpen := '1';
157
          end if;
158
          v.timers(i).value := res;
159
          if (z and not r.timers(i).load) = '1' then
160
            v.timers(i).enable := r.timers(i).restart;
161
            if r.timers(i).restart = '1' then
162
              v.timers(i).value := r.timers(i).reload;
163
            end if;
164
          end if;
165
        end if;
166
      end if;
167
      if r.timers(i).load = '1' then
168
        v.timers(i).value := r.timers(i).reload;
169
      end if;
170
    end loop;
171
 
172
    if sepirq /= 0 then
173
      for i in 1 to ntimers loop
174
        xirq(i-1+pirq) := r.timers(i).irq and r.timers(i).irqen;
175
      end loop;
176
    else
177
      for i in 1 to ntimers loop
178
        xirq(pirq) := xirq(pirq) or (r.timers(i).irq and r.timers(i).irqen);
179
      end loop;
180
    end if;
181
 
182
-- read registers
183
 
184
    readdata := (others => '0');
185
    case apbi.paddr(6 downto 2) is
186
    when "00000" => readdata(sbits-1 downto 0)  := r.scaler;
187
    when "00001" => readdata(sbits-1 downto 0)  := r.reload;
188
    when "00010" =>
189
        readdata(2 downto 0) := conv_std_logic_vector(ntimers, 3) ;
190
        readdata(7 downto 3) := conv_std_logic_vector(pirq, 5) ;
191
        if (sepirq /= 0) then readdata(8) := '1'; end if;
192
        readdata(9) := r.dishlt;
193
    when others =>
194
      for i in 1 to ntimers loop
195
        if conv_integer(apbi.paddr(6 downto 4)) = i then
196
          case apbi.paddr(3 downto 2) is
197
          when "00" => readdata(nbits-1 downto 0) := r.timers(i).value;
198
          when "01" => readdata(nbits-1 downto 0) := r.timers(i).reload;
199
          when "10" => readdata(6 downto 0) :=
200
                gpti.dhalt & r.timers(i).chain &
201
                r.timers(i).irqpen & r.timers(i).irqen & r.timers(i).load &
202
                r.timers(i).restart & r.timers(i).enable;
203
          when others =>
204
          end case;
205
        end if;
206
      end loop;
207
    end case;
208
 
209
-- write registers
210
 
211
    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
212
      case apbi.paddr(6 downto 2) is
213
      when "00000" => v.scaler := apbi.pwdata(sbits-1 downto 0);
214
      when "00001" => v.reload := apbi.pwdata(sbits-1 downto 0);
215
                      v.scaler := apbi.pwdata(sbits-1 downto 0);
216
      when "00010" => v.dishlt := apbi.pwdata(9);
217
      when others =>
218
        for i in 1 to ntimers loop
219
          if conv_integer(apbi.paddr(6 downto 4)) = i then
220
            case apbi.paddr(3 downto 2) is
221
              when "00" => v.timers(i).value   := apbi.pwdata(nbits-1 downto 0);
222
              when "01" => v.timers(i).reload  := apbi.pwdata(nbits-1 downto 0);
223
              when "10" => v.timers(i).chain   := apbi.pwdata(5);
224
                           v.timers(i).irqpen  := apbi.pwdata(4);
225
                           v.timers(i).irqen   := apbi.pwdata(3);
226
                           v.timers(i).load    := apbi.pwdata(2);
227
                           v.timers(i).restart := apbi.pwdata(1);
228
                           v.timers(i).enable  := apbi.pwdata(0);
229
            when others =>
230
            end case;
231
          end if;
232
        end loop;
233
      end case;
234
    end if;
235
 
236
 
237
-- reset operation
238
 
239
    if rst = '0' then
240
      for i in 1 to ntimers loop
241
        v.timers(i).enable := '0'; v.timers(i).irqen := '0';
242
      end loop;
243
      v.scaler := (others => '1'); v.reload := (others => '1');
244
      v.tsel := 0; v.dishlt := '0'; v.timers(ntimers).irq := '0';
245
      if (wdog /= 0) then
246
        v.timers(ntimers).enable := '1'; v.timers(ntimers).load := '1';
247
        v.timers(ntimers).reload := conv_std_logic_vector(wdog, nbits);
248
        v.timers(ntimers).chain := '0'; v.timers(ntimers).irqen := '1';
249
        v.timers(ntimers).irqpen := '0'; v.timers(ntimers).restart := '0';
250
      end if;
251
    end if;
252
 
253
    timer1 := (others => '0'); timer1(nbits-1 downto 0) := r.timers(1).value;
254
 
255
    rin <= v;
256
    apbo.prdata <= readdata;    -- drive apb read bus
257
    apbo.pirq <= xirq;
258
    apbo.pindex <= pindex;
259
    gpto.tick <= r.tick & tick;
260
    gpto.timer1 <= timer1;      -- output timer1 value for debugging
261
    gpto.wdogn <= r.wdogn;
262
    gpto.wdog  <= r.wdog;
263
 
264
  end process;
265
 
266
  apbo.pconfig <= pconfig;
267
 
268
-- registers
269
 
270
  regs : process(clk)
271
  begin if rising_edge(clk) then r <= rin; end if; end process;
272
 
273
-- boot message
274
 
275
-- pragma translate_off
276
    bootmsg : report_version
277
    generic map ("gptimer" & tost(pindex) &
278
        ": GR Timer Unit rev " & tost(REVISION) &
279
        ", " & tost(sbits) & "-bit scaler, " & tost(ntimers) &
280
        " " & tost(nbits) & "-bit timers" & ", irq " & tost(pirq));
281
-- pragma translate_on
282
 
283
end;

powered by: WebSVN 2.1.0

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