-------------------------------------------------------------------------------
-- Title :
-- Project : Arithmetic blocks
-------------------------------------------------------------------------------
-- File : arit.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
--
-------------------------------------------------------------------------------
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)
function BitsToSpan(num : integer) return integer is
variable work : integer;
begin
work := num-1;
for i in 1 to 32 loop
work := work/2;
if (work = 0) then return i; end if;
end loop;
-- report "BitsToSpan: Input too large" severity error;
return 0;
end;
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 : std_logic_vector(BitsToSpan(OPSIZE)-1 downto 0); -- counter
variable validvar : std_logic; -- ValidOut variable
begin -- process mac
if rst_n = '0' then -- asynchronous reset (active low)
ValidOut <= '1';
Res <= (others => '0');
validvar := '1';
op2tmp := (others => '0');
op1tmp := (others => '0');
tmpres := (others => '0');
andres := (others => '1');
count := (others => '0');
Overflow <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
andres := (others => '1');
if validvar = '1' then
ValidOut <= '0';
validvar := '0';
tmpres := (others => '0');
op1tmp := op1;
op2tmp := op2;
Overflow <= '0';
end if;
if count = (count'range => '1') then
ValidOut <= '1';
validvar := '1';
for i in 0 to OPSIZE -1 loop
andres(i) := op1tmp(i) and op2tmp(OPSIZE - 1 - conv_integer(count));
end loop; -- i
tmpres := andres + tmpres;
-- No shift in the last clock
Res <= tmpres;
count := (others => '0');
else
for i in 0 to OPSIZE -1 loop
andres(i) := op1tmp(i) and op2tmp(OPSIZE - 1 - conv_integer(count));
end loop; -- i
tmpres := andres + tmpres;
if tmpres(OPSIZE -1 ) = '1' then
Overflow <= '1';
end if;
tmpres := tmpres(OPSIZE -2 downto 0 ) & '0';
Res <= tmpres;
end if;
count := count + 1;
end if;
end process mac;
end behavior;