-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- =============================================================================
-- Authors: Thomas B. Preusser
--
-- Entity: Poc.arith_counter_free
--
-- Description:
--
-- Implements a free-running counter that generates a strobe signal every
-- DIVIDER-th cycle the increment input was asserted. There is deliberately no
-- output or specification of the counter value so as to allow an implementation
-- to optimize as much as possible.
--
-- The implementation guarantees a strobe output directly from a register. It is
-- asserted exactly for one clock after DIVIDER cycles of an asserted increment
-- input have been observed.
--
-- License:
-- =============================================================================
-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
-- Chair of VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- =============================================================================
library IEEE;
use IEEE.std_logic_1164.all;
entity [docs]arith_counter_free is
generic (
DIVIDER : positive
);
port (
-- Global Control
clk : in std_logic;
rst : in std_logic;
inc : in std_logic;
stb : out std_logic -- End-of-Period Strobe
);
end entity arith_counter_free;
library IEEE;
use IEEE.numeric_std.all;
library PoC;
use PoC.utils.all;
architecture [docs]rtl of arith_counter_free is
begin
genNoDiv: if DIVIDER = 1 generate
process(clk)
begin
if rising_edge(clk) then
stb <= inc;
end if;
end process;
end generate genNoDiv;
genDoDiv: if DIVIDER > 1 generate
-- Note: For DIVIDER=2**K+1, this could be marginally reduced to log2ceil(DIVIDER-1)
-- if it was known that the increment input inc would never be deasserted.
constant N : natural := log2ceil(DIVIDER);
signal Cnt : unsigned(N downto 0) := (others => '0');
signal cin : unsigned(0 downto 0);
begin
cin(0) <= not inc;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
Cnt <= to_unsigned(DIVIDER-2, N+1);
else
Cnt <= Cnt + ite(Cnt(N) = '0', (Cnt'range => '1'), to_unsigned(DIVIDER-1, N+1)) + cin;
end if;
end if;
end process;
stb <= Cnt(N);
end generate genDoDiv;
end rtl;