1

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;

enter image description here

Deepa
  • 113
  • 3
  • `((34 downto 28=>product(index1)(27)) ` what type of syntax is this? (geniunely curious) – Fra93 Jul 15 '22 at 06:23
  • This is done for sign extending the product to 35 bits.It works correctly. – Deepa Jul 15 '22 at 06:31
  • 1
    None of your signals are going to "Dont care" (which is `'-'`) It appears many are `'U'`, uninitialised. Wave editors usually aggregate meta values as 'X' (which would be "unknown"). Re-check the design to make sure all signals have a value. – Tricky Jul 15 '22 at 06:43

1 Answers1

0

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 Xvalue 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 Xs. 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.

Fra93
  • 1,992
  • 1
  • 9
  • 18
  • Did you try to wait some cycles and buffer/realing the multiplier result such that you don't pick an X value when assigning to the adder? Do you even care about such Xs? FIR have a inherent latency. – Fra93 Jul 15 '22 at 08:05
  • I am new to vhdl. So I have a doubt. Here you arre telling that we have to wait till the product is no longer 'X'. Is it done using wait statements. Are these wait statements synthesizable – Deepa Jul 15 '22 at 08:43
  • Nono, `wait` statements are only for testbenches, you can't synthesize them. What I mean is that you could implement an hardware delay. For instance you can let your multiplier output a valid signal when the result is no longer "X" and then add in your second process `if mult_valid = 1` etc.. – Fra93 Jul 15 '22 at 08:45
  • The important part here is that you understand what is "wrong" with your implementation. – Fra93 Jul 15 '22 at 08:46
  • I added a hardware delay as said by you i.e multiplier output a valid signal when the result was no longer "X" and then added it in the second process and got the correct output – Deepa Jul 15 '22 at 11:26