-------------------------------------------------------------------------------
-- Title :
-- Project    : Arithmetic blocks
-------------------------------------------------------------------------------
-- File        : smac.VHD
-- Author      : Jamil Khatib  
-- Organization: OpenIPCore Project
-- Created     : 2000/04/12
-- Last update : 2000/04/17
-- Platform    : 
-- Simulators  : Modelsim 5.3XE / Windows98
-- Synthesizers: Leonardo / WindowsNT
-- Target      : 
-- Dependency  : 
-------------------------------------------------------------------------------
-- Description: Arithmetic blocks
-------------------------------------------------------------------------------
-- Copyright (c) 2000 Jamil Khatib
-- 
-- This VHDL design file is an open design; you can redistribute it and/or
-- modify it and/or implement it under the terms of the Openip General Public
-- License as it is going to be published by the OpenIPCore Organization and
-- any coming versions of this license.
-- You can check the draft license at
-- http://www.openip.org/oc/license.html

-------------------------------------------------------------------------------
-- Revisions  :
-- Revision Number :   1
-- Version         :   0.1
-- Date            :   12th Apr 2000
-- Modifier        :   Jamil Khatib (khatib@ieee.org)
-- Desccription    :   Created
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Revision Number :   2
-- Version         :   0.2
-- Date            :   17th Apr 2000
-- Modifier        :   Jamil Khatib (khatib@ieee.org)
-- Desccription    :   More generic
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Revision Number :   3
-- Version         :   0.3
-- Date            :   18th Apr 2000
-- Modifier        :   "Gerli, Luca" (luca_gerli@mentorg.com>)
-- Desccription    :   Speed and size improvement
--
-------------------------------------------------------------------------------



library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;


entity ScaleMAC is


  generic (
    OPSIZE : integer := 8);             -- Operand size


  port (
    Op1 : in  std_logic_vector(OPSIZE - 1 downto 0);  -- Operand 1
    Op2 : in  std_logic_vector(OPSIZE - 1 downto 0);  -- Operand 2
    Res : out std_logic_vector(OPSIZE -1 downto 0);   -- Result

	 Overflow : out std_logic; -- Overflow
    ValidOut : out std_logic;           -- valid output active high
    clk      : in  std_logic;           -- system clock positive edge
    rst_n    : in  std_logic);          -- system reset active low

end ScaleMAC;


library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

use ieee.std_logic_unsigned.all;



architecture behavior of ScaleMAC is


begin  -- behavior

  -- purpose: calculates MAC using serial approach
  -- type   : sequential
  -- inputs : clk    positive edge
  --          rst_n  active low
  -- outputs: 
  mac                 : process (clk, rst_n)
    variable op2tmp   : std_logic_vector(OPSIZE - 1 downto 0); -- Temporary store of operand 2                                        
    variable op1tmp   : std_logic_vector(OPSIZE - 1 downto 0); -- Temporary store of operand 1                                        
    variable tmpres   : std_logic_vector(OPSIZE - 1 downto 0); -- Temporary result                                        
    variable andres   : std_logic_vector(OPSIZE -1 downto 0);  -- Anding result
    variable count    : integer range 0 to (OPSIZE-1);  -- counter
    variable validvar : std_logic;      -- ValidOut variable
    variable overflowvar : std_logic;      -- ValidOut variable
    variable resvar : std_logic_vector(OPSIZE -1 downto 0);  
  begin  -- process mac

	if rst_n = '0' then                 -- asynchronous reset (active low)


		resvar := (others => '0');
		validvar := '1';
		op2tmp   := (others => '0');
		op1tmp   := (others => '0');
		tmpres   := (others => '0');
		count    := 0;
		overflowvar := '0';

	elsif clk'event and clk = '1' then  -- rising clock edge

		if validvar = '1' then
			validvar := '0';
			tmpres   := (others => '0');
			op1tmp   := op1;
			op2tmp   := op2;
			overflowvar := '0';
		end if; -- if validvar = '1' then

		overflowvar := overflowvar or tmpres(OPSIZE-1);
		tmpres := tmpres(OPSIZE - 2 downto 0 ) & '0';
		if op2tmp(OPSIZE-1) = '1' then
			tmpres := tmpres + op1tmp;
		end if;
		op2tmp := op2tmp(OPSIZE-2 downto 0) & '0';

		if count = (OPSIZE-1) then
			validvar := '1';
			resvar := tmpres;
			count    := 0;
		else
			count := count + 1;          
		end if; -- if count = (OPSIZE-1) then

	end if; -- elsif clk'event and clk = '1' then
	
	ValidOut <= validvar;
	Overflow <= overflowvar;
	Res <= resvar;
	
  end process mac;

end behavior;