-- 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:					This module detects whether all bit positions of a std_logic_vector have the same value.
--
-- Description:
-- 
-- This circuit may, for instance, be used to detect the first sign change
-- and, thus, the range of a two's complement number.
--
-- These components may be chained by using the output of the predecessor as
-- guard input. This chaining allows to have intermediate results available
-- while still ensuring the use of a fast carry chain on supporting FPGA
-- architectures. When chaining, make sure to overlap both vector slices by one
-- bit position as to avoid an undetected sign change between the slices.
--
-- License:
-- =============================================================================
-- Copyright 2007-2015 Technische Universität 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.config.all;
use			PoC.utils.all;
use			PoC.arith.all;


entity [docs]arith_same is
	generic (
		N : positive														 -- Input width
	);
	port (
		g : in	std_logic := '1';								-- Guard Input (!g => !y)
		x : in	std_logic_vector(N-1 downto 0);	-- Input Vector
		y : out std_logic												-- All-same Output
	);
end entity;


architecture [docs]rtl of arith_same is
	constant DEV_INFO	: T_DEVICE_INFO		:= DEVICE_INFO;

	constant K : positive := DEV_INFO.LUT_FanIn;			-- LUT Fanin
	constant M : positive := (N-2+1/N)/(K-1) + 1;			-- Required Stage Count
	signal	 p : std_logic_vector(M-1 downto 0);			-- Stage Propagates

begin

	-- Compute Propagates in LUT Stages
	genCC: for i in 0 to M-1 generate
		-- Relevant Vector Slice
		constant LO : natural :=						i	 *(K-1);
		constant HI : natural := imin(N-1, (i+1)*(K-1));
	begin
		p(i) <= '1' when x(HI downto LO) = (HI downto LO => '0') else
						'1' when x(HI downto LO) = (HI downto LO => '1') else
						'0';
	end generate;

	-- Compute Equivalence in Carry Chain
	genXLXn: if DEV_INFO.Vendor /= VENDOR_XILINX generate
		signal	 s : std_logic_vector(M downto 0);
	begin
		-- Infere Carry Chain from Addition
		s <= std_logic_vector(unsigned('0' & p) + (0 to 0 => g));
		y <= s(M);
	end generate genXLXn;

	genXLXy: if DEV_INFO.Vendor = VENDOR_XILINX generate
		i: arith_inc_ovcy_xilinx
			generic map (
				N => M
			)
			port map (
				p => p,
				g => g,
				v => y
			);
	end generate genXLXy;
end architecture;