Forum: FPGA, VHDL & Co. Multiplizierer in VHDL


von Klaus M. (max_musterm)


Lesenswert?

Hallo,
ich bin dabei Uni-bedingt einen Multiplizierer zu basteln und komme 
leider seit fast einer halben Woche nicht weiter. Ich finde einfach 
nicht den Fehler und habe das Gefühl dass ich den Wald vor lauter Bäumen 
nicht sehe.
Wenn ich das ganze mit ISim simuliere ist mein Produktvektor komplett 
Undefined.


Da ich inzwischen ziemlich im Zeitdruck mit der Abgabe bin wollt ich mal 
schauen ob mir jemand hier im Forum weiterhelfen kann - bin ich über 
jeden Tipp dankbar.


Code des Multiplizieres:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Multio2signed is
  port(
    multiplicand  : in  signed;
    multiplicator : in  signed;
    product       : out signed;
    error : out std_ulogic
  );
end;

architecture behav of Multio2signed is



  constant m: positive := multiplicand'length;
  constant n: positive := multiplicator'length;

  type Table is array (natural range <>) of signed(m-1 downto 0);
  signal A : Table(0 to n-1);
  signal B : Table(0 to n);
  signal c1 : signed(m downto 0);

begin



Multiprozess : process

begin
  B(0)<=(others=>'0');
  assert product'length=m+n;
  error <= '0';


  -- Belegung Matrix A

  for i in 0 to n-1 loop

    if multiplicator(i) = '1' then
      A(i)<=multiplicand;
    elsif multiplicator(i) = '0' then
      A(i)<=(others=>'0');
      else error <= '1';
    end if;
  end loop;




  --Belegung Matrix B und Produktzuweisung

    for k in 1 to n loop
  c1<=resize(A(k-1),m+1)+resize(B(k-1),m+1);
    product(k-1 downto k-1)<=c1(0 downto 0);
    B(k)<=c1(m downto 1);
  end loop;
  product(m+n-1 downto n)<=c1(m downto 1);
  wait;
  end process;

  end;









Testbench:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Multio2signed_tb is
  end;

architecture test of Multio2signed_tb is
  signal mcand_int : signed(3 downto 0) :=(others => '0');
  signal mtor_int : signed(3 downto 0) :=(others => '0');
  signal p_int : signed((mcand_int'length + mtor_int'length - 1) downto 
0) :=(others => '0');
    signal error : std_ulogic;


begin
  Multi : entity work.Multio2signed

  port map
        (multiplicand      => mcand_int,
           multiplicator      => mtor_int,
           product  => p_int,
           error => error

           );


  stimuli : process
  begin


      mcand_int     <= "0110";
      mtor_int     <= "1101";
      wait for 10 ms;
      assert error = '0' report "Fehler";
      assert p_int = "01001110" report "Unexpected Result" ;-- severity 
FAILURE;




  wait;
  end process;


  end;

von Tobias L. (murxwitz)


Lesenswert?

Am einfachsten wäre wohl, da du ja schon die numeric_std und signed 
verwendest:
product <= multiplicand * multiplicator;

von Klaus M. (max_musterm)


Lesenswert?

Die Aufgabe besteht dadrin den Multiplizierer ohne "*" Operanden 
hinzubekommen ;)

von berndl (Gast)


Lesenswert?

super, und dann gibt's mal wieder VHDL ohne irgendeinen Kommentar der 
grob beschreibt, was man denn eigentlich machen wollte...

Nee, ich werde hier nicht versuchen, reverse-engineering zu betreiben!

von Fpgakuechle K. (Gast)


Lesenswert?

"sensitivity List" fehlt.

MfG,

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


Lesenswert?

Dafür steht da ein
> wait;

@Klaus M:
muss dein Zeug synthetisierbar sein?

von Klaus M. (max_musterm)


Angehängte Dateien:

Lesenswert?

@IKmiller ich weiß nicht genau was du mit synthetisierbar meinst, aber 
ich denke nein. Der Code soll nur fehlerfrei über ISim simuliert werden 
können.




@Rest
Ah sorry, total vergessen,
also,der Plan war/ist, am Beispiel mit der Multiplikation von 0110 * 
1101: (siehe Bild)

multiplicand (m bit lang) * multiplicator (n bit lang) = produkt (m+n 
bit lang)


Erst alle "einzel" Multiplikationen vom least significant bit aus bis 
zum most sig. bit  (vom Bultiplikator) durch eine Schleife ausführen und 
die Ergebnisse davon in der Matrix A speichern.

also :

1 * 0110 = (0110)
0 * 0110 = (0000)   wobei dies die Matrix A darstellen soll
1 * 0110 = (0110)
1 * 0110 = (0110)

Dann im nächsten Schritt die Matrix B in einer Schleife generieren.
Diese hat in der ersten Zeile nur "0000" und entsteht danach durch 
Addition von ihrer vorherigen Zeile mit der entsprechenden Zeile aus A, 
wobei hier das least significant bit nur temporär in c1 gespeichert bzw 
ans produkt weitergegeben wird.
Dies dann bis zum Ende ausführen und am Schluß den Kopf des Produktes 
von c1 erhalten.


Ich hoffe zusammen mit dem Bild ist dies einigermaßen verständlich.




Hier auch nochmal der Code in VHDL:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity Multio2signed is
6
  port(
7
    multiplicand  : in  signed;
8
    multiplicator : in  signed;
9
    product       : out signed;
10
    error : out std_ulogic
11
  );
12
end;
13
14
architecture behav of Multio2signed is
15
16
17
18
  constant m: positive := multiplicand'length;
19
  constant n: positive := multiplicator'length;
20
21
  type Table is array (natural range <>) of signed(m-1 downto 0);
22
  signal A : Table(0 to n-1);
23
  signal B : Table(0 to n);
24
  signal c1 : signed(m downto 0);
25
26
begin
27
28
29
30
Multiprozess : process
31
32
begin
33
  B(0)<=(others=>'0');
34
  assert product'length=m+n;
35
  error <= '0';
36
37
38
  -- Belegung Matrix A
39
40
  for i in 0 to n-1 loop
41
42
    if multiplicator(i) = '1' then
43
      A(i)<=multiplicand;
44
    elsif multiplicator(i) = '0' then
45
      A(i)<=(others=>'0');
46
      else error <= '1';
47
    end if;
48
  end loop;
49
50
51
52
53
  --Belegung Matrix B und Produktzuweisung
54
55
    for k in 1 to n loop
56
  c1<=resize(A(k-1),m+1)+resize(B(k-1),m+1);
57
    product(k-1 downto k-1)<=c1(0 downto 0);
58
    B(k)<=c1(m downto 1);
59
  end loop;
60
  product(m+n-1 downto n)<=c1(m downto 1);
61
  wait;
62
  end process;
63
64
  end;

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


Lesenswert?

Ein Tipp zum Thema "Schleifen mit Signalen": Signale übernehmen in VHDL 
erst beim nächsten "wait" oder am Prozessende den zuletzt an sie 
zugewiesenen Wert...

Du brauchst für solche Schleifen als "Zwischenspeicher" immer Variablen.

Ich würde für so eine stumpfsinnige und praxisferne Aufgabe (es gibt wie 
schon gesagt den fertigen Operator) einfach mal per Reverse Engeneering 
angehen: wie ist der Operator in der numeric_std umgesetzt? Den 
Quellcode dafür gibts an jeder Ecke...

: Bearbeitet durch Moderator
von Fpgakuechle K. (Gast)


Lesenswert?

Gute, wenn auch knappe Seite zu Multiplizierer in FPGA:
http://www.andraka.com/multipli.htm

Am besten für eine der Grundstrukturen z.B Wallace-tree entscheiden und 
die dann als hierarchische Blockstrukter über generate-Anweisungen 
aufbauen.

MfG,

von Paul B. (Gast)


Lesenswert?

berndl schrieb:
> super, und dann gibt's mal wieder VHDL ohne irgendeinen Kommentar der
> grob beschreibt, was man denn eigentlich machen wollte...
>
> Nee, ich werde hier nicht versuchen, reverse-engineering zu betreiben!

Das ist wirklich ein Problem, vieler Entwickler, dass sie ihre Gedanken 
nicht formulieren können oder wollen, weil sie es nicht für nötig 
halten. Dabei wäre es wichtig, das SOLL zu kennen, um die Art der 
Umsetzung und ihre Defizite zu begreifen und nicht nur das IST zu sehen 
und das SOLL zu erraten.

Ok, bei vielen Dingen ist es trivial (genug), damit das "reverse 
engineering" durch den Gegenüber klappt, aber das Schwierige daran ist, 
dass dadurch, dass man es so nie richtig lernt zu formulieren und zu 
dokumentieren und dann, wenn es gebraucht würde, weil die Probleme 
komplexer werden, es dann nur unzureichend kann.

Damit bleibt man im Hamsterrad.

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.