1 |
2 |
danv |
-------------------------------------------------------------------------------
|
2 |
|
|
--
|
3 |
3 |
danv |
-- Copyright 2020
|
4 |
2 |
danv |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
5 |
|
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
6 |
3 |
danv |
--
|
7 |
|
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
|
|
-- you may not use this file except in compliance with the License.
|
9 |
|
|
-- You may obtain a copy of the License at
|
10 |
|
|
--
|
11 |
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
12 |
|
|
--
|
13 |
|
|
-- Unless required by applicable law or agreed to in writing, software
|
14 |
|
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
|
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
|
|
-- See the License for the specific language governing permissions and
|
17 |
|
|
-- limitations under the License.
|
18 |
2 |
danv |
--
|
19 |
|
|
-------------------------------------------------------------------------------
|
20 |
|
|
|
21 |
|
|
-- Purpose : Counter with extra options
|
22 |
|
|
-- Description:
|
23 |
|
|
-- - default wrap at 2**g_width or special wrap at fixed g_max or dynamically via cnt_max
|
24 |
|
|
-- - default increment +1 or other g_step_size
|
25 |
|
|
-- - external clr
|
26 |
|
|
-- - external load with g_init or dynamically via load
|
27 |
|
|
-- Remarks:
|
28 |
|
|
-- . If g_max = 2**g_width then use g_max=0 for default wrap and avoid truncation warning.
|
29 |
|
|
-- The check g_max = 2**g_width does not work for g_width >= 31 due to that the INTEGER
|
30 |
|
|
-- range in VHDL is limited to -2**31 to +2**31-1. Therefore detect that g_max = 2**g_width
|
31 |
|
|
-- via ceil_log2(g_max+1)>g_width and use this to init the cnt_max input.
|
32 |
|
|
|
33 |
|
|
LIBRARY IEEE, common_pkg_lib;
|
34 |
|
|
USE IEEE.std_logic_1164.all;
|
35 |
|
|
USE common_pkg_lib.common_pkg.ALL;
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
ENTITY common_counter IS
|
39 |
|
|
GENERIC (
|
40 |
|
|
g_latency : NATURAL := 1; -- default 1 for registered count output, use 0 for immediate combinatorial count output
|
41 |
|
|
g_init : INTEGER := 0;
|
42 |
|
|
g_width : NATURAL := 32;
|
43 |
|
|
g_max : NATURAL := 0; -- default 0 to disable the g_max setting.
|
44 |
|
|
g_step_size : INTEGER := 1 -- counting in steps of g_step_size, can be + or -
|
45 |
|
|
);
|
46 |
|
|
PORT (
|
47 |
|
|
rst : IN STD_LOGIC := '0'; -- either use asynchronous rst or synchronous cnt_clr
|
48 |
|
|
clk : IN STD_LOGIC;
|
49 |
|
|
clken : IN STD_LOGIC := '1';
|
50 |
|
|
cnt_clr : IN STD_LOGIC := '0'; -- synchronous cnt_clr is only interpreted when clken is active
|
51 |
|
|
cnt_ld : IN STD_LOGIC := '0'; -- cnt_ld loads the output count with the input load value, independent of cnt_en
|
52 |
|
|
cnt_en : IN STD_LOGIC := '1';
|
53 |
|
|
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
|
54 |
|
|
load : IN STD_LOGIC_VECTOR(g_width-1 DOWNTO 0) := TO_SVEC(g_init, g_width);
|
55 |
|
|
count : OUT STD_LOGIC_VECTOR(g_width-1 DOWNTO 0)
|
56 |
|
|
);
|
57 |
|
|
END common_counter;
|
58 |
|
|
|
59 |
|
|
|
60 |
|
|
ARCHITECTURE rtl OF common_counter IS
|
61 |
|
|
|
62 |
|
|
CONSTANT zeros : STD_LOGIC_VECTOR(count'RANGE) := (OTHERS => '0'); -- used to check if cnt_max is zero
|
63 |
|
|
SIGNAL reg_count : STD_LOGIC_VECTOR(count'RANGE) := TO_SVEC(g_init, g_width); -- in case rst is not used
|
64 |
|
|
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()
|
65 |
|
|
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()
|
66 |
|
|
|
67 |
|
|
BEGIN
|
68 |
|
|
|
69 |
|
|
comb_count <= nxt_count;
|
70 |
|
|
|
71 |
|
|
count <= comb_count WHEN g_latency=0 ELSE reg_count;
|
72 |
|
|
|
73 |
|
|
ASSERT g_step_size /= 0 REPORT "common_counter: g_step_size must be /= 0" SEVERITY FAILURE;
|
74 |
|
|
|
75 |
|
|
p_clk : PROCESS (rst, clk)
|
76 |
|
|
BEGIN
|
77 |
|
|
IF rst = '1' THEN
|
78 |
|
|
reg_count <= TO_SVEC(g_init, g_width);
|
79 |
|
|
ELSIF rising_edge(clk) THEN
|
80 |
|
|
IF clken='1' THEN
|
81 |
|
|
reg_count <= nxt_count;
|
82 |
|
|
END IF;
|
83 |
|
|
END IF;
|
84 |
|
|
END PROCESS;
|
85 |
|
|
|
86 |
|
|
p_count : PROCESS(reg_count, cnt_clr, cnt_en, cnt_ld, load, cnt_max)
|
87 |
|
|
BEGIN
|
88 |
|
|
nxt_count <= reg_count;
|
89 |
|
|
IF cnt_clr='1' OR (reg_count=cnt_max AND cnt_max /= zeros) THEN
|
90 |
|
|
nxt_count <= (OTHERS => '0');
|
91 |
|
|
ELSIF cnt_ld='1' THEN
|
92 |
|
|
nxt_count <= load;
|
93 |
|
|
ELSIF cnt_en='1' THEN
|
94 |
|
|
nxt_count <= INCR_UVEC(reg_count, g_step_size);
|
95 |
|
|
END IF;
|
96 |
|
|
END PROCESS;
|
97 |
|
|
|
98 |
|
|
END rtl;
|