www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Multiplitierer in VHDL


Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Leute,ich muss hier ein multiplitierer programmieren denn 
den wert von A*B in shift speicher und die an der ausgang result 
ubergeben soll.Das problem ist ubergebende wert muss nicht große und 
nicht kleiner als limit.ich hatte gedacht mit schieben von bit kann ich 
etwas erreichen aber es schien mein idee nicht so gut gewesen zu 
sein.Hat jemand  eine idee oder ist meine idee gut und ic kann es nicht 
umsetzen.ich danke euch.was ich gemacht habe ist hier unten.
entity Mul is
port ( clk       :in std_logic;
       reset_n    :in std_logic;
       A            :in std_logic_vector(15 downto 0);
       B            :in std_logic_vector(15 downto 0);
       limit        :in std_logic_vector(15 downto 0);
       result       :out std_logic_vector(15 downto 0)
       );
end Mul;
architecture verh of Mul is
signal shift        :std_logic_vector(15 downto 0);
 begin
  process(clk,reset_n)
    begin
    if reset_n = '0' then
    --  A <= x"0";
      --B <= x"0";
       elsif clk='1' and clk'event then
      shift <= A * B ;
       if shift >= limit then
      shift<= '0' & limit(14 downto 0);
       elsif shift <= limit then
      shift<= limit(15 downto 1) & '1';
    end if;
  end if;
    end process;
 result<= shift;
end verh;

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

Bewertung
0 lesenswert
nicht lesenswert
> wert muss nicht große und nicht kleiner als limit.
Dann muß er gleich sein  :-o

Das Ergebnis einers Multipliziers ist genaus breit wie die beiden 
Eingangswerte zusammen.

Ein Multiplizierer ist ein kombinatorisches Bauwerk.
Dashalb brauchst du keinen Takt und keinen Reset und kannst für die 
Multiplikation ganz einfach schreiben:
:
use IEEE.numeric_std.all
:
entity Mul is
port ( A            :in std_logic_vector(15 downto 0);
       B            :in std_logic_vector(15 downto 0);
       result       :out std_logic_vector(31 downto 0) --- Breite!!!
       );
end Mul;

architecture verh of Mul is
begin
 result <= std_logic_vector(unsigned(A) * unsigned(B));
end verh;

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ingo 16 Takte Zeit hat für die Berechnung, kann man einen schönen 
einfachen Multiplizierer basteln, der erheblich kleiner ist als das 
vorgeschlagene (schnelle) kombinatorische Konstrukt.

Autor: befro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ein Multiplizierer ist ein kombinatorisches Bauwerk.
Das hängt davon ab, wieviele Resourcen man verbraten will. Einen 
Multiplizierer mit getakteter Struktur braucht zwar mehr Rechenzeit, 
dafür aber weniger Gatter.

Autor: Matthias G. (mgottke)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Je nach dem auf welcher Zielhardware man hat, kann ev. auch ein 
integrierter Hardwaremultiplizierer verwendet werden.

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

Bewertung
0 lesenswert
nicht lesenswert
Ich sehe das so:
Wenn ich ein FPGA mit einem übrigen Multiplizierer habe, dann habe ich 
sogar noch Ressourcen besser ausgenutzt, wenn ich diesen verwende. Und 
wenn kein Multiplizierer mehr übrig ist, dann muß ich einen der anderen 
multiplexen. Dann bin ich in einem Takt fertig...

Ja, und wenn ich keinen Multiplizierer habe, dann mache ich das 
logischerweise auch nicht kombinatorisch (wobei es auf die Wortbreite 
ankommt). Aber die meisten meinen eben, ein Mutliplizierer müsse 
getaktet sein.

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wer meint denn das?

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für euere hilfe.Aber lothar ich muss den ausgang an einer eingang 
von FPGA mikroprocesseur mit 16 bit verbinden deswegen ist es unmöglich 
meine ausgang mit 32 bits zu machen.mit den clk und reset ist klar.Und 
limit ist normaleweise da um den wert von A*B aus die herausgegeben 
werden soll nicht mehr als und nicht weniger als 16 bits ist.
Danke

Autor: John-eric K. (mockup)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du kannst die Daten doch nacheinander einlesen.
erst die höheren 16bit
und danach die unteren 16. (oder andersherum)

wie wäre es damit(nicht getestet)

entity Mul is
port ( clk          :in std_logic;
       reset_n      :in std_logic;
       A            :in std_logic_vector(15 downto 0);
       B            :in std_logic_vector(15 downto 0);
       limit        :in std_logic_vector(15 downto 0);
       result       :out std_logic_vector(15 downto 0)
       );
end Mul;
architecture verh of Mul is
signal shift        :std_logic_vector(32 downto 0);
 begin
  process(clk)
    begin
     if rising_edge(clk) then
      shift <= A * B;
       if shift >= ("0000" & limit) then
      shift(15 downto 0) <= '0' & limit(14 downto 0);
       elsif shift <= ("0000" & limit) then
      shift(15 downto 0)<= limit(15 downto 1) & '1';
    end if;
  end if;
    end process;
 result<= shift(15 downto 0);
end verh;

jetzt kannste ganz normal berechnen und wenn der wert über/unter deiner 
limit variable liegt, wird sie geändert.

Autor: Thomas Reinemann (Firma: abaxor engineering) (abaxor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ingo,

Du darfst nicht innerhalb eines Prozesses einem Signal zweimal einen 
Wert zuweisen ohne die Zuweisungen zu priorisieren. In deinem Fall 
erfolgen

shift <= A * B ;
und eine der Zuweisungen gleichzeitig.
  shift<= '0' & limit(14 downto 0);
  shift<= limit(15 downto 1) & '1';
Welche Tatsächlich ausgeführt wird hängt von der Code-Optimierung sowohl 
im Simulator als auch in der Synthese ab. Das führt zu frustierenden 
Ergebnissen.

Bei dem Fall treten auch keine multiplen Treiber auf, d.h. elektrisch 
ist es richtig nur nicht logisch.

Versuche mal folgendes

prod <= A * B;
if prod >= ("0000" & limit) then
  shift(15 downto 0) <= '0' & limit(14 downto 0);
elsif prod < ("0000" & limit) then -- kein <= da = schon im if; Warum
                                   -- überhaupt ein elsif?
  shift(15 downto 0)<= limit(15 downto 1) & '1';
end if;

Tom

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

Bewertung
0 lesenswert
nicht lesenswert
> Welche Tatsächlich ausgeführt wird hängt von der Code-Optimierung sowohl
> im Simulator als auch in der Synthese ab.
Nein, in einem Prozess wird die letze ausgeführte Zuweisung an ein 
Signal ausgeführt. Das bedeutet hier allerdings, dass shift mit einem 
Takt Latency daherkommt.

Offenbar sollte das
> signal shift        :std_logic_vector(32 downto 0);
eine Variable sein.
Denn dann wird erst die Multiplikation ausgeführt, danach das Ergebnis 
der Multiplikation zur weiteren Verarbeitung verwendet.

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
 ich habe alles möglich probiert. den code compliliert richtig aber wenn 
ich das uber nios 2 aufruf wird keine multiplcatin ausgeführt.Wie kann 
ich dass verändert?
danke euch

Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe noch probiert und bekomme nur den wert von limit raus ? und es 
sollte nicht sein.Bitte kann mir jemand helfen

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

Bewertung
0 lesenswert
nicht lesenswert
> Bitte kann mir jemand helfen
Zeig doch mal deinen Code.

Autor: ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE IEEE.std_logic_signed.ALL;
entity Mul is
port ( clk       :in std_logic;
       reset_n    :in std_logic;
       A            :in std_logic_vector(15 downto 0);
       B            :in std_logic_vector(15 downto 0);
       limit        :in std_logic_vector(15 downto 0);
       result       :out std_logic_vector(15 downto 0)
       );
end Mul;
architecture verh of Mul is
signal shift        :std_logic_vector(31 downto 0);
 begin
  process(clk,reset_n)
    begin
    if reset_n = '0' then
      elsif clk='1' and clk'event then
      shift <= A * B ;
      if shift >=("0000" & limit) then
        shift(15 downto 0) <=  limit(15 downto 0);
      elsif shift < ("0000" & limit)  then
        shift(15 downto 0) <= limit (15 downto 0) ;
      end if;
      result <= shift(15 downto 0);
    end if;
end process;
end verh;

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

Bewertung
0 lesenswert
nicht lesenswert
> aber wenn ich das uber nios 2 aufruf wird keine multiplcatin ausgeführt.
Du wartest in deinem NIOS-Code aber schon, bis die Multiplikation fertig 
ist?

Hast du die vorhergehenden Posts gelesen?
Ich zitiere mich selbst ungern, aber:
> Offenbar sollte das
>> signal shift        :std_logic_vector(32 downto 0);
> eine Variable sein.
> Denn dann wird erst die Multiplikation ausgeführt, danach das Ergebnis
> der Multiplikation zur weiteren Verarbeitung verwendet.

EDIT:
Noch ein Zitat
>>> wert muss nicht große und nicht kleiner als limit.
>> Dann muß er gleich sein  :-o
Und genau das macht die Abfrage in deinem Code (ja, ich weiß dass du den 
"nur" kopiert hast; das entschuldigt dich aber nicht). Denn das:
      if shift >=("0000" & limit) then      -- wenn größer oder gleich
        shift(15 downto 0) <=  limit(15 downto 0);
      elsif shift < ("0000" & limit)  then  -- wenn kleiner
        shift(15 downto 0) <= limit (15 downto 0) ;
      end if;
könnte auch so geschrieben werden:
      if ( shift>=("0000"&limit) or   shift<("0000"&limit) )then      -- wenn größer oder gleich oder kleiner
        shift(15 downto 0) <=  limit(15 downto 0);
      end if;
oder wesentlich kompakter:
        shift(15 downto 0) <=  limit(15 downto 0);
Und genau das erhältst du.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vor allem was soll das bringen? Der NIOS-II hat doch die Option einen 
Hardwaremultiplizierer (sogar 32 bit) anzubinden...
Und wenns per hand sein soll/muß würd ich da auch eher das 
CustomInstruction Interface vorschlagen.

Autor: m.rose (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der obige Quelltext kann nicht funktionieren, weil die Signalzuweisung 
nur EINMAL erfolgt, und zwar wenn der Simulator den Prozess verläßt.

Aber das läßt sich sehr einfach lösen, indem du im Prozess mit Variablen 
arbeitest. Variablen werden SOFORT zugewiesen, nachdem die betreffende 
Anweisung gelesen wurde.

Am Ende, d.h. direkt vor der Anweisung "end ...", weist du dann dem 
Signal die Variable einmalig zu, und alles ist paletti.

SIGNAL sig: typ;
VARIABLE var : typ; -- gleicher typ wie sig!


PROCESS (clk)

   IF (clk'EVENT AND clk=1) THEN

       -- 1) Signal an Variable übergeben:

          var := sig;

       -- 2) mit Variable rechnen, etwa wie folgt:

          var := var +1;
          IF var = 10 THEN var:=0;

       -- 3) das ergebnis einmalig dem signal zuweisen:

          sig <= var;

   END IF;

END PROCESS;

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, Mr. m.rose (Gast), ich finds gut, dass du hier Zeit investieren 
möchtest, um anderen Leuten zu helfen. Aber ob die Leute wirklich 
jahrelang auf eine Antwort gewartet haben, wage ich zu bezweifeln ;-)

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.