-- 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
-- Martin Zabel
-- Steffen Koehler
--
-- Entity: Gray-Code counter.
--
-- Description:
--
-- .. TODO:: No documentation available.
--
-- License:
-- =============================================================================
-- Copyright 2007-2014 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;
use ieee.numeric_std.all;
entity [docs]arith_counter_gray is
generic (
BITS : positive; -- Bit width of the counter
INIT : natural := 0 -- Initial/reset counter value
);
port (
clk : in std_logic;
rst : in std_logic; -- Reset to INIT value
inc : in std_logic; -- Increment
dec : in std_logic := '0'; -- Decrement
val : out std_logic_vector(BITS-1 downto 0); -- Value output
cry : out std_logic -- Carry output
);
end entity arith_counter_gray;
architecture [docs]rtl of arith_counter_gray is
-- purpose: gray constant encoder
function [docs]gray_encode (val : natural; len : positive) return unsigned is
variable bin : unsigned(len-1 downto 0) := to_unsigned(val, len);
begin
if len = 1 then
return bin;
end if;
return bin xor '0' & bin(len-1 downto 1);
end gray_encode;
-- purpose: parity generation
function [docs]parity (val : unsigned) return std_logic is
variable res : std_logic := '0';
begin -- parity
for i in val'range loop
res := res xor val(i);
end loop;
return res;
end parity;
-- Counter Register
constant INIT_GRAY : unsigned(BITS-1 downto 0) := gray_encode(INIT, BITS);
signal gray_cnt_r : unsigned(BITS-1 downto 0) := INIT_GRAY;
signal gray_cnt_nxt : unsigned(BITS-1 downto 0);
signal en : std_logic; -- enable: inc xor dec
begin
-----------------------------------------------------------------------------
-- Actual Counter Register
en <= inc xor dec;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
gray_cnt_r <= INIT_GRAY;
elsif en = '1' then
gray_cnt_r <= gray_cnt_nxt;
end if;
end if;
end process;
val <= std_logic_vector(gray_cnt_r);
-----------------------------------------------------------------------------
-- Computation of Increment/Decrement
-- Trivial one-bit Counter
g1: if BITS = 1 generate
gray_cnt_nxt <= not gray_cnt_r;
cry <= gray_cnt_r(0) xor dec;
end generate g1;
-- Multi-Bit Counter
g2: if BITS > 1 generate
constant INIT_PAR : std_logic := parity(INIT_GRAY);
-- search for first one in gray_cnt_r(MSB-1 downto LSB)
-- first_one_n(i) = '1' denotes position i
-- parity of gray_cnt_r
signal par_r : std_logic := INIT_PAR;
signal par_nxt : std_logic;
begin
-- Parity Register
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
par_r <= INIT_PAR;
elsif en = '1' then
par_r <= par_nxt;
end if;
end if;
end process;
-- Computation of next Value
process(gray_cnt_r, par_r, dec)
variable x : unsigned(BITS-1 downto 0);
variable s : unsigned(BITS-1 downto 0);
begin
-- Prefer inc over dec to keep combinational path short in standard use.
x := gray_cnt_r(BITS-2 downto 0) & (par_r xnor dec);
x(x'left) := not gray_cnt_r(BITS-1); -- catch final carry to invert last bit
s := not x + 1; -- locate first intermediate '1'
gray_cnt_nxt <= s(BITS-1) & (gray_cnt_r(BITS-2 downto 0) xor
(s(BITS-2 downto 0) and x(BITS-2 downto 0)));
par_nxt <= s(0) xor dec;
end process;
cry <= (gray_cnt_r(BITS-1) xor dec) and (gray_cnt_nxt(BITS-1) xnor dec);
end generate g2;
end rtl;