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


von Kirill Y. (schkrent)


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:
1
library ieee;
2
3
use ieee.std_logic_1164.all;
4
use ieee.std_logic_arith.all;
5
use ieee.std_logic_signed.all;
6
--use ieee.std_logic_unsigned.all;
7
8
package FILTER_PACK is 
9
  constant K:      integer := 6; -- Anzahl Filterkoeffizienten
10
  constant EIN_SIZE:  integer := 9; -- Bitbreite Eingang
11
  constant AUS_SIZE:  integer := 11; -- Biltbreite Ausgang
12
  constant MULT_SIZE: integer := 18; -- Multiplizierer Bitbreite 2*EIN_SIZE
13
  constant ADD_SIZE:  integer := 19; -- Addierer Bitbreite MULT_SIZE + ld(K)-1
14
  constant PIPE:    integer := 5;  -- Anzahl von Stufen im Multiplizierer-Pipeline
15
  constant FACTOR:  integer := 8; -- Ergebnis geteilt durch 2^FACTOR
16
end FILTER_PACK;
17
18
library ieee;
19
20
use ieee.std_logic_1164.all;
21
use ieee.std_logic_arith.all;
22
use ieee.std_logic_signed.all;
23
--use ieee.std_logic_unsigned.all;
24
25
library work;
26
use work.FILTER_PACK.all;
27
28
entity FILTER is
29
  port (clk:    in std_logic;
30
      load_x:  in std_logic;
31
      data_in:  in std_logic_vector(EIN_SIZE - 1 downto 0);
32
      koeff_in:  in std_logic_vector(EIN_SIZE - 1 downto 0);
33
      data_out: out std_logic_vector(AUS_SIZE - 1 downto 0));
34
end FILTER;      
35
36
architecture arch of filter is
37
  subtype EIN_BIT  is std_logic_vector(EIN_SIZE - 1 downto 0);
38
  subtype MULT_BIT is std_logic_vector(MULT_SIZE - 1 downto 0);
39
  subtype ADD_BIT  is std_logic_vector(ADD_SIZE - 1 downto 0);
40
  type   ARRAY_EIN_BIT  is array (0 to K - 1) of EIN_BIT;
41
  type   ARRAY_MULT_BIT is array (0 to K - 1) of MULT_BIT;
42
  type   ARRAY_ADD_BIT  is array (0 to K - 1) of ADD_BIT;
43
  
44
  signal ein:   EIN_BIT;
45
  signal aus:    ADD_BIT;
46
  signal koeff:  ARRAY_EIN_BIT;  -- Koeffizient array
47
  signal prod:  ARRAY_MULT_BIT; -- Produkt array
48
  signal sum:    ARRAY_ADD_BIT;  -- Addierer array
49
50
component pipelined_multiplier is
51
  generic (
52
    size:   integer; 
53
    level: integer);
54
55
  port (
56
    a : in std_logic_vector (size-1 downto 0) ;
57
    b : in std_logic_vector (size-1 downto 0) ;
58
    clk : in std_logic;
59
    res : out std_logic_vector (2*size-1 downto 0));
60
61
end component pipelined_multiplier ;
62
63
  
64
  begin
65
  
66
  LOAD: process -- Data oder Koeffizienten werden geladen 
67
  
68
  begin
69
    wait until clk = '1';
70
    if (load_x = '1') then
71
      koeff(K - 1) <= koeff_in; -- Koeffizient in den Register speichern
72
      for i in K-2 downto 0 loop
73
        koeff(i) <= koeff(i + 1);
74
        end loop;
75
      else 
76
        ein <= data_in; -- sonst Data laden
77
    end if;
78
  end process LOAD;   
79
  
80
  SUMM: process (clk)  -- in diesem Pozess wird die Summe gebildet
81
    begin
82
    if clk'event and (clk = '1') then
83
    for i in 0 to k - 2 loop
84
      sum(i) <= (prod(i)(MULT_SIZE - 1) & prod(i)) + sum(i + 1);
85
      --sum(i) <= "0" & prod(i) + sum(i + 1);
86
    end loop;
87
      sum(k - 1) <= prod(k - 1)(MULT_SIZE - 1) & prod(k - 1);
88
      --sum(k - 1) <= "0" & prod(k - 1);
89
    end if;
90
    aus <= sum(0);
91
  end process SUMM;    
92
  
93
  MUL_GEN: for i in 0 to k - 1 generate
94
  mul: pipelined_multiplier
95
    generic map (size => EIN_SIZE,
96
           level => PIPE)       
97
    port map (a => ein,
98
          b => koeff(i),
99
          clk => clk,
100
          res => prod(i));
101
    end generate;
102
    
103
  data_out <= aus(ADD_SIZE - 1 downto FACTOR);
104
  
105
  end arch;
Pipelined-miltiplizierer:
1
library ieee ;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_arith.all;
4
use ieee.std_logic_signed.all;
5
6
entity pipelined_multiplier is
7
  generic (
8
    size:   integer; 
9
    level: integer);
10
11
  port (
12
    a : in std_logic_vector (size-1 downto 0) ;
13
    b : in std_logic_vector (size-1 downto 0) ;
14
    clk : in std_logic;
15
    res : out std_logic_vector (2*size-1 downto 0));
16
end pipelined_multiplier ;
17
18
architecture arch of pipelined_multiplier is
19
  type levels_of_registers is array(level-1 downto 0) of signed(2*size-1 downto 0);
20
  signal a_int : signed (size-1 downto 0);
21
  signal b_int : signed (size-1 downto 0);
22
  signal res_int: levels_of_registers;
23
24
  begin
25
  res <= std_logic_vector(res_int (level-1));
26
27
  process(clk)
28
  begin
29
  if clk'event and clk = '1' then
30
  -- multiplier operand inputs are registered
31
  a_int <= signed (a);
32
  b_int <= signed (b);
33
  -- 'level' levels of registers to be inferred at the
34
  -- output of the multiplier
35
  res_int(0) <= a_int*b_int;
36
    for i in 1 to level-1 loop
37
      res_int (i) <= res_int (i-1);
38
    end loop;
39
  end if;
40
end process;
41
end arch;

Und Testbench:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.std_logic_signed.all;
4
USE ieee.numeric_std.ALL;
5
 
6
ENTITY filter_tb IS
7
END filter_tb;
8
 
9
ARCHITECTURE testbench OF filter_tb IS 
10
 
11
    -- Component Declaration for the Unit Under Test (UUT)
12
 
13
    COMPONENT filter
14
    PORT(
15
         clk : IN  std_logic;
16
         load_x : IN  std_logic;
17
         data_in : IN  std_logic_vector(8 downto 0);
18
         koeff_in : IN  std_logic_vector(8 downto 0);
19
         data_out : OUT  std_logic_vector(10 downto 0)
20
        );
21
    END COMPONENT;
22
    
23
24
   --Inputs
25
   signal clk : std_logic := '0';
26
   signal load_x : std_logic := '0';
27
   signal data_in : std_logic_vector(8 downto 0) := (others => '0');
28
   signal koeff_in : std_logic_vector(8 downto 0) := (others => '0');
29
30
   --Outputs
31
   signal data_out : std_logic_vector(10 downto 0);
32
33
   -- Clock period definitions
34
   constant clk_period : time := 50 ns; -- 20 MHz
35
 
36
BEGIN
37
 
38
  -- Instantiate the Unit Under Test (UUT)
39
   uut: filter PORT MAP (
40
          clk => clk,
41
          load_x => load_x,
42
          data_in => data_in,
43
          koeff_in => koeff_in,
44
          data_out => data_out
45
        );
46
47
   -- Clock process definitions
48
   clk_process: process
49
   begin
50
    clk <= '0';
51
    wait for clk_period/2;
52
    clk <= '1';
53
    wait for clk_period/2;
54
   end process;
55
 
56
57
   -- Stimulus process
58
   stim_proc: process
59
   begin    
60
    load_x <= '0';
61
    data_in <= "000000000";
62
    koeff_in <= "001111100"; -- Koeff 1 - 124
63
    wait for clk_period;
64
    koeff_in <= "000110010"; -- Koeff 2 - 50
65
    --koeff_in <= "000000000";
66
    wait for clk_period;
67
    koeff_in <= "001000011"; -- Koeff 3 - 67
68
    --koeff_in <= "000000000";
69
    wait for clk_period;
70
    koeff_in <= "001010011"; -- Koeff 4 - 83
71
    --koeff_in <= "000000000";
72
    wait for clk_period;
73
    koeff_in <= "011010110"; -- Koeff 5 - 214
74
    --koeff_in <= "000000000";
75
    wait for clk_period;
76
    koeff_in <= "010110000"; -- Koeff 6 - 176
77
    --koeff_in <= "000000000";
78
    wait for clk_period;
79
    koeff_in <= "000000000";
80
    wait for 2*clk_period;
81
    load_x <= '1';
82
    wait for clk_period;
83
    data_in <= "001100100";
84
    --wait for 2*clk_period;
85
    --data_in <= "000000000";
86
    
87
      -- hold reset state for 100ms.
88
      --wait for 100ms;  
89
90
     -- wait for clk_period*10;
91
92
      -- insert stimulus here 
93
94
      wait;
95
   end process;
96
97
END;

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

von Frager (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

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

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


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

von Kirill Y. (schkrent)


Lesenswert?

der Unterschied ist mir bekannt )))
1
for i in 0 to k - 2 loop
2
      sum(i) <= (prod(i)(MULT_SIZE - 1) & prod(i)) + sum(i + 1);
3
    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.

von Kirill Y. (schkrent)


Lesenswert?

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

von Kirill Y. (schkrent)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.