Below is a 4 tap filter. That means the order of the filter is 4 and so it has 4 coefficients. the input is signed type of 8 bits wide. The output is also of signed type with 16 bits width. The design contains two files. One is the main file with all multiplications and adders defined in it, and another for defining the D flip flop operation.
The main file is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fir_4tap is
port( Clk : in std_logic; --clock signal
Xin : in signed(7 downto 0); --input signal
Yout : out signed(15 downto 0) --filter output
);
end fir_4tap;
architecture Behavioral of fir_4tap is
component DFF is
port(
Q : out signed(15 downto 0); --output connected to the adder
Clk :in std_logic; -- Clock input
D :in signed(15 downto 0) -- Data input from the MCM block.
);
end component;
signal H0,H1,H2,H3 : signed(7 downto 0) := (others => '0');
signal MCM0,MCM1,MCM2,MCM3,add_out1,add_out2,add_out3 : signed(15 downto 0) := (others => '0');
signal Q1,Q2,Q3 : signed(15 downto 0) := (others => '0');
begin
--filter coefficient initializations.
--H = [-2 -1 3 4].
H0 <= to_signed(-2,8);
H1 <= to_signed(-1,8);
H2 <= to_signed(3,8);
H3 <= to_signed(4,8);
--Multiple constant multiplications.
MCM3 <= H3*Xin;
MCM2 <= H2*Xin;
MCM1 <= H1*Xin;
MCM0 <= H0*Xin;
--adders
add_out1 <= Q1 + MCM2;
add_out2 <= Q2 + MCM1;
add_out3 <= Q3 + MCM0;
--flipflops(for introducing a delay).
dff1 : DFF port map(Q1,Clk,MCM3);
dff2 : DFF port map(Q2,Clk,add_out1);
dff3 : DFF port map(Q3,Clk,add_out2);
--an output produced at every positive edge of clock cycle.
process(Clk)
begin
if(rising_edge(Clk)) then
Yout <= add_out3;
end if;
end process;
end Behavioral;
VHDL code for the component DFF is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DFF is
port(
Q : out signed(15 downto 0); --output connected to the adder
Clk :in std_logic; -- Clock input
D :in signed(15 downto 0) -- Data input from the MCM block.
);
end DFF;
architecture Behavioral of DFF is
signal qt : signed(15 downto 0) := (others => '0');
begin
Q <= qt;
process(Clk)
begin
if ( rising_edge(Clk) ) then
qt <= D;
end if;
end process;
end Behavioral;
I have written a small test bench code for testing the design. It contains 8 test inputs which are serially applied to the filter module. See below:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
signal Clk : std_logic := '0';
signal Xin : signed(7 downto 0) := (others => '0');
signal Yout : signed(15 downto 0) := (others => '0');
constant Clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.fir_4tap PORT MAP (
Clk => Clk,
Xin => Xin,
Yout => Yout
);
-- Clock process definitions
Clk_process :process
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for Clk_period*2;
Xin <= to_signed(-3,8); wait for clk_period*1;
Xin <= to_signed(1,8); wait for clk_period*1;
Xin <= to_signed(0,8); wait for clk_period*1;
Xin <= to_signed(-2,8); wait for clk_period*1;
Xin <= to_signed(-1,8); wait for clk_period*1;
Xin <= to_signed(4,8); wait for clk_period*1;
Xin <= to_signed(-5,8); wait for clk_period*1;
Xin <= to_signed(6,8); wait for clk_period*1;
Xin <= to_signed(0,8);
wait;
end process;
END;
The main question is the simulation result is coming good and whether this code will work on fpga virtex 4 device.I am using xilinx software and this software has ip core generators but i am not using them because i want to get good coding practice.