synthesizeable_vhdl-model-library:patras:fir

FIR

The FIR consists of the following generic components:

The FIR component can be verified with this testbench:

This component implements an FIR (Finite Impulse Response) Filter. An FIR filter of N_taps coefficients is defined by the following equation:

FIR Equation

Each filter's sample, xn-1, has a word length of Wx-bits, while each filter's coefficient, Ci, has a word length of Wc-bits. The f(x) FIR's output has a word length of Wx-bits.

fir_lib.vhd
-- ############################################################################
-- # Project    :    Leonardo CBT-Kernel                                      #
-- #                                                                          #
-- # Filename   :    fir.vhd                                                  #
-- #                                                                          #
-- # Component  :    fir : N_taps-Wx x Wc Bits FIR (unrolled)                 #
-- #                                                                          #
-- # Model      :    behav                                                    #
-- #                                                                          #
-- # Designer   :    S. Theoharis                                             #
-- # Institute  :    VLSI Design Lab., University of Patras                   #
-- # Date       :    01.05.1999                                               #
-- ############################################################################
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
 
PACKAGE  fir_lib IS
 
-- Constant & SubType declarations.
CONSTANT Wx            : integer :=9;        -- Word length for FIR's X sample.
CONSTANT Wc            : integer :=10;       -- Word length for FIR's coefficient.
CONSTANT N_taps        : integer :=4;        -- Number of FIR taps. i.e. 4,6,8
 
-- Shifter type for FIR component.
TYPE fir_shifter_type IS ARRAY(N_taps-1 downto 0) OF std_ulogic_vector(Wx-1 downto 0);
 -- Coefficient type for FIR component.
TYPE fir_coefficient_type IS ARRAY(N_taps-1 downto 0) OF std_ulogic_vector(Wc-1 downto 0);
 
-- Definition of coefficient matrix.
CONSTANT C_matrix : fir_coefficient_type := (
-- "1010100100",
-- "0101110000",
-- "0101010000",
-- "1010110100",
"0010110001",
"1100100000",
"0010101000",
"1001100101"
);
 
-- Function declaration.
 
FUNCTION log2 (N : integer) RETURN integer;
FUNCTION mult_shift_add (X : IN std_ulogic_vector; C : IN std_ulogic_vector; N_taps : integer) RETURN std_ulogic_vector;
END fir_lib;
-------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
 
PACKAGE BODY fir_lib IS 
---------------------------------------------
FUNCTION log2 (N : integer) RETURN integer IS
VARIABLE temp : INTEGER;
BEGIN
IF N < 2 THEN
	RETURN 0;
ELSE
	temp := 2;
	FOR i IN 1 TO (N/2) LOOP
            temp := 2 * temp;
            IF (temp = N) THEN 
               	RETURN (i+1);
            ELSIF (temp > N) THEN
               	RETURN  i;
            END IF;
	END LOOP;  
END IF;
END;
 
---------------------------------------------
FUNCTION mult_shift_add (X : IN std_ulogic_vector; C : IN std_ulogic_vector; N_taps : integer) RETURN std_ulogic_vector IS
VARIABLE W : integer := X'length+C'length+log2(N_taps);
VARIABLE result : std_ulogic_vector(W-1 downto 0);
VARIABLE X_int,C_int,X_int_neg,t : integer;
VARIABLE X_neg : std_ulogic_vector(X'length-1 downto 0);
VARIABLE C_neg : std_ulogic_vector(C'length-1 downto 0);
VARIABLE sign : std_ulogic;
BEGIN
 
-- Convert X operand. X_int_neg is the correct integer value of X.
X_int := conv_integer(X);
IF (X(X'length-1)='1') THEN
	X_neg := to_stdulogicvector(-X_int,X'length);
ELSE
	X_neg := to_stdulogicvector(X_int,X'length);
END IF;
X_int_neg := conv_integer(X_neg);
 
-- Convert C operand. C_neg is the correct std_ulogic_vector of C.
C_int := conv_integer(C);
IF (C(C'length-1)='1') THEN
	C_neg := to_stdulogicvector(-C_int,C'length);
ELSE
	C_neg := to_stdulogicvector(C_int,C'length);
END IF;
 
-- What is the result's sign ?
sign:= X(X'length-1) xor C(C'length-1);
 
t:=0;
FOR i IN 0 TO C_neg'length-1 LOOP
IF (C_neg(i)='1') THEN
	t:=t+X_int_neg*(2**i);
END IF;
END LOOP;
 
IF (sign='0') THEN
	result := to_stdulogicvector(t,W);
ELSE
	result := to_stdulogicvector(-t,W);
END IF;
 
RETURN(result);
END;
 
END fir_lib;
fir.vhd
-- ############################################################################
-- # Project    :    Leonardo CBT-Kernel                                      #
-- #                                                                          #
-- # Filename   :    fir.vhd                                                  #
-- #                                                                          #
-- # Component  :    fir : N_taps-Wx x Wc Bits FIR (unrolled)                 #
-- #                                                                          #
-- # Model      :    behav                                                    #
-- #                                                                          #
-- # Designer   :    S. Theoharis                                             #
-- # Institute  :    VLSI Design Lab., University of Patras                   #
-- # Date       :    01.05.1999                                               #
-- ############################################################################
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
USE work.fir_lib.ALL;
 
ENTITY fir IS
GENERIC (
	   N_taps : integer := 4;  -- # FIR's taps.
	   Wx     : integer := 4;  -- # bits/X sample.
	   Wc     : integer := 4   -- # bits/X sample.
         ); 
PORT  (
       X        : IN  std_ulogic_vector(Wx-1 downto 0);
       C        : IN  fir_coefficient_type;
	 CLK      : IN  std_ulogic;
	 RESETB   : IN  std_ulogic;
	 Y        : OUT std_ulogic_vector(Wx-1 downto 0)
	);
END fir;
 
ARCHITECTURE behav OF fir IS
--------------------------------------------------------------
COMPONENT in_shifter_fir
GENERIC (
   	   N_taps : integer := 4;  -- # shifter's words.
	   Wx     : integer := 6   -- # bits/sample.
         ); 
PORT  (
       SI             : IN  std_ulogic_vector(Wx-1 downto 0);
	 CLK_SHIFT      : IN  std_ulogic;
	 RESETB         : IN  std_ulogic;
	 SO             : OUT fir_shifter_type
	);
END COMPONENT;
 
SIGNAL result : std_ulogic_vector(Wx+Wc+log2(N_taps)-1 downto 0);
SIGNAL X_shifter : fir_shifter_type;
 
BEGIN
--------------------------------------------------------------
X_shifter_component : in_shifter_fir
GENERIC MAP (
	       N_taps=>N_taps,
	       Wx=>Wx
            ) 
PORT MAP (
          SI=>X,
	    CLK_SHIFT=>CLK,
	    RESETB=>RESETB,
	    SO=>X_shifter
	   );
--------------------------------------------------------------
PROCESS (X_shifter,C)
VARIABLE t : integer;
BEGIN
t:=0;
FOR i IN 0 TO N_taps-1 LOOP
	t:= t + conv_integer(mult_shift_add(X_shifter(i),C(i),N_taps));
END LOOP;
result<=to_stdulogicvector(t,Wx+Wc+log2(N_taps));
END PROCESS;
--------------------------------------------------------------
PROCESS (RESETB,CLK)
BEGIN
IF (RESETB='0') THEN
	Y <= (OTHERS=>'0');
ELSIF (rising_edge(CLK)) THEN
	Y <= result(Wx-1 downto 0);
END IF;
END PROCESS;
--------------------------------------------------------------
END behav;
in_shifter_fir.vhd
-- ############################################################################
-- # Project    :    Leonardo CBT-Kernel                                      #
-- #                                                                          #
-- # Filename   :    in_shifter_fir.vhd                                       #
-- #                                                                          #
-- # Component  :    in_shifter_fir : N_taps-Wx Bit shifter                   #
-- #                                                                          #
-- # Model      :    behav                                                    #
-- #                                                                          #
-- # Designer   :    S. Theoharis                                             #
-- # Institute  :    VLSI Design Lab., University of Patras                   #
-- # Date       :    01.05.1999                                               #
-- ############################################################################
 
library IEEE;
use IEEE.std_logic_1164.all;
USE work.fir_lib.ALL;
 
ENTITY in_shifter_fir IS
GENERIC (
	N_taps : integer := 4;  -- # shifter's words.
	Wx     : integer := 6   -- # bits/sample.
         ); 
PORT  (
       SI             : IN  std_ulogic_vector(Wx-1 downto 0);
	 CLK_SHIFT      : IN  std_ulogic;
	 RESETB         : IN  std_ulogic;
	 SO             : OUT fir_shifter_type
	);
END in_shifter_fir;
 
ARCHITECTURE behav OF in_shifter_fir IS
SIGNAL shifter : fir_shifter_type;
BEGIN
 
-- Shifter process : shifts out N samples of W bits.
Shifter_process : PROCESS(CLK_SHIFT,RESETB)
BEGIN
IF (RESETB='0') THEN
	FOR i IN N_taps-1 downto 0 LOOP
		shifter(i) <= (OTHERS=>'0');
	END LOOP;
ELSIF (rising_edge(CLK_SHIFT)) THEN
	shifter(N_taps-1 downto 0) <= shifter(N_taps-2 downto 0) & SI;
END IF;
END PROCESS Shifter_process;
 
SO <= shifter;
 
END behav;
test_fir.vhd
-- ############################################################################
-- # Project    :    Leonardo CBT-Kernel                                      #
-- #                                                                          #
-- # Filename   :    test_fir.vhd                                             #
-- #                                                                          #
-- # Component  :    test_fir : Test bench for an FIR of N_taps-Wx x Wc Bits. #
-- #                                                                          #
-- # Model      :    behav                                                    #
-- #                                                                          #
-- # Designer   :    S. Theoharis                                             #
-- # Institute  :    VLSI Design Lab., University of Patras                   #
-- # Date       :    01.05.1999                                               #
-- ############################################################################
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
USE std.TEXTIO.ALL;
USE work.fir_lib.ALL;
 
ENTITY test_fir IS
END test_fir;
 
ARCHITECTURE behav OF test_fir IS
--------------------------------------------------------------
COMPONENT fir
GENERIC (
   	   N_taps : integer := 4;  -- # shifter's words.
	   Wx     : integer := 6   -- # bits/sample.
         ); 
PORT  (
       X              : IN  std_ulogic_vector(Wx-1 downto 0);
       C              : IN  fir_coefficient_type;
       CLK            : IN  std_ulogic;
       RESETB         : IN  std_ulogic;
       Y              : OUT std_ulogic_vector(Wx-1 downto 0)
     );
END COMPONENT;
--------------------------------------------------------------
TYPE sample_values IS FILE OF CHARACTER;
FILE file_in  : sample_values IS IN  "./lena256.raw";
FILE file_out : sample_values IS OUT "./lena256_fir.raw";
-- FILE file_in  : sample_values IS "./lena256.raw";
-- FILE file_out : sample_values IS "./lena256_fir.raw";
 
SIGNAL CLK,RESETB : std_ulogic := '0';
SIGNAL X,Y : std_ulogic_vector(Wx-1 downto 0);
 
SIGNAL FIR_Coefficients : fir_coefficient_type;
CONSTANT BINARY_VALUES : boolean := FALSE;
 
SIGNAL X_int,Y_int : integer RANGE 0 TO 2**Wx-1;
BEGIN
--------------------------------------------------------------
X_int <= conv_integer('0' & X);
Y_int <= conv_integer('0' & Y);
 
FIR_coefficients <= C_matrix;
RESETB <= '0', '1' AFTER 20 ns;
CLK <= '1' xor CLK AFTER 50 ns;
 
--------------------------
-- X sample generation. --
--------------------------
PROCESS(RESETB,CLK)
VARIABLE char : CHARACTER;
VARIABLE tmp_X : integer; 
BEGIN
-- (1) Create binary counter values ... 
IF (BINARY_VALUES) THEN
	IF (RESETB='0') THEN
		X <= (OTHERS=>'0');
	ELSIF (rising_edge(CLK)) THEN
		tmp_X := conv_integer('0' & X);
		IF (tmp_X=2**Wx-1) THEN
			tmp_X := 0; 
		ELSE
			tmp_X := tmp_X + 1;
		END IF;
		X <= to_stdulogicvector(tmp_X,Wx);
	END IF;
ELSE
-- (2) Read values from file ...
IF (RESETB='0') THEN
	X <= (OTHERS=>'0');
ELSIF (rising_edge(CLK)) THEN
	IF (NOT ENDFILE(file_in)) THEN
		READ(file_in,char);
    		X <= to_stdulogicvector(CHARACTER'pos(char),Wx);
	END IF;
	ASSERT (NOT ENDFILE(file_in))
    		REPORT "End of file ./do/lena256.raw"
  	SEVERITY FAILURE;
	END IF;
END IF;	
END PROCESS;
--------------------------------------------------------------
FIR_inst : fir
GENERIC MAP (
   	     N_taps=>N_taps,
	     Wx=>Wx
            ) 
PORT MAP (
          X=>X,
          C=>FIR_coefficients,
          CLK=>CLK,
          RESETB=>RESETB,
          Y=>Y
        );
--------------------------------------------------------------
END behav;