I am trying to implement a transposed form FIR filter of order 4.I am attaching the code and the waveform alongwith.In the first clock cycle, I have given a reset signal which will initialize the adder_output to 0.Input data is loaded in the second clock cycle.Input is written in a register.So the input is loaded at third clock cycle and the multiplication result of the input and filter coefficient is obtained in the third clock cycle.But at the same clock cycle, the adder output becomes dont care.Hence I am not getting the output for the first 3 clock cycles and after that the output is correct.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.numeric_std.all;
entity bpf is
port
(
rst :in std_logic;
clk : in std_logic;
bpf_enable : in std_logic;
bpf_input : in std_logic_vector(14 downto 0);
bpf_output : out std_logic_vector(14 downto 0);
bpf_ready : out std_logic
);
end bpf;
architecture bpf_behav OF bpf is
component multiplier is
port(
in1 :in std_logic_vector(14 downto 0);
in2 :in std_logic_vector(12 downto 0);
product:out std_logic_vector(27 downto 0)
);
end component;
type coeff_array is array(0 to 3) of std_logic_vector(12 downto 0);
type product_array is array(0 to 3) of std_logic_vector(27 downto 0);
type adder_array is array(0 to 3) of std_logic_vector(34 downto 0);
signal input_data :std_logic_vector(14 downto 0);
signal output_data:std_logic_vector(14 downto 0);
signal coefficient : coeff_array; -- Coefficient array
signal product :product_array;
signal adder_out: adder_array; -- Adder array
signal multiplier_en:std_logic;
begin
coefficient(0)<=std_logic_vector(to_signed(250,13));
coefficient(1)<=std_logic_vector(to_signed(608,13));
coefficient(2)<=std_logic_vector(to_signed(1530,13));
coefficient(3)<=std_logic_vector(to_signed(2603,13));
data_load:process(clk)
begin
if(rising_edge(clk)) then
if(bpf_enable='1') then
input_data<= bpf_input;
end if;
end if;
end process data_load;
mulgen :for index1 in 0 to 3 generate
u_multiplier:multiplier port map
(
in1=>input_data,
in2=>coefficient(index1),
product=>product(index1)
);
end generate;
adder:process(clk)
begin
if(rst='1') then
adder_out<=(others=>(others=>'0'));
elsif(rising_edge(clk)) then
for index1 in 0 to 2 loop
adder_out(index1)<=((34 downto 28=>product(index1)(27)) & product(index1))+adder_out(index1+1);
end loop;
adder_out(3)<=(34 downto 28=>product(3)(27)) & product(3);
end if;
end process adder;
bpf_output<=adder_out(0)(29 downto 15);
end bpf_behav;
entity multiplier is
port
(
in1: in std_logic_vector(14 downto 0);
in2:in std_logic_vector(12 downto 0);
product:out std_logic_vector(27 downto 0)
);
end multiplier;
architecture multiplier_behav of multiplier is
begin
product<=in1*in2;
end multiplier_behav;
The adder is at 0 initially because you reset it correctly. After that the reset is not active anymore so the value assigned to the accumulator is defined by this piece of code:
elsif(rising_edge(clk)) then
for index1 in 0 to 2 loop
adder_out(index1)<=((34 downto 28=>product(index1)(27)) & product(index1))+adder_out(index1+1);
end loop;
adder_out(3)<=(34 downto 28=>product(3)(27)) & product(3);
end if;
When you get an X
value it means that one or more of the signals used to generate the value is an X
, hence we need to analyze such values.
Looking at the product
waveforms we can see that before the reset it is all X
s. As soon as we exit the reset the assignment is then:
adder_out(0)<=((34 downto 28=>product(0)(27)) & product(0))+adder_out(1);
adder_out(1)<=((34 downto 28=>product(1)(27)) & product(1))+adder_out(2);
adder_out(2)<=((34 downto 28=>product(2)(27)) & product(2))+adder_out(3);
adder_out(3)<= (34 downto 28=>product(3)(27)) & product(3);
adder_out(0)<= XXXXX & XXX + 0
adder_out(1)<= XXXXX & XXX + 0
adder_out(2)<= XXXXX & XXX + 0
adder_out(3)<= XXXXX & XXX
The next clock cycle the product
becomes defined, but now the X
are in the adder itself, and they disappear one cycle at a time (starting from the last element because it does not use any adder in its assignment), until no Xs are there anymore (I use DDD
to indicate data).
cc n+1
adder_out(0)<= DDDDD & DDD + XXX
adder_out(1)<= DDDDD & DDD + XXX
adder_out(2)<= DDDDD & DDD + XXX
adder_out(3)<= DDDDD & DDD
cc n+2
adder_out(0)<= DDDDD & DDD + DDD
adder_out(1)<= DDDDD & DDD + XXX
adder_out(2)<= DDDDD & DDD + XXX
adder_out(3)<= DDDDD & DDD
cc n+2
adder_out(0)<= DDDDD & DDD + DDD
adder_out(1)<= DDDDD & DDD + DDD
adder_out(2)<= DDDDD & DDD + XXX
adder_out(3)<= DDDDD & DDD
cc n+3
adder_out(0)<= DDDDD & DDD + DDD
adder_out(1)<= DDDDD & DDD + DDD
adder_out(2)<= DDDDD & DDD + DDD
adder_out(3)<= DDDDD & DDD
How to fix this? product
should be a defined value when is read by the accumulator. This can't be enforced before reset, so I think you should wait some cycles before reading it in your adder logic, or implement a valid signal to tell that the first result from the multiplier is ready.