-- 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: Patrick Lehmann
--
-- Package: Common primitives described as a function
--
-- Description:
--
-- This packages describes common primitives like flip flops and multiplexers
-- as a function to use them as one-liners.
--
-- ATTENSION:
-- The parameter 'constant INIT' of some functions is actually the reset
-- value, not the initial value after device programming (e.g. for FPGAs),
-- this value MUST be set via signal declaration!
--
-- License:
-- =============================================================================
-- Copyright 2007-2016 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;
library PoC;
use PoC.utils.all;
package [docs]components is
-- implement an optional register stage
function [docs]registered(signal Clock : std_logic; constant IsRegistered : boolean) return boolean;
-- FlipFlop functions
-- ===========================================================================
-- RS-FlipFlops
function [docs]ffrs(q : std_logic; rst : std_logic := '0'; set : std_logic := '0') return std_logic; -- RS-FlipFlop with dominant rst
function [docs]ffsr(q : std_logic; rst : std_logic := '0'; set : std_logic := '0') return std_logic; -- RS-FlipFlop with dominant set
-- D-FlipFlops (Delay)
function [docs]ffdre(q : std_logic; d : std_logic; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : std_logic := '0') return std_logic; -- D-FlipFlop with reset and enable
function [docs]ffdre(q : std_logic_vector; d : std_logic_vector; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : std_logic_vector := (0 to 0 => '0')) return std_logic_vector; -- D-FlipFlop with reset and enable
function [docs]ffdse(q : std_logic; d : std_logic; set : std_logic := '0'; en : std_logic := '1') return std_logic; -- D-FlipFlop with set and enable
-- T-FlipFlops (Toggle)
function [docs]fftre(q : std_logic; t : std_logic; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : std_logic := '0') return std_logic; -- T-FlipFlop with reset and enable
function [docs]fftse(q : std_logic; t : std_logic; set : std_logic := '0'; en : std_logic := '1') return std_logic; -- T-FlipFlop with set and enable
-- counter
function [docs]upcounter_next(cnt : unsigned; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : natural := 0) return unsigned;
function [docs]upcounter_equal(cnt : unsigned; value : natural) return std_logic;
function [docs]downcounter_next(cnt : signed; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : integer := 0) return signed;
function [docs]downcounter_equal(cnt : signed; value : integer) return std_logic;
function [docs]downcounter_neg(cnt : signed) return std_logic;
-- shiftregisters
function [docs]shreg_left(q : std_logic_vector; i : std_logic; en : std_logic := '1') return std_logic_vector;
function [docs]shreg_right(q : std_logic_vector; i : std_logic; en : std_logic := '1') return std_logic_vector;
-- rotate registers
function [docs]rreg_left(q : std_logic_vector; en : std_logic := '1') return std_logic_vector;
function [docs]rreg_right(q : std_logic_vector; en : std_logic := '1') return std_logic_vector;
-- compare
function [docs]comp(value1 : std_logic_vector; value2 : std_logic_vector) return std_logic_vector;
function [docs]comp(value1 : unsigned; value2 : unsigned) return unsigned;
function [docs]comp(value1 : signed; value2 : signed) return signed;
function [docs]comp_allzero(value : std_logic_vector) return std_logic;
function [docs]comp_allzero(value : unsigned) return std_logic;
function [docs]comp_allzero(value : signed) return std_logic;
function [docs]comp_allone(value : std_logic_vector) return std_logic;
function [docs]comp_allone(value : unsigned) return std_logic;
function [docs]comp_allone(value : signed) return std_logic;
-- multiplexing
function [docs]mux(sel : std_logic; sl0 : std_logic; sl1 : std_logic) return std_logic;
function [docs]mux(sel : std_logic; slv0 : std_logic_vector; slv1 : std_logic_vector) return std_logic_vector;
function [docs]mux(sel : std_logic; us0 : unsigned; us1 : unsigned) return unsigned;
function [docs]mux(sel : std_logic; s0 : signed; s1 : signed) return signed;
end package;
package body components is
-- implement an optional register stage
-- ===========================================================================
function registered(signal Clock : std_logic; constant IsRegistered : boolean) return boolean is
begin
return ite(IsRegistered, rising_edge(Clock), TRUE);
end function;
-- FlipFlops
-- ===========================================================================
-- D-flipflop with reset and enable
function ffdre(q : std_logic; d : std_logic; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : std_logic := '0') return std_logic is
begin
if not SIMULATION then
if (INIT = '0') then
return ((d and en) or (q and not en)) and not rst;
elsif (INIT = '1') then
return ((d and en) or (q and not en)) or rst;
else
report "Unsupported INIT value for synthesis." severity FAILURE;
return 'X';
end if;
elsif (rst = '1') then
return INIT;
else
return ((d and en) or (q and not en));
end if;
end function;
function ffdre(q : std_logic_vector; d : std_logic_vector; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : std_logic_vector := (0 to 0 => '0')) return std_logic_vector is
constant INIT_I : std_logic_vector(q'range) := resize(INIT, q'length);
variable Result : std_logic_vector(q'range);
begin
for i in q'range loop
Result(i) := ffdre(q => q(i), d => d(i), rst => rst, en => en, INIT => INIT_I(i));
end loop;
return Result;
end function;
-- D-flipflop with set and enable
function ffdse(q : std_logic; d : std_logic; set : std_logic := '0'; en : std_logic := '1') return std_logic is
begin
return ffdre(q => q, d => d, rst => set, en => en, INIT => '1');
end function;
-- T-flipflop with reset and enable
function fftre(q : std_logic; t : std_logic; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : std_logic := '0') return std_logic is
begin
if not SIMULATION then
if (INIT = '0') then
return ((not q and (t and en)) or (q and not (t and en))) and not rst;
elsif (INIT = '1') then
return ((not q and (t and en)) or (q and not (t and en))) or rst;
else
report "Unsupported INIT value for synthesis." severity FAILURE;
return 'X';
end if;
elsif (rst = '1') then
return INIT;
else
return ((not q and (t and en)) or (q and not (t and en)));
end if;
end function;
-- T-flipflop with set and enable
function fftse(q : std_logic; t : std_logic; set : std_logic := '0'; en : std_logic := '1') return std_logic is
begin
return fftre(q => q, t => t, rst => set, en => en, INIT => '1');
end function;
-- RS-flipflop with dominant rst
function ffrs(q : std_logic; rst : std_logic := '0'; set : std_logic := '0') return std_logic is
begin
return (q or set) and not rst;
end function;
-- RS-flipflop with dominant set
function ffsr(q : std_logic; rst : std_logic := '0'; set : std_logic := '0') return std_logic is
begin
return (q and not rst) or set;
end function;
-- Counters
-- ===========================================================================
-- up-counter
function upcounter_next(cnt : unsigned; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : natural := 0) return unsigned is
begin
if (rst = '1') then
return to_unsigned(INIT, cnt'length);
elsif (en = '1') then
return cnt + 1;
else
return cnt;
end if;
end function;
function upcounter_equal(cnt : unsigned; value : natural) return std_logic is
begin
-- optimized comparison for only up counting values
return to_sl((cnt and to_unsigned(value, cnt'length)) = value);
end function;
-- down-counter
function downcounter_next(cnt : signed; rst : std_logic := '0'; en : std_logic := '1'; constant INIT : integer := 0) return signed is
begin
if (rst = '1') then
return to_signed(INIT, cnt'length);
elsif (en = '1') then
return cnt - 1;
else
return cnt;
end if;
end function;
function downcounter_equal(cnt : signed; value : integer) return std_logic is
begin
-- optimized comparison for only down counting values
return to_sl((cnt nor to_signed(value, cnt'length)) /= value);
end function;
function downcounter_neg(cnt : signed) return std_logic is
begin
return cnt(cnt'high);
end function;
-- Shift/Rotate Registers
-- ===========================================================================
function shreg_left(q : std_logic_vector; i : std_logic; en : std_logic := '1') return std_logic_vector is
begin
return mux(en, q, q(q'left - 1 downto q'right) & i);
end function;
function shreg_right(q : std_logic_vector; i : std_logic; en : std_logic := '1') return std_logic_vector is
begin
return mux(en, q, i & q(q'left downto q'right - 1));
end function;
function rreg_left(q : std_logic_vector; en : std_logic := '1') return std_logic_vector is
begin
return mux(en, q, q(q'left - 1 downto q'right) & q(q'left));
end function;
function rreg_right(q : std_logic_vector; en : std_logic := '1') return std_logic_vector is
begin
return mux(en, q, q(q'right) & q(q'left downto q'right - 1));
end function;
-- compare functions
-- ===========================================================================
-- Returns, when
-- 1- => value1 < value2 (difference is negative)
-- 00 => value1 = value2 (difference is zero)
-- -1 => value1 > value2 (difference is positive)
function comp(value1 : std_logic_vector; value2 : std_logic_vector) return std_logic_vector is
begin
report "Comparing two STD_LOGIC_VECTORs - implicit conversion to UNSIGNED" severity WARNING;
return std_logic_vector(comp(unsigned(value1), unsigned(value2)));
end function;
function comp(value1 : unsigned; value2 : unsigned) return unsigned is
begin
if value1 < value2 then
return "10";
elsif value1 = value2 then
return "00";
else
return "01";
end if;
end function;
function comp(value1 : signed; value2 : signed) return signed is
begin
if value1 < value2 then
return "10";
elsif value1 = value2 then
return "00";
else
return "01";
end if;
end function;
function comp_allzero(value : std_logic_vector) return std_logic is
begin
return comp_allzero(unsigned(value));
end function;
function comp_allzero(value : unsigned) return std_logic is
begin
return to_sl(value = (value'range => '0'));
end function;
function comp_allzero(value : signed) return std_logic is
begin
return to_sl(value = (value'range => '0'));
end function;
function comp_allone(value : std_logic_vector) return std_logic is
begin
return comp_allone(unsigned(value));
end function;
function comp_allone(value : unsigned) return std_logic is
begin
return to_sl(value = (value'range => '1'));
end function;
function comp_allone(value : signed) return std_logic is
begin
return to_sl(value = (value'range => '1'));
end function;
-- multiplexers
function mux(sel : std_logic; sl0 : std_logic; sl1 : std_logic) return std_logic is
begin
return (sl0 and not sel) or (sl1 and sel);
end function;
function mux(sel : std_logic; slv0 : std_logic_vector; slv1 : std_logic_vector) return std_logic_vector is
begin
return (slv0 and not (slv0'range => sel)) or (slv1 and (slv1'range => sel));
end function;
function mux(sel : std_logic; us0 : unsigned; us1 : unsigned) return unsigned is
begin
return (us0 and not (us0'range => sel)) or (us1 and (us1'range => sel));
end function;
function mux(sel : std_logic; s0 : signed; s1 : signed) return signed is
begin
return (s0 and not (s0'range => sel)) or (s1 and (s1'range => sel));
end function;
end package body;