High performance FIR

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was started in April 2018

I was interested to see how hard it was to infer a high-performance FIR filter, using a single DSP48A block and block RAM to hold the kernel and the samples.

Contents

Performance

The design can process at up to 280 million 18x18 MACs per second (one per clock cycle). Throughput depends on length of the filter - e.g. with 280 taps it can process 1M samples per second.

Peak performance is limited by the switching limit for the block RAM:

Component Switching Limit Checks: TS_clk = PERIOD TIMEGRP "clk" 3.57 ns HIGH 50%; 
 -------------------------------------------------------------------------------- 
 Slack: 0.000ns (period - min period limit) 
   Period: 3.570ns 
   Min period limit: 3.570ns (280.112MHz) (Trper_CLKA(Fmax)) 
   Physical resource: Mram_memory/CLKA 
   Logical resource: Mram_memory/CLKA 
   Location pin: RAMB16_X0Y14.CLKA 
   Clock network: clk_BUFGP 

And here is the final timing summary, for a grade 2 Spartan-6.

Timing summary: 
 --------------- 
  
 Timing errors: 0  Score: 0  (Setup/Max: 0, Hold: 0) 
  
 Constraints cover 590 paths, 0 nets, and 288 connections 
  
 Design statistics: 
    Minimum period:   3.570ns{1}   (Maximum frequency: 280.112MHz) 

Resource usage =

22 Slices
1 x DSP48A1
2 x  RAMB16BWERs
 

Source

inferred_dsp.vhd

With the DSP block in a separate module it is relatively simple to see if all of the registers and logic have been absorbed into the DSP block. It would also make it easier to implement something similar on a different architecture. "max_count" should be set to the number of tap constant in the filter. Unused taps can be set to any value without upsetting the filter output.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity inferred_dsp is
    Port ( clk        : in  STD_LOGIC;
           a          : in  STD_LOGIC_VECTOR (17 downto 0);
           b          : in  STD_LOGIC_VECTOR (17 downto 0);
           accumulate : in  STD_LOGIC;
           p          : out  STD_LOGIC_VECTOR (47 downto 0));
end inferred_dsp;

architecture Behavioral of inferred_dsp is
   signal   product1     : signed(35 downto 0);
   signal   accum        : signed(47 downto 0);
   signal   a1           : signed(17 downto 0);
   signal   a2           : signed(17 downto 0);
   signal   b1           : signed(17 downto 0);
   signal   b2           : signed(17 downto 0);
begin
   p <= std_logic_vector(accum);
   
dsp_proc : process(clk)
   begin
      if rising_edge(clk) then
         --------------------------------------------------
         -- This should all be absorbed into the DSP block
         --------------------------------------------------
         if accumulate = '0' then
            accum       <= to_signed(0,48)  + product1;
         else
            accum       <= accum            + product1;
         end if;
         product1 <= a2 * b2;
         a2 <= a1;
         b2 <= b1;
         a1 <= signed(a);
         b1 <= signed(b);
      end if;
   end process;

end Behavioral;

big_filter.vhd

This includes the filter kernel as constants.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity big_filter is
    Port ( clk         : in  STD_LOGIC;
           din         : in  STD_LOGIC_VECTOR (17 downto 0);
           din_enable  : in  STD_LOGIC;
           dout        : out  STD_LOGIC_VECTOR (47 downto 0);
           dout_enable : out STD_LOGIC);
end big_filter;

architecture Behavioral of big_filter is
    component inferred_dsp is
    Port ( clk        : in  STD_LOGIC;
           a          : in  STD_LOGIC_VECTOR (17 downto 0);
           b          : in  STD_LOGIC_VECTOR (17 downto 0);
           accumulate : in  STD_LOGIC;
           p          : out  STD_LOGIC_VECTOR (47 downto 0));
   end component;

   type a_kernel is array(0 to 1023) of std_logic_vector(17 downto 0);
   constant kernel : a_kernel := (
      "111111110111111110", "111111101000001011", "111111011001100110", "111111001101000111",
      "111111000011100001", "111110111101011101", "111110111011010110", "111110111101011001",
      "111111000011100001", "111111001101011100", "111111011010100111", "111111101010010010",
      "111111111011100100", "000000001101011001", "000000011110101111", "000000101110100001",
      "000000111011110000", "000001000101100101", "000001001011010110", "000001001100101000",
      "000001001001010000", "000001000001010111", "000000110101010100", "000000100101110011",
      "000000010011101011", "000000000000000000", "111111101011111100", "111111011000101100",
      "111111000111011101", "111110111001010100", "111110101111001100", "111110101001110011",
      "111110101001100011", "111110101110100101", "111110111000101100", "111111000111011000",
      "111111011001110101", "111111101111000010", "000000000101101111", "000000011100101000",
      "000000110010010010", "000001000101011000", "000001010100101011", "000001011111001010",
      "000001100100000101", "000001100011000000", "000001011011110110", "000001001110111001",
      "000000111100110010", "000000100110011111", "000000001101010000", "111111110010100100",
      "111111010111111110", "111110111111000111", "111110101001100011", "111110011000101011",
      "111110001101101010", "111110001001010101", "111110001100001010", "111110010110001010",
      "111110100110111101", "111110111101101110", "111111011001010000", "111111111000000001",
      "000000011000001111", "000000111000000001", "000001010101011010", "000001101110100010",
      "000010000001101110", "000010001101100110", "000010010001001100", "000010001011111110",
      "000001111101111110", "000001100111101100", "000001001010001100", "000000100110111111",
      "000000000000000000", "111111010111011110", "111110101111110001", "111110001011010111",
      "111101101100100110", "111101010101100110", "111101001000000110", "111101000101010110",
      "111101001110000000", "111101100010000101", "111110000000111011", "111110101001001010",
      "111111011000110110", "000000001101011101", "000001000100000110", "000001111001100010",
      "000010101010011110", "000011010011101101", "000011110010001111", "000100000011100111",
      "000100000101111001", "000011111000000000", "000011011001101001", "000010101011100000",
      "000001101111001100", "000000100111010010", "111111010111001010", "111110000010111010",
      "111100101111001110", "111011100001000111", "111010011101101110", "111001101010000011",
      "111001001010110001", "111001000011111001", "111001011000100110", "111010001011000101",
      "111011011100010100", "111101001100000010", "111111011000101010", "000001111111010001",
      "000100111011110011", "001000001001000100", "001011100000111110", "001110111100110001",
      "010010010101010011", "010101100011010110", "011000011111110011", "011011000100001000",
      "011101001010011110", "011110101110000100", "011111101011010010", "011111111111111101",
      "011111101011010010", "011110101110000100", "011101001010011110", "011011000100001000",
      "011000011111110011", "010101100011010110", "010010010101010011", "001110111100110001",
      "001011100000111110", "001000001001000100", "000100111011110011", "000001111111010001",
      "111111011000101010", "111101001100000010", "111011011100010100", "111010001011000101",
      "111001011000100110", "111001000011111001", "111001001010110001", "111001101010000011",
      "111010011101101110", "111011100001000111", "111100101111001110", "111110000010111010",
      "111111010111001010", "000000100111010010", "000001101111001100", "000010101011100000",
      "000011011001101001", "000011111000000000", "000100000101111001", "000100000011100111",
      "000011110010001111", "000011010011101101", "000010101010011110", "000001111001100010",
      "000001000100000110", "000000001101011101", "111111011000110110", "111110101001001010",
      "111110000000111011", "111101100010000101", "111101001110000000", "111101000101010110",
      "111101001000000110", "111101010101100110", "111101101100100110", "111110001011010111",
      "111110101111110001", "111111010111011110", "000000000000000000", "000000100110111111",
      "000001001010001100", "000001100111101100", "000001111101111110", "000010001011111110",
      "000010010001001100", "000010001101100110", "000010000001101110", "000001101110100010",
      "000001010101011010", "000000111000000001", "000000011000001111", "111111111000000001",
      "111111011001010000", "111110111101101110", "111110100110111101", "111110010110001010",
      "111110001100001010", "111110001001010101", "111110001101101010", "111110011000101011",
      "111110101001100011", "111110111111000111", "111111010111111110", "111111110010100100",
      "000000001101010000", "000000100110011111", "000000111100110010", "000001001110111001",
      "000001011011110110", "000001100011000000", "000001100100000101", "000001011111001010",
      "000001010100101011", "000001000101011000", "000000110010010010", "000000011100101000",
      "000000000101101111", "111111101111000010", "111111011001110101", "111111000111011000",
      "111110111000101100", "111110101110100101", "111110101001100011", "111110101001110011",
      "111110101111001100", "111110111001010100", "111111000111011101", "111111011000101100",
      "111111101011111100", "000000000000000000", "000000010011101011", "000000100101110011",
      "000000110101010100", "000001000001010111", "000001001001010000", "000001001100101000",
      "000001001011010110", "000001000101100101", "000000111011110000", "000000101110100001",
      "000000011110101111", "000000001101011001", "111111111011100100", "111111101010010010",
      "111111011010100111", "111111001101011100", "111111000011100001", "111110111101011001",
      "111110111011010110", "111110111101011101", "111111000011100001", "111111001101000111",
      "111111011001100110", "111111101000001011", "111111110111111110", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000",
      "000000000000000000", "000000000000000000", "000000000000000000", "000000000000000000"
   );   
   
   type a_memory is array(0 to 1023) of std_logic_vector(17 downto 0);
   signal   memory           : a_memory := (others => (others => '0'));
   
   constant max_count        : unsigned( 9 downto 0) := to_unsigned(255,10);
   signal   index            : unsigned( 9 downto 0) := to_unsigned(254,10);
   signal   wr_index         : unsigned( 9 downto 0) := to_unsigned(254,10);
   signal   count            : unsigned( 9 downto 0) := max_count;

   signal   accum            : std_logic_vector(47 downto 0);
   signal   a                : std_logic_vector(17 downto 0);
   signal   b                : std_logic_vector(17 downto 0);
   signal   accumulate_eject : std_logic_vector( 4 downto 0)  := (others => '0');
   signal   accumulate_reset : std_logic_vector( 4 downto 0)  := (others => '0');
   
begin

i_dsp: inferred_dsp port map (
   clk        => clk,
   a          => a,
   b          => b,
   accumulate => accumulate_reset(0),
   p          => accum
);

process(clk) 
   begin
      if rising_edge(clk) then
         -----------------------------------------------------
         -- Eject data_out when new data_in is being processed
         -----------------------------------------------------
         if accumulate_eject(0) = '1' then
            dout        <= std_logic_vector(accum);
            dout_enable <= '1';
         else
            dout_enable <= '0';
         end if;

         ----------------------------------------------------
         -- Control the timing of the zero of the accumulator
         ----------------------------------------------------
         if count = max_count-1 then
            accumulate_eject <= '1' & accumulate_eject(accumulate_eject'high downto 1);
         else 
            accumulate_eject <= '0' & accumulate_eject(accumulate_eject'high downto 1);
         end if;

         if din_enable = '1' then
            accumulate_reset <= '0' & accumulate_reset(accumulate_reset'high downto 1);
         else 
            accumulate_reset <= '1' & accumulate_reset(accumulate_reset'high downto 1);
         end if;

         ------------------------------
         -- Loading data into the DSP 
         ------------------------------
         a <= std_logic_vector(kernel(to_integer(count)));
         b <= std_logic_vector(memory(to_integer(index)));

         ----------------------------------------------------
         -- New data arrives 
         ----------------------------------------------------
         if din_enable = '1' then
            -- Save to memory
            memory(to_integer(wr_index)) <= din;
            -- Restart the FIR filter
            count                        <= (others => '0');
            wr_index                     <= wr_index+1;
            index <= index - max_count + 1;
         elsif count /= max_count then
            -- Stall the FIR filter
            count <=  count+1;
            index <=  index+1;         
         end if;
      end if;
   end process;

end Behavioral;

fir_filter.c

Here is a C program to generate a basic sinc() FIR filter, and output it in a format that is suitable for pasting into the VHDL module. You will want to add windowing of the filter if you want to generate a practical filter.

#include <stdio.h>
#include <math.h>

/* Frequency for the filter, relative to sample rage */
double f = 0.10;
int kernel_len = 255;
int scale = (1<<17)-3;
double kernel[1024];

void printval(int i, int len) {
   while(len > 0) {
     len--;
     putchar( (i&1<<len) ? '1' : '0');
   }
}

int main(int argc, char *argv[]) {
   int i;
   int ac_gain = 0;
   int dc_gain = 0;
   for( i = 0; i < kernel_len; i++)
   {
      double x = (2.0*3.141592)/f * (i-kernel_len/2) / kernel_len;
      double y = sin(x)/x * scale;
      kernel[i] = y;
   }
   kernel[kernel_len/2] = scale;

   for( i = 0; i < kernel_len; i++) {
     printf("%4i: %10.2f\n", i, kernel[i]);
     dc_gain += (int)kernel[i];
     if(kernel[i] > 0)
       ac_gain += (int)kernel[i];
     else
       ac_gain -= (int)kernel[i];
   }

   printf("-- Kernel len %i\n", kernel_len);
   printf("-- Scale      %i\n", scale);
   printf("-- Frequency  %6.3f\n",f);
   printf("-- DC Gain    %i\n", dc_gain);
   printf("-- Peak       %i\n", ac_gain);

   for(i = 0; i < 1023; i++) {
      if(i%4 == 0)
         printf("      ");
      putchar('"');
      printval((int)kernel[i],18);
      putchar('"');
      if(i %4 == 3)
        printf(",\n");
      else
        printf(", ");
   }
   putchar('"');
   printval(0,18);
   putchar('"');
   printf("\n");
}

Personal tools