Welcome to 16892 Developer Community-Open, Learning,Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

What this is

I'm trying to create a simple FIR filter. What I'm going to present you may not exactly be a FIR filter as I'm gradually increasing complexity of my project for educational purpouses till it reaches desired functionality.

What it should be doing

Basically what it should be doing so far:

  • load data to registers after applying load = 1,
  • unload processed data (which is product of multiplication of samples with corresponding coefficients) after applying start = 1.

Where it fails

However from what I've noticed it fails to load data into registers. Seems to be working like a latch, as after load drops to 0, the last vector value at input port is being latched in the registers. But I may be wrong, it just appears to be working like this in simulation. Pre- and post-synthesis functional simulation is working! Only the post-synthesis timing is failing to work as desired!

What I've tried

  • Adding DONT_TOUCH parameter to entity declaration in its .vhd file,
  • Adding kind of buffer (unsigned variable) after data_in port from which the data is being transfered to registers - but it did not even appear in schematic after synthesis, maybe the DONT_TOUCH did not work?

Simulations pictures

Pre-synth functional - https://imgur.com/0TaNQyn

Post-synth timing - https://imgur.com/mEOv67t

Program

I'm using Vivado 2020.2 webpack

Testbench

Testbench code here: https://pastebin.pl/view/d2f9a4ad

Main code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity fir is
 Port ( 
 clk: in std_logic;
 data_in: in unsigned(7 downto 0);
 data_out: out unsigned(7 downto 0);
 en: in std_logic;
 load: in std_logic;
 start: in std_logic;
 reset: in std_logic
 );
end fir;

architecture Behavioral of fir is

-- type coeff_array is array (0 to 7) of integer range 0 to 255;
constant reg_size: integer := 8;
constant filter_order: integer := 7;

type samples_reg is array (0 to reg_size-1) of unsigned(7 downto 0);
type coeffs_reg is array (0 to filter_order) of unsigned(7 downto 0);


begin

process(clk, reset)
     
    -- variable coeffs: coeff_array := (0,0,0,0,0,0,0,0);
    --variable b0: unsigned(7 downto 0) := 8D"0";
    variable b0: unsigned(7 downto 0) := to_unsigned(1,8);
    variable b1: unsigned(7 downto 0) := to_unsigned(2,8);
    variable b2: unsigned(7 downto 0) := to_unsigned(3,8);
    variable b3: unsigned(7 downto 0) := to_unsigned(4,8);
    variable b4: unsigned(7 downto 0) := to_unsigned(5,8);
    variable b5: unsigned(7 downto 0) := to_unsigned(6,8);
    variable b6: unsigned(7 downto 0) := to_unsigned(7,8);
    variable b7: unsigned(7 downto 0) := to_unsigned(8,8);
    
    variable i: integer range 0 to reg_size := 0;
    
    variable samples: samples_reg := (others => (others => '0'));
    variable coeffs: coeffs_reg := (b0,b1,b2,b3,b4,b5,b6,b7);
    
    variable data_processed: unsigned(15 downto 0) := (others => '0');
    
       
    
    
    -- variable reg_element:
    
    -- signal s1 : signed(47 downto 0) := 48D"46137344123";
    
    begin    
    
    if reset = '1' then
        -- data_out <= (others => '0');
        samples := (others => (others => '0'));
        data_processed := (others => '0');
        i := 0;            

    -- synch part
    elsif rising_edge(clk) and en = '1' then
    
    samples := samples;
        
        -- loading data
        if load = '1' then
            samples(i) := data_in;
            
            i := i+1;
        else null;
        end if;                      
        
        -- deloading data
        if start = '1' then
            
        data_processed := samples(i)*coeffs(i);
        i := i+1;
        else null; 
        end if;
            
        -- reset counter after overflow
        if(i = reg_size) then
            i := 0;
        else null;
        end if;
        
        -- reset counter if no data is being transferred
        if load = '0' and start = '0' then
            i := 0;
            data_processed := (others => '0');
        else null;
        end if;    
                    
    end if;
    
    data_out <= data_processed(7 downto 0);
    
 end process;


end Behavioral;

Other info

  • I just noticed that I'm holding load = 1 for one excessive cycle, which is why the highest number appears first.
  • The coefficients are: 1, 2, 3, 4, 5, 6, 7, 8.
  • In post-synth simulations after peeking into UUT, I've noticed that the samples registers are not loading the data (except for the last one, as I've mentioned earlier), the i is incrementing and the rest appears to be working properly.
  • I'll be happy to hear about some improvements for my code in addition to the problem solution!

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
3.2k views
Welcome To Ask or Share your Answers For Others

1 Answer

Turns out in timing simulation I had to give the device at least 100 ns of warm-up time.

Seems like the timing simulations takes some factors related to device start-up into consideration -- anyway, I'm not sure about the explanation but I am sure of the above solution.

I have rephrased the title so others can find this post by searching for core problem in this case.

Good luck :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to 16892 Developer Community-Open, Learning and Share
...