summaryrefslogtreecommitdiffstats
path: root/fpga/hw-v2/src/mt_filter/mt_fil_mac_slow.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/hw-v2/src/mt_filter/mt_fil_mac_slow.vhd')
-rw-r--r--fpga/hw-v2/src/mt_filter/mt_fil_mac_slow.vhd146
1 files changed, 146 insertions, 0 deletions
diff --git a/fpga/hw-v2/src/mt_filter/mt_fil_mac_slow.vhd b/fpga/hw-v2/src/mt_filter/mt_fil_mac_slow.vhd
new file mode 100644
index 0000000..603b72a
--- /dev/null
+++ b/fpga/hw-v2/src/mt_filter/mt_fil_mac_slow.vhd
@@ -0,0 +1,146 @@
+---------------------------------------------------------------------------------------------------
+-- 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 <http://www.gnu.org/licenses/>. --
+-----------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+-- 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;