Forum: FPGA, VHDL & Co. Überlauf / Unterlauf - VHDL


von Mark (Gast)


Lesenswert?

Hallo zusammen

Wer kann mir helfen?
Ist wahrscheinlich total trivial für die VHDL-Experten hier...

E(n) = E(n-1) + A - C

Diese Formel gilt es zu implementieren.

C kann die Werte von 8 bis 31 annehmen kann.
A kann 0 bis 511 annehmen.

So, E(n) darf aber nicht kleiner als 0 und darf auch nicht größer als
1023 werden.

Gruss,
Mark

von theFloe (Gast)


Lesenswert?

Was soll passieren wenn E(n) größer als 1023 bzw kleiner als 0 wäre?
Soll E(n) dann auf 1023 bzw 0 gesetzt werden?

Eine Möglichkeit wäre E(n) per Range bei der Deklaration auf 0 bis 1023
zu beschränken oder:
1
tmp = E(n-1)+A-C
2
if tmp >= 1023 then
3
E(n) = 1023
4
elsif tmp <= 0 then
5
E(n) = 0
6
end if;

von Mark (Gast)


Lesenswert?

Hallo Tobias

Ja, danke erst mal.
Aber E(n) soll vom Typ std_logic_vector sein.

Wenn E(n) größer als 1023 oder kleiner 0 wird, so soll E(n) auf 1023
bzw auf 0 begrenzt werden.

Mark

von Ines (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Tobias,

ich habe Dir mal meine Lösung angehängt. Damit wirst Du aber keine
allzuschnelle Systemfrequenz erreichen, da alles in einem Takt
berechnet wird.

Wenn Du Fragen zum Code hast, bitte melden.

Gruß
Ines

von theFloe (Gast)


Lesenswert?

Hallo Ines,

von Mark kam die Problemstellung :)

Gruß Tobias

von Ines (Gast)


Lesenswert?

Oh, na gut! Hauptsache Ihr beide verwechselt Euch nicht :-)
Aber danke für den Hinweis!

von FPGA-User (Gast)


Lesenswert?

@Ines
Deine Lösung bringt auf Anhieb 3 Errors im Modelsim

@Mark
lass Dir sowas nicht andrehn ;-)))

von Mark (Gast)


Lesenswert?

Danke, Danke!

von Ines (Gast)


Lesenswert?

@FPGA-User
Der Code war auch mehr als Anregung gedacht. Ich hätte vielleicht
dazuschreiben sollen, dass er weder kompiliert, noch synthetisiert,
noch getestet ist.

@Tobias - arghh - ich meine natürlich Mark :-)))
Ich hoffe, Du kannst trotzdem was damit anfangen!

von Mark (Gast)


Lesenswert?

Danke Ines!

von FPGA-User (Gast)


Lesenswert?

@Mark

um noch nen konstruktiven Beitrag zu leisten, so würde
ich das machen :

   process(reset, clk)

      variable y : signed(11 downto 0); -- Zwischenwert 2 bits mehr

   begin
      if reset = '1' then
         en <= conv_std_logic_vector(0, en'LENGTH);

      elsif rising_edge(clk) then

         y := signed("00" & en) + signed('0' & a) - signed('0' &
c);

         if y > 1023 then
            en <= (others=>'1');
         elsif y < 0 then
            en <= (others=>'0');
         else
            en <= std_logic_vector( y(9 downto 0) );
         end if;


      end if;
   end process;

Es fehlt nur die Zeile, wo en zu Beginn seinen Startwert bekommt.
(Der Code ist simuliert...)

PS : es ist etwas krampfhaft mit std_logic_vector Rechenoperationen
zu machen, besser gehts mit signed, das liest sich dann auch besser

von Mark (Gast)


Lesenswert?

Hallo FGPA-User

Kannst du mir das VHDL-technisch mal erklären, warum es "krampfhaft"
ist, mit std_logic_vector Rechenoperationen zu machen uns warum es
besser mit signed geht?
Danke schon mal.

Ach ja: Danke für deinen Code-Vorschlag!

Was machst du eigentlich hier:
en <= conv_std_logic_vector(0, en'LENGTH);
...und hier:
y  := signed("00" & en) + signed('0' & a) - signed('0' & c);
...und warum eigentlich "signed" und nicht unsigned?

Mark

von FPGA-User (Gast)


Lesenswert?

@Mark

en <= conv_std_logic_vector(0, en'LENGTH)

heisst, dass der Wert 0 (den ich als Integer hinschreibe)
auf std_logic_vector konvertiert wird und en zugewiesen
wird. Dabei muss man angeben, wieviele bits en hat (en'LENGTH)
Damit kann ich - wie gesagt - einen Integer an en zuweisen,
fällt mir leichter als binär- oder Hexzahlen im Kopf zu berechnen.
Hier werden keine extra Resourcen benötigt, ich könnte genausogut
schreiben
en <= "0001110011"; -- net ganz so gut lesbar

Die Zeile mit Y ist etwas komplizierter, damit der Vergleich auf
< 0 sauber funktioniert bringe ich alles auf SIGNED.
Dazu müssen alle Summanden (die ja unsigned sind ) um ein MSB
erweitert werden, dass 0 ist. Damit ist klar, dass es positive
Zahlen sind. Ansonsten würde der Compiler das MSB erweitern
und sobald dieses gesetzt wäre (bei a oder c) würde man falsch
rechnen.

Mindestens 1 Summand muss genauso groß sein (Bitbreite) wie das
Ergebnis, deshalb wird en um 2 bits "00" erweitert.
Das war u.a. ein Fehler von Ines.
y ist 2 bits größer als en gewählt, da das Ergebnis nach Deinen
Vorgaben max. 1023 + 511 - 8 = 1526 sein kann, wenn ich mich recht
erinnere 1526. Um +1526 als signed darzustellen braucht man 12 bits
( = -2048 ... + 2047), deshalb ist y 12 bits breit.

Da ich weiss, dass meine Vergleiche y < 0 und y > 1023 abgefangen
haben, kann ich am Ende einfach die 10 LSBs abspeichern.

Hoffe, dass es wenigstens teilweise verständlich ist, hier muss
man mit Binärzahlen und Zahlenformaten einigermaßen sattelfest sein.
Sicher ist es für Anfänger leichter, die Rechnung + Vergleiche
schrittweise zu machen.

von FPGA-User (Gast)


Lesenswert?

@Mark

nochwas, std_logic_vector nehme ich eigentlich ungern,
keiner weiß, was die bits darin bedeuten.

Viel besser finde ich:
integer, positive, unsigned, signed, ...

oder sowas:

   type INT_ACK_REG_TYPE is
      record
         int_ack    : INT_SIG_TYPE;
         write_flag : boolean;
      end record;


da weiß man gleich, was dahinter steckt.

von Mark (Gast)


Lesenswert?

Hallo FPGA-User

Sieht elegant aus:
en <= conv_std_logic_vector(0, en'LENGTH)
So werd' ich's in Zukunft auch machen.
;-)

Aber warum du auf SIGNED (also MSB = 1 => Negativ bzw. MSB = 0 =>
Positiv) gehst, verstehe ich immer noch nicht.
(Is' wahrscheinlich ein Verständnis-Problem.)

Nochwas: SIGNED stellt seine Werte doch immer im 2er Komplement dar,
ja?
Also: 111111111 entspricht "Minus-1", ja?

Mark

von FPGA-User (Gast)


Lesenswert?

ja, 2er Komplement, die -1 ist richtig

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.