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;
> 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:
1 | :
|
2 | use IEEE.numeric_std.all |
3 | :
|
4 | entity Mul is |
5 | port ( A :in std_logic_vector(15 downto 0); |
6 | B :in std_logic_vector(15 downto 0); |
7 | result :out std_logic_vector(31 downto 0) --- Breite!!! |
8 | );
|
9 | end Mul; |
10 | |
11 | architecture verh of Mul is |
12 | begin
|
13 | result <= std_logic_vector(unsigned(A) * unsigned(B)); |
14 | end verh; |
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.
>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.
Je nach dem auf welcher Zielhardware man hat, kann ev. auch ein integrierter Hardwaremultiplizierer verwendet werden.
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.
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
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.
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
> 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.
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
ich habe noch probiert und bekomme nur den wert von limit raus ? und es sollte nicht sein.Bitte kann mir jemand helfen
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;
> 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:
1 | if shift >=("0000" & limit) then -- wenn größer oder gleich |
2 | shift(15 downto 0) <= limit(15 downto 0); |
3 | elsif shift < ("0000" & limit) then -- wenn kleiner |
4 | shift(15 downto 0) <= limit (15 downto 0) ; |
5 | end if; |
könnte auch so geschrieben werden:
1 | if ( shift>=("0000"&limit) or shift<("0000"&limit) )then -- wenn größer oder gleich oder kleiner |
2 | shift(15 downto 0) <= limit(15 downto 0); |
3 | end if; |
oder wesentlich kompakter:
1 | shift(15 downto 0) <= limit(15 downto 0); |
Und genau das erhältst du.
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.
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;
Ä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 ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.