OpenCores
URL https://opencores.org/ocsvn/astron_requantizer/astron_requantizer/trunk

Subversion Repositories astron_requantizer

[/] [astron_requantizer/] [trunk/] [common_resize.vhd] - Rev 3

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
-- 
-- 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, common_pkg_lib, common_components_lib;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE common_pkg_lib.common_pkg.ALL;
 
ENTITY common_resize IS
  GENERIC (
    g_representation  : STRING  := "SIGNED";  -- SIGNED or UNSIGNED resizing
    g_clip            : BOOLEAN := FALSE;     -- when TRUE clip input if it is outside the output range, else wrap
    g_clip_symmetric  : BOOLEAN := FALSE;     -- when TRUE clip signed symmetric to +c_smax and -c_smax, else to +c_smax and c_smin_symm
                                              -- for wrapping when g_clip=FALSE the g_clip_symmetric is ignored, so signed wrapping is done asymmetric
    g_pipeline_input  : NATURAL := 0;         -- >= 0
    g_pipeline_output : NATURAL := 1;         -- >= 0
    g_in_dat_w        : INTEGER := 36;
    g_out_dat_w       : INTEGER := 18
  );
  PORT (
    clk        : IN  STD_LOGIC;
    clken      : IN  STD_LOGIC := '1';
    in_dat     : IN  STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
    out_dat    : OUT STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
    out_ovr    : OUT STD_LOGIC
  );
END;
 
 
ARCHITECTURE rtl OF common_resize IS
 
  -- Clipping is only necessary when g_out_dat_w<g_in_dat_w.
  CONSTANT c_clip      : BOOLEAN := g_clip AND (g_out_dat_w<g_in_dat_w);
 
  -- Use SIGNED, UNSIGNED to avoid NATURAL (32 bit range) overflow error
  CONSTANT c_umax      : UNSIGNED(out_dat'RANGE) := UNSIGNED(      c_slv1(g_out_dat_w-1 DOWNTO 0));  -- =  2** g_out_dat_w   -1
  CONSTANT c_smax      :   SIGNED(out_dat'RANGE) :=   SIGNED('0' & c_slv1(g_out_dat_w-2 DOWNTO 0));  -- =  2**(g_out_dat_w-1)-1
  CONSTANT c_smin_most :   SIGNED(out_dat'RANGE) :=   SIGNED('1' & c_slv0(g_out_dat_w-2 DOWNTO 0));  -- = -2**(c_in_dat_w-1)
  CONSTANT c_smin_symm :   SIGNED(out_dat'RANGE) := -c_smax;                                         -- = -2**(c_in_dat_w-1)+1
  CONSTANT c_smin      :   SIGNED(out_dat'RANGE) := sel_a_b(g_clip_symmetric, c_smin_symm, c_smin_most);
 
  SIGNAL reg_dat     : STD_LOGIC_VECTOR(in_dat'RANGE);
  SIGNAL wrap        : STD_LOGIC;
  SIGNAL clip        : STD_LOGIC;
  SIGNAL sign        : STD_LOGIC;
  SIGNAL res_ovr     : STD_LOGIC;
  SIGNAL res_dat     : STD_LOGIC_VECTOR(out_dat'RANGE);
  SIGNAL res_vec     : STD_LOGIC_VECTOR(g_out_dat_w DOWNTO 0);
  SIGNAL out_vec     : STD_LOGIC_VECTOR(g_out_dat_w DOWNTO 0);
 
BEGIN
 
  u_input_pipe : ENTITY common_components_lib.common_pipeline  -- pipeline input
  GENERIC MAP (
    g_representation => "SIGNED",
    g_pipeline       => g_pipeline_input,
    g_in_dat_w       => g_in_dat_w,
    g_out_dat_w      => g_in_dat_w
  )
  PORT MAP (
    clk     => clk,
    clken   => clken,
    in_dat  => in_dat,
    out_dat => reg_dat
  );
 
  no_clip : IF c_clip=FALSE GENERATE
    -- Note that g_pipeline_input=0 AND g_clip=FALSE is equivalent to using RESIZE_SVEC or RESIZE_UVEC directly.
    gen_s : IF g_representation="SIGNED" GENERATE
      -- If g_out_dat_w>g_in_dat_w then IEEE resize extends the sign bit,
      -- else IEEE resize preserves the sign bit and keeps the low part.
      wrap <= '1' WHEN SIGNED(reg_dat)>c_smax OR SIGNED(reg_dat)< c_smin_most ELSE '0';
      res_dat <= RESIZE_SVEC(reg_dat, g_out_dat_w);
      res_ovr <= wrap;
    END GENERATE;
 
    gen_u : IF g_representation="UNSIGNED" GENERATE
      -- If g_out_dat_w>g_in_dat_w then IEEE resize sign extends with '0',
      -- else IEEE resize keeps the low part.
      wrap <= '1' WHEN UNSIGNED(reg_dat)>c_umax ELSE '0';
      res_dat <= RESIZE_UVEC(reg_dat, g_out_dat_w);
      res_ovr <= wrap;
    END GENERATE;
  END GENERATE;
 
  gen_clip : IF c_clip=TRUE GENERATE
    gen_s_clip : IF g_representation="SIGNED" GENERATE
      clip <= '1' WHEN SIGNED(reg_dat)>c_smax OR SIGNED(reg_dat)< c_smin ELSE '0';
      sign <= reg_dat(reg_dat'HIGH);
      res_dat <= reg_dat(out_dat'RANGE) WHEN clip='0' ELSE STD_LOGIC_VECTOR( c_smax) WHEN sign='0' ELSE STD_LOGIC_VECTOR(c_smin);
      res_ovr <= clip;
    END GENERATE;
 
    gen_u_clip : IF g_representation="UNSIGNED" GENERATE
      clip <= '1' WHEN UNSIGNED(reg_dat)>c_umax ELSE '0';
      res_dat <= reg_dat(out_dat'RANGE) WHEN clip='0' ELSE STD_LOGIC_VECTOR(c_umax);
      res_ovr <= clip;
    END GENERATE;
  END GENERATE;
 
  res_vec <= res_ovr & res_dat;
 
  u_output_pipe : ENTITY common_components_lib.common_pipeline  -- pipeline output
  GENERIC MAP (
    g_representation => "SIGNED",
    g_pipeline       => g_pipeline_output,
    g_in_dat_w       => g_out_dat_w+1,
    g_out_dat_w      => g_out_dat_w+1
  )
  PORT MAP (
    clk     => clk,
    clken   => clken,
    in_dat  => res_vec,
    out_dat => out_vec
  );
 
  out_ovr <= out_vec(g_out_dat_w);
  out_dat <= out_vec(g_out_dat_w-1 DOWNTO 0);
 
END rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.