mikrocontroller.net

Forum: FPGA, VHDL & Co. FIR mit variabler Anzahl von Koeffizienten


Autor: Kirill Yasinovskiy (schkrent)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
ich brauche eure Hilfe, bin ein VHDL-Anfaenger :)
Hab ne Aufgabe bekommen einen FIR mit variabler Anzahl von Koeffizienten 
in VHDL zu realiseiren.
Irgendwie scheint mein Code nicht richtig zu sein, oder mein Testbench 
ist einfach falsch geschrieben...

FIR:
library ieee;

use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
--use ieee.std_logic_unsigned.all;

package FILTER_PACK is 
  constant K:      integer := 6; -- Anzahl Filterkoeffizienten
  constant EIN_SIZE:  integer := 9; -- Bitbreite Eingang
  constant AUS_SIZE:  integer := 11; -- Biltbreite Ausgang
  constant MULT_SIZE: integer := 18; -- Multiplizierer Bitbreite 2*EIN_SIZE
  constant ADD_SIZE:  integer := 19; -- Addierer Bitbreite MULT_SIZE + ld(K)-1
  constant PIPE:    integer := 5;  -- Anzahl von Stufen im Multiplizierer-Pipeline
  constant FACTOR:  integer := 8; -- Ergebnis geteilt durch 2^FACTOR
end FILTER_PACK;

library ieee;

use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
--use ieee.std_logic_unsigned.all;

library work;
use work.FILTER_PACK.all;

entity FILTER is
  port (clk:    in std_logic;
      load_x:  in std_logic;
      data_in:  in std_logic_vector(EIN_SIZE - 1 downto 0);
      koeff_in:  in std_logic_vector(EIN_SIZE - 1 downto 0);
      data_out: out std_logic_vector(AUS_SIZE - 1 downto 0));
end FILTER;      

architecture arch of filter is
  subtype EIN_BIT  is std_logic_vector(EIN_SIZE - 1 downto 0);
  subtype MULT_BIT is std_logic_vector(MULT_SIZE - 1 downto 0);
  subtype ADD_BIT  is std_logic_vector(ADD_SIZE - 1 downto 0);
  type   ARRAY_EIN_BIT  is array (0 to K - 1) of EIN_BIT;
  type   ARRAY_MULT_BIT is array (0 to K - 1) of MULT_BIT;
  type   ARRAY_ADD_BIT  is array (0 to K - 1) of ADD_BIT;
  
  signal ein:   EIN_BIT;
  signal aus:    ADD_BIT;
  signal koeff:  ARRAY_EIN_BIT;  -- Koeffizient array
  signal prod:  ARRAY_MULT_BIT; -- Produkt array
  signal sum:    ARRAY_ADD_BIT;  -- Addierer array

component pipelined_multiplier is
  generic (
    size:   integer; 
    level: integer);

  port (
    a : in std_logic_vector (size-1 downto 0) ;
    b : in std_logic_vector (size-1 downto 0) ;
    clk : in std_logic;
    res : out std_logic_vector (2*size-1 downto 0));

end component pipelined_multiplier ;

  
  begin
  
  LOAD: process -- Data oder Koeffizienten werden geladen 
  
  begin
    wait until clk = '1';
    if (load_x = '1') then
      koeff(K - 1) <= koeff_in; -- Koeffizient in den Register speichern
      for i in K-2 downto 0 loop
        koeff(i) <= koeff(i + 1);
        end loop;
      else 
        ein <= data_in; -- sonst Data laden
    end if;
  end process LOAD;   
  
  SUMM: process (clk)  -- in diesem Pozess wird die Summe gebildet
    begin
    if clk'event and (clk = '1') then
    for i in 0 to k - 2 loop
      sum(i) <= (prod(i)(MULT_SIZE - 1) & prod(i)) + sum(i + 1);
      --sum(i) <= "0" & prod(i) + sum(i + 1);
    end loop;
      sum(k - 1) <= prod(k - 1)(MULT_SIZE - 1) & prod(k - 1);
      --sum(k - 1) <= "0" & prod(k - 1);
    end if;
    aus <= sum(0);
  end process SUMM;    
  
  MUL_GEN: for i in 0 to k - 1 generate
  mul: pipelined_multiplier
    generic map (size => EIN_SIZE,
           level => PIPE)       
    port map (a => ein,
          b => koeff(i),
          clk => clk,
          res => prod(i));
    end generate;
    
  data_out <= aus(ADD_SIZE - 1 downto FACTOR);
  
  end arch;
Pipelined-miltiplizierer:

library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;

entity pipelined_multiplier is
  generic (
    size:   integer; 
    level: integer);

  port (
    a : in std_logic_vector (size-1 downto 0) ;
    b : in std_logic_vector (size-1 downto 0) ;
    clk : in std_logic;
    res : out std_logic_vector (2*size-1 downto 0));
end pipelined_multiplier ;

architecture arch of pipelined_multiplier is
  type levels_of_registers is array(level-1 downto 0) of signed(2*size-1 downto 0);
  signal a_int : signed (size-1 downto 0);
  signal b_int : signed (size-1 downto 0);
  signal res_int: levels_of_registers;

  begin
  res <= std_logic_vector(res_int (level-1));

  process(clk)
  begin
  if clk'event and clk = '1' then
  -- multiplier operand inputs are registered
  a_int <= signed (a);
  b_int <= signed (b);
  -- 'level' levels of registers to be inferred at the
  -- output of the multiplier
  res_int(0) <= a_int*b_int;
    for i in 1 to level-1 loop
      res_int (i) <= res_int (i-1);
    end loop;
  end if;
end process;
end arch;

Und Testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_signed.all;
USE ieee.numeric_std.ALL;
 
ENTITY filter_tb IS
END filter_tb;
 
ARCHITECTURE testbench OF filter_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT filter
    PORT(
         clk : IN  std_logic;
         load_x : IN  std_logic;
         data_in : IN  std_logic_vector(8 downto 0);
         koeff_in : IN  std_logic_vector(8 downto 0);
         data_out : OUT  std_logic_vector(10 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';
   signal load_x : std_logic := '0';
   signal data_in : std_logic_vector(8 downto 0) := (others => '0');
   signal koeff_in : std_logic_vector(8 downto 0) := (others => '0');

   --Outputs
   signal data_out : std_logic_vector(10 downto 0);

   -- Clock period definitions
   constant clk_period : time := 50 ns; -- 20 MHz
 
BEGIN
 
  -- Instantiate the Unit Under Test (UUT)
   uut: filter PORT MAP (
          clk => clk,
          load_x => load_x,
          data_in => data_in,
          koeff_in => koeff_in,
          data_out => data_out
        );

   -- 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    
    load_x <= '0';
    data_in <= "000000000";
    koeff_in <= "001111100"; -- Koeff 1 - 124
    wait for clk_period;
    koeff_in <= "000110010"; -- Koeff 2 - 50
    --koeff_in <= "000000000";
    wait for clk_period;
    koeff_in <= "001000011"; -- Koeff 3 - 67
    --koeff_in <= "000000000";
    wait for clk_period;
    koeff_in <= "001010011"; -- Koeff 4 - 83
    --koeff_in <= "000000000";
    wait for clk_period;
    koeff_in <= "011010110"; -- Koeff 5 - 214
    --koeff_in <= "000000000";
    wait for clk_period;
    koeff_in <= "010110000"; -- Koeff 6 - 176
    --koeff_in <= "000000000";
    wait for clk_period;
    koeff_in <= "000000000";
    wait for 2*clk_period;
    load_x <= '1';
    wait for clk_period;
    data_in <= "001100100";
    --wait for 2*clk_period;
    --data_in <= "000000000";
    
      -- hold reset state for 100ms.
      --wait for 100ms;  

     -- wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;


Es laesst sich alles komplilieren, entsteht auch Hardware... Ich kriege 
aber kein richtiges Ergebnisbei der Simulation.

Autor: Frager (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Es laesst sich alles komplilieren, entsteht auch Hardware...
Das würde mich bei dem Konstrukt "wait until clk = '1';" aber wundern.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  begin
    wait until clk = '1';
    if (load_x = '1') then
Das ist ein Takt auf die steigende Flanke.
Xilinx kann das ;-)

Meine bevorzugte Schreibweise ist allerdings
  begin
    wait until rising_edge(clk);
    if (load_x = '1') then

Allerdings wundert mich, warum die Schreibweise des nächsten Prozesses 
wieder anders ist:
  SUMM: process (clk)  -- in diesem Pozess wird die Summe gebildet
    begin
    if clk'event and (clk = '1') then


@ Kirill Yasinovskiy
Eine Frage. Was willst du damit erreichen:
    for i in 0 to k - 2 loop
      sum(i) <= (prod(i)(MULT_SIZE - 1) & prod(i)) + sum(i + 1);
      --sum(i) <= "0" & prod(i) + sum(i + 1);
    end loop;
Dir ist der grundlegende Unterschied einer for-Schleife in VHDL und z.B. 
C (oder Basic...) bekannt?

Autor: Kirill Yasinovskiy (schkrent)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der Unterschied ist mir bekannt )))
for i in 0 to k - 2 loop
      sum(i) <= (prod(i)(MULT_SIZE - 1) & prod(i)) + sum(i + 1);
    end loop;
das führebde bit des multiplikationergebnises wird mit dem ergebnis 
konkateniert und rekursiv addiert (da es in sum ein bit mehr gibt), mehr 
passiert hier nicht.

Autor: Kirill Yasinovskiy (schkrent)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab gerade meinen Pipelined-Multiplizierer noch mal gestestet, alles 
läuft prima... Hab keine Ahnung, wo das Problem liegt.

Autor: Kirill Yasinovskiy (schkrent)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat sich erledigt. Mein Testebench war nicht korrekt )))
Danke für eure Hilfe!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.