Wolf-LITE/FPGA/tx_ciccomp/auk_dspip_roundsat_hpfir.vhd

188 wiersze
7.5 KiB
VHDL

-- (C) 2001-2018 Intel Corporation. All rights reserved.
-- Your use of Intel Corporation's design tools, logic functions and other
-- software and tools, and its AMPP partner logic functions, and any output
-- files from any of the foregoing (including device programming or simulation
-- files), and any associated documentation or information are expressly subject
-- to the terms and conditions of the Intel Program License Subscription
-- Agreement, Intel FPGA IP License Agreement, or other applicable
-- license agreement, including, without limitation, that your use is for the
-- sole purpose of programming logic devices manufactured by Intel and sold by
-- Intel or its authorized distributors. Please refer to the applicable
-- agreement for further details.
-------------------------------------------------------------------------
-------------------------------------------------------------------------
--
-- Revision Control Information
--
-- $RCSfile: auk_dspip_roundsat_hpfir.vhd,v $
--
-- $Revision: #1 $
-- $Date: 2010/08/19 $
-- Check in by : $Author: max $
--
-- Description :
-- Implement output options for HP-FIR
--
-- ALTERA Confidential and Proprietary
-- Copyright 2006 (c) Altera Corporation
-- All rights reserved
--
-------------------------------------------------------------------------
-------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity auk_dspip_roundsat_hpfir is
generic (
IN_WIDTH_g : natural := 8; -- i/p data width
REM_LSB_BIT_g : natural := 2; -- no. of lsb to be removed
REM_LSB_TYPE_g : string := "trunc"; -- trunc/round
REM_MSB_BIT_g : natural := 2; -- no. of msb to be removed
REM_MSB_TYPE_g : string := "trunc" -- trunc/sat
);
port (
clk : in std_logic;
reset_n : in std_logic;
enable : in std_logic;
datain : in std_logic_vector(IN_WIDTH_g-1 downto 0);
valid : out std_logic;
dataout : out std_logic_vector(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1 downto 0)
);
end entity auk_dspip_roundsat_hpfir;
architecture beh of auk_dspip_roundsat_hpfir is
signal data_lsb : std_logic_vector(IN_WIDTH_g-REM_LSB_BIT_g-1 downto 0);
signal valid_lsb : std_logic;
signal data_msb : std_logic_vector(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1 downto 0);
constant zero_vec : std_logic_vector := std_logic_vector(to_signed(0, REM_LSB_BIT_g));
begin -- architecture beh
-----------------------------------------------------------------------------
-- lsb : trunc/round-up (symmetric)
-----------------------------------------------------------------------------
remove_lsb: if REM_LSB_BIT_g > 0 generate
begin
trunc_lsb: if REM_LSB_TYPE_g = "trunc" generate
begin
data_lsb <= datain(IN_WIDTH_g-1 downto REM_LSB_BIT_g);
valid_lsb <= enable;
end generate trunc_lsb;
rndup_lsb: if REM_LSB_TYPE_g = "round" generate
round_up_sym_p : process (clk, reset_n)
variable OR_accu : std_logic := '0';
begin
if reset_n = '0' then
data_lsb <= (others => '0');
valid_lsb <= '0';
elsif rising_edge(clk) then
if enable = '1' then
OR_accu := '0';
for i in 0 to REM_LSB_BIT_g-2 loop
OR_accu := OR_accu or datain(i);
end loop;
-- negative value
if (datain(IN_WIDTH_g-1) = '1') then
-- larger than -x.5 : rounded to -x
if (datain(REM_LSB_BIT_g-1)='1' and OR_accu='1') then
data_lsb <= std_logic_vector(signed(datain(IN_WIDTH_g-1 downto REM_LSB_BIT_g))+1);
-- less than or equal -x.5 : rounded to -x + 1
else
data_lsb <= datain(IN_WIDTH_g-1 downto REM_LSB_BIT_g);
end if;
-- positive value
else
-- maximum positive value
if datain(IN_WIDTH_g-1 downto REM_LSB_BIT_g-1) = std_logic_vector(to_signed(2**(IN_WIDTH_g-REM_LSB_BIT_g)-1, IN_WIDTH_g-REM_LSB_BIT_g+1)) then
data_lsb <= std_logic_vector(to_signed( 2**(IN_WIDTH_g-REM_LSB_BIT_g-1)-1, IN_WIDTH_g-REM_LSB_BIT_g));
-- larger than or equal x.5 : rounded to x + 1
elsif datain(REM_LSB_BIT_g-1) = '1' then
data_lsb <= std_logic_vector(signed(datain(IN_WIDTH_g-1 downto REM_LSB_BIT_g))+1);
-- less than x.5 : rounded to x
else
data_lsb <= datain(IN_WIDTH_g-1 downto REM_LSB_BIT_g);
end if;
end if;
end if;
valid_lsb <= enable;
end if;
end process round_up_sym_p;
end generate rndup_lsb;
end generate remove_lsb;
-----------------------------------------------------------------------------
-- keep lsb
-----------------------------------------------------------------------------
keep_lsb: if REM_LSB_BIT_g = 0 generate
begin
data_lsb <= datain;
valid_lsb <= enable;
end generate keep_lsb;
-----------------------------------------------------------------------------
-- msb : trunc/saturation
-----------------------------------------------------------------------------
remove_msb: if REM_MSB_BIT_g > 0 generate
signal min_val, max_val : std_logic_vector(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1 downto 0);
begin
trunc_msb: if REM_MSB_TYPE_g = "trunc" generate
begin
data_msb <= data_lsb(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1 downto 0);
dataout <= data_msb;
valid <= valid_lsb;
end generate trunc_msb;
sat_msb: if REM_MSB_TYPE_g = "sat" generate
max_val(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1) <= '0';
max_val(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-2 downto 0) <= (others => '1');
min_val(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1) <= '1';
min_val(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-2 downto 0) <= (others => '0');
data_msb <= std_logic_vector(max_val) when signed(data_lsb) > signed(max_val) else
std_logic_vector(min_val) when signed(data_lsb) < signed(min_val) else
data_lsb(IN_WIDTH_g-REM_LSB_BIT_g-REM_MSB_BIT_g-1 downto 0);
msb_p : process (clk, reset_n)
begin
if reset_n = '0' then
dataout <= (others => '0');
valid <= '0';
elsif rising_edge(clk) then
if valid_lsb = '1' then
dataout <= data_msb;
end if;
valid <= valid_lsb;
end if;
end process msb_p;
end generate sat_msb;
end generate remove_msb;
-----------------------------------------------------------------------------
-- keep msb
-----------------------------------------------------------------------------
keep_msb: if REM_MSB_BIT_g = 0 generate
begin
data_msb <= data_lsb;
dataout <= data_msb;
valid <= valid_lsb;
end generate keep_msb;
-----------------------------------------------------------------------------
-- error checking:
-- Have we got a valid round mode?
-- Is the input greater than the output?
-----------------------------------------------------------------------------
assert (REM_LSB_TYPE_g = "trunc" or
REM_LSB_TYPE_g = "round" or
REM_MSB_TYPE_g = "trunc" or
REM_MSB_TYPE_g = "sat"
) report "Please check your round type and its spelling. Currently, we only support trunc, and round for LSB, trunc and sat for MSB" severity error;
end architecture beh;