--------------------------------------------------------------------------------------------------- -- Filename : mt_fil_mac_slow.vhd -- Project : maintech filter toolbox -- Purpose : MAC cell for FIR-like filters -- - version for 'slow' filter versions --------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------- -- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany -- -- written by Matthias Kleffel -- -- -- -- This program is free software; you can redistribute it and/or modify -- -- it under the terms of the GNU General Public License as published by -- -- the Free Software Foundation as version 3 of the License, or -- -- -- -- This program is distributed in the hope that it will be useful, -- -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -- GNU General Public License V3 for more details. -- -- -- -- You should have received a copy of the GNU General Public License -- -- along with this program. If not, see . -- ----------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -- mt_fil_mac_slow ------------------------------------------------------------ ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; use work.all; use work.mt_toolbox.all; use work.mt_filter.all; entity mt_fil_mac_slow is port ( -- common clk : in std_logic; reset : in std_logic; -- control-path start : in std_logic; active : in std_logic; presub : in std_logic; -- data input smp1 : in fir_dataword18; smp2 : in fir_dataword18; coeff : in fir_dataword18; -- data output dnew : out std_logic; dout : out fir_dataword18 ); end mt_fil_mac_slow; architecture rtl of mt_fil_mac_slow is -- rounding constant (16 bits will get truncated) constant RNDVAL : natural := (2**16/2); -- control signals signal done : std_logic; signal active_del : std_logic_vector(2 downto 0); signal start_del : std_logic_vector(2 downto 0); signal done_del : std_logic_vector(2 downto 0); -- data registers signal psreg : std_logic; signal dreg : signed(17 downto 0); signal b0reg : signed(17 downto 0); signal b1reg : signed(18 downto 0); signal a0reg : signed(17 downto 0); signal a1reg : signed(17 downto 0); signal mreg : signed(35 downto 0); signal preg : signed(35 downto 0); begin -- create done-flag after 'active' goes low or 'start' is set while still active done <= (start or (not active)) and active_del(0); -- create delayed control-signals process(clk) begin if rising_edge(clk) then active_del <= active_del(active_del'left-1 downto 0) & active; start_del <= start_del(start_del'left-1 downto 0) & start; done_del <= done_del(done_del'left-1 downto 0) & done; end if; end process; -- do math process(clk) begin if rising_edge(clk) then -- simple storage registers psreg <= presub; dreg <= smp1; b0reg <= smp2; a0reg <= coeff; a1reg <= a0reg; -- pre-adder if psreg='1' then b1reg <= resize(b0reg,19) - resize(dreg,19); else b1reg <= resize(b0reg,19) + resize(dreg,19); end if; -- multiplier mreg <= a1reg * b1reg(18 downto 1); -- post-adder / accumulator if active_del(2)='1' then if start_del(2)='1' then preg <= mreg + to_signed(RNDVAL,36); else preg <= mreg + preg; end if; end if; end if; end process; -- update output process(reset, clk) begin if reset='1' then dnew <= '0'; dout <= (others=>'0'); elsif rising_edge(clk) then if done_del(2)='1' then dnew <= '1'; if preg(35)='0' and preg(34 downto 33)/="00" then dout <= to_signed(2**17-1,18); elsif preg(35)='1' and preg(34 downto 33)/="11" then dout <= to_signed(-(2**17),18); else dout <= preg(33 downto 16); end if; else dnew <= '0'; end if; end if; end process; end rtl;