--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    12:16:14 10/02/05
-- Design Name:    
-- Module Name:    mix_cpx - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
USE ieee.numeric_std.ALL;

library ieee_proposed;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.fixed_pkg.all;

use work.fixed_util_pkg.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity undc_real is
Generic
(
	nbits_data		: integer := 12;
	nbits_data_frac	: integer := 12;
	nbits_k			: integer := 12;
	nbits_k_frac	: integer := 12;
	has_in_reg		: boolean := false;
	rounding		: fixed_round_style_type := fixed_round;
	saturating		: fixed_overflow_style_type := fixed_saturate
);
Port
(
	srst		: in std_logic;
	clk			: in std_logic;
	din_valid	: in std_logic;
	din			: in sfixed;
	kin_valid	: in std_logic;
	kin			: in sfixed;
	dout_valid	: out std_logic;
	dout		: out sfixed;
	dc_out		: out sfixed
);
end undc_real;

architecture Behavioral of undc_real is

constant nbits_internal : integer := nbits_data + nbits_data;
constant nbits_internal_frac : integer := nbits_data_frac + nbits_data_frac;

signal x : sfixed(sproto(nbits_data, nbits_data_frac)'high downto sproto(nbits_data, nbits_data_frac)'low);
signal k : sfixed(sproto(nbits_k, nbits_k_frac)'high downto sproto(nbits_k, nbits_k_frac)'low);
signal dc : sfixed(sproto(nbits_internal, nbits_internal_frac)'high downto sproto(nbits_internal, nbits_internal_frac)'low);
signal y : sfixed(sproto(nbits_internal, nbits_internal_frac)'high downto sproto(nbits_internal, nbits_internal_frac)'low);
signal y1 : sfixed(sproto(nbits_internal, nbits_internal_frac)'high downto sproto(nbits_internal, nbits_internal_frac)'low);
signal y2 : sfixed(sproto(nbits_internal, nbits_internal_frac)'high downto sproto(nbits_internal, nbits_internal_frac)'low);

begin

dout <= resize(y, sproto(nbits_data, nbits_data_frac), saturating, rounding);
dc_out <= resize(dc, sproto(nbits_data, nbits_data_frac), fixed_wrap, fixed_truncate);

------------------------------------------------------------
	proc_din_reg: process(clk, din_valid, din)
	begin
		if has_in_reg = true then
			if rising_edge(clk) then
				if srst = '1' then
					x <= to_sfixed(0, x);
				else
					if din_valid = '1' then
						x <= din;
					end if;
				end if;
			end if;
		else
			x <= din;
		end if;
	end process;

------------------------------------------------------------
	proc_valid_reg: process(clk, din_valid)
	begin
		if has_in_reg = true then
			if rising_edge(clk) then
				if srst = '1' then
					dout_valid <= '0';
				else
					dout_valid <= din_valid;
				end if;
			end if;
		else
			dout_valid <= din_valid;
		end if;
	end process;

------------------------------------------------------------
	proc_kin_reg: process(clk, kin_valid, kin)
	begin
		if rising_edge(clk) then
			if srst = '1' then
				k <= to_sfixed(0, k);
			else
				if kin_valid = '1' then
					k <= kin;
				end if;
			end if;
		end if;
	end process;

------------------------------------------------------------
	proc_pipe_y: process(clk, x, dc)
	begin
		y <= resize(x - dc, y, fixed_wrap, fixed_truncate);
		if rising_edge(clk) then
			if srst = '1' then
				y1 <= to_sfixed(0, y1);
				y2 <= to_sfixed(0, y2);
				dc <= to_sfixed(0, dc);
			else
				y1 <= y;
				y2 <= resize(y1 * k, y2, fixed_wrap, fixed_truncate);
				dc <= resize(y2 + dc, dc, fixed_wrap, fixed_truncate);
			end if;	
		end if;	
	end process;
	
------------------------------------------------------------
end Behavioral;
