1 |
2 |
danv |
-------------------------------------------------------------------------------
|
2 |
|
|
--
|
3 |
|
|
-- Copyright (C) 2009
|
4 |
|
|
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
5 |
|
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
6 |
|
|
--
|
7 |
|
|
-- This program is free software: you can redistribute it and/or modify
|
8 |
|
|
-- it under the terms of the GNU General Public License as published by
|
9 |
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
10 |
|
|
-- (at your option) any later version.
|
11 |
|
|
--
|
12 |
|
|
-- This program is distributed in the hope that it will be useful,
|
13 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 |
|
|
-- GNU General Public License for more details.
|
16 |
|
|
--
|
17 |
|
|
-- You should have received a copy of the GNU General Public License
|
18 |
|
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19 |
|
|
--
|
20 |
|
|
-------------------------------------------------------------------------------
|
21 |
|
|
|
22 |
|
|
-- Purpose : Counter with extra options
|
23 |
|
|
-- Description:
|
24 |
|
|
-- - default wrap at 2**g_width or special wrap at fixed g_max or dynamically via cnt_max
|
25 |
|
|
-- - default increment +1 or other g_step_size
|
26 |
|
|
-- - external clr
|
27 |
|
|
-- - external load with g_init or dynamically via load
|
28 |
|
|
-- Remarks:
|
29 |
|
|
-- . If g_max = 2**g_width then use g_max=0 for default wrap and avoid truncation warning.
|
30 |
|
|
-- The check g_max = 2**g_width does not work for g_width >= 31 due to that the INTEGER
|
31 |
|
|
-- range in VHDL is limited to -2**31 to +2**31-1. Therefore detect that g_max = 2**g_width
|
32 |
|
|
-- via ceil_log2(g_max+1)>g_width and use this to init the cnt_max input.
|
33 |
|
|
|
34 |
|
|
LIBRARY IEEE, common_pkg_lib;
|
35 |
|
|
USE IEEE.std_logic_1164.all;
|
36 |
|
|
USE common_pkg_lib.common_pkg.ALL;
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
ENTITY common_counter IS
|
40 |
|
|
GENERIC (
|
41 |
|
|
g_latency : NATURAL := 1; -- default 1 for registered count output, use 0 for immediate combinatorial count output
|
42 |
|
|
g_init : INTEGER := 0;
|
43 |
|
|
g_width : NATURAL := 32;
|
44 |
|
|
g_max : NATURAL := 0; -- default 0 to disable the g_max setting.
|
45 |
|
|
g_step_size : INTEGER := 1 -- counting in steps of g_step_size, can be + or -
|
46 |
|
|
);
|
47 |
|
|
PORT (
|
48 |
|
|
rst : IN STD_LOGIC := '0'; -- either use asynchronous rst or synchronous cnt_clr
|
49 |
|
|
clk : IN STD_LOGIC;
|
50 |
|
|
clken : IN STD_LOGIC := '1';
|
51 |
|
|
cnt_clr : IN STD_LOGIC := '0'; -- synchronous cnt_clr is only interpreted when clken is active
|
52 |
|
|
cnt_ld : IN STD_LOGIC := '0'; -- cnt_ld loads the output count with the input load value, independent of cnt_en
|
53 |
|
|
cnt_en : IN STD_LOGIC := '1';
|
54 |
|
|
cnt_max : IN STD_LOGIC_VECTOR(g_width-1 DOWNTO 0) := TO_UVEC(sel_a_b(ceil_log2(g_max+1)>g_width, 0, g_max), g_width); -- see remarks
|
55 |
|
|
load : IN STD_LOGIC_VECTOR(g_width-1 DOWNTO 0) := TO_SVEC(g_init, g_width);
|
56 |
|
|
count : OUT STD_LOGIC_VECTOR(g_width-1 DOWNTO 0)
|
57 |
|
|
);
|
58 |
|
|
END common_counter;
|
59 |
|
|
|
60 |
|
|
|
61 |
|
|
ARCHITECTURE rtl OF common_counter IS
|
62 |
|
|
|
63 |
|
|
CONSTANT zeros : STD_LOGIC_VECTOR(count'RANGE) := (OTHERS => '0'); -- used to check if cnt_max is zero
|
64 |
|
|
SIGNAL reg_count : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width); -- in case rst is not used
|
65 |
|
|
SIGNAL nxt_count : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width); -- to avoid Warning: NUMERIC_STD.">=": metavalue detected, returning FALSE, when using unsigned()
|
66 |
|
|
SIGNAL comb_count : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width); -- to avoid Warning: NUMERIC_STD.">=": metavalue detected, returning FALSE, when using unsigned()
|
67 |
|
|
|
68 |
|
|
BEGIN
|
69 |
|
|
|
70 |
|
|
comb_count <= nxt_count;
|
71 |
|
|
|
72 |
|
|
count <= comb_count WHEN g_latency=0 ELSE reg_count;
|
73 |
|
|
|
74 |
|
|
ASSERT g_step_size /= 0 REPORT "common_counter: g_step_size must be /= 0" SEVERITY FAILURE;
|
75 |
|
|
|
76 |
|
|
p_clk : PROCESS (rst, clk)
|
77 |
|
|
BEGIN
|
78 |
|
|
IF rst = '1' THEN
|
79 |
|
|
reg_count <= TO_SVEC(g_init, g_width);
|
80 |
|
|
ELSIF rising_edge(clk) THEN
|
81 |
|
|
IF clken='1' THEN
|
82 |
|
|
reg_count <= nxt_count;
|
83 |
|
|
END IF;
|
84 |
|
|
END IF;
|
85 |
|
|
END PROCESS;
|
86 |
|
|
|
87 |
|
|
p_count : PROCESS(reg_count, cnt_clr, cnt_en, cnt_ld, load, cnt_max)
|
88 |
|
|
BEGIN
|
89 |
|
|
nxt_count <= reg_count;
|
90 |
|
|
IF cnt_clr='1' OR (reg_count=cnt_max AND cnt_max /= zeros) THEN
|
91 |
|
|
nxt_count <= (OTHERS => '0');
|
92 |
|
|
ELSIF cnt_ld='1' THEN
|
93 |
|
|
nxt_count <= load;
|
94 |
|
|
ELSIF cnt_en='1' THEN
|
95 |
|
|
nxt_count <= INCR_UVEC(reg_count, g_step_size);
|
96 |
|
|
END IF;
|
97 |
|
|
END PROCESS;
|
98 |
|
|
|
99 |
|
|
END rtl;
|