Hallo zusammen! Ich brauche 2 Vektoren miteinander zu dividieren. Dazu habe ich ein kleines Programm geschrieben, das zwei std_logic_vectoren mit der Längen 10 miteinander dividiert. Leider funktioniert das nicht:( Ich denke, dass es an die unterschiedlichen Dauer der Instruktionen liegt. So die Werte, die durch Verschiebung entstehen können möglicherweise erts in der nächsten Clock fertig sein, so dass die for-schleife mit falschen Werten arbeitet. Vielleicht kann man irgendwie eine Verzögerung überlegen, befor man in die for- Schleife kommt. Und darf ich überhaupt in diesem Fall die for- Schleife benutzen??? Bin für jede Hilfe dankbar! Hier ist mein Programm und Testbench. library STD; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity VectorDivision is Port(Clock : in std_logic; VectorA : in std_logic_vector(9 downto 0); VectorB : in std_logic_vector(9 downto 0); Ergebnis:out std_logic_vector(9 downto 0); Rest :out std_logic_vector(9 downto 0)); end VectorDivision; architecture Behavioral of VectorDivision is signal Nullen: std_logic_vector(8 downto 0):=(others=>'0'); signal tempA: std_logic_vector(18 downto 0); signal tempB: std_logic_vector(27 downto 0); signal tempC: std_logic_vector(18 downto 0); signal y: std_logic_vector(9 downto 0); begin Process (Clock) begin if rising_edge(Clock) then tempA <=Nullen & VectorA;--Erweiterung mit Nullen, damit beim Vergleich tempB <=Nullen & VectorB & Nullen; -- die Laengen uebereinstimmen for i in 9 downto 0 loop tempC <= tempB(27-i downto 9-i); if tempA >= tempC then -- Vector A mit Vector B*2**i vergleichen y(i)<= '1'; --A groesser als B*2**i wird i-Bit gesetzt tempA <= tempA-tempC; --und B*2**i wird von A abgezogen else y(i) <= '0'; end if; end loop; Rest <= tempA(9 downto 0); Ergebnis <= y; end if; end process; end Behavioral; library STD; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY TB_VecortDivision IS END TB_VecortDivision; ARCHITECTURE behavior OF TB_VecortDivision IS COMPONENT VectorDivision PORT( Clock : IN std_logic; VectorA : IN std_logic_vector(9 downto 0); VectorB : IN std_logic_vector(9 downto 0); Ergebnis : OUT std_logic_vector(9 downto 0); Rest : OUT std_logic_vector(9 downto 0) ); END COMPONENT; signal Clock : std_logic := '0'; signal VectorA : std_logic_vector(9 downto 0) := "1111101000"; --1000 dec signal VectorB : std_logic_vector(9 downto 0) := "0000010100"; -- 20 dec signal Ergebnis: std_logic_vector(9 downto 0); signal Rest : std_logic_vector(9 downto 0); constant ClockPeriod: time:= 6.666 ns; BEGIN uut: VectorDivision PORT MAP ( Clock => Clock, VectorA => VectorA, VectorB => VectorB, Ergebnis => Ergebnis, Rest => Rest ); ClockProcess :process begin Clock <= '1'; wait for ClockPeriod; Clock <= '0'; wait for ClockPeriod; end process; END;
Signale erhalten ihren neuen Wert erst dann, wenn der Prozess zum nächsten Mal ausgeführt wird. Wenn du Variablen anstatt von Signalen verwenden würdest, dann könnte dein Programm zumindest im Simulator funktionieren. Für die Synthese ist der Ansatz aber komplett falsch; wiederholte Ausführung mit Schleifen gibt es da nicht, das muss man von Hand mit einem Zustandsautomaten machen. Am besten schaust du dir noch mal ein paar einfachere VHDL-Beispiele an, und liest nach wie die einzelnen Konstrukte (Variablen, Signale, Schleifen) funktionieren. Da fehlen noch ein paar Grundlagen bevor du dich an einen Dividierer wagen kannst.
> Ich denke, dass es an die unterschiedlichen Dauer der Instruktionen liegt. Diese Denkweise ist grundlegend falsch. :-o Deine VHDL-Beschreibung wird parallel in Hardware umgesetzt, und mit jedem Takt einmal komplett ausgeführt. Wenn da ein langsamer Kombinatorikpfad drin ist, dann sagt dir das das Synthesetool. Vergiss für den Anfang das Schlüsselwort loop. Eine Schleife in VHDL beschreibt nicht etwas, das nacheinander x-mal ausgeführt wird, sondern etwas, das x-mal gleichzeitig auf das FPGA abgebildet wird. Und vor allem: wenn du irgendwas simulieren kannst, dann heißt das noch lange nicht, dass du es auch auf Hardware synthetisiert bekommst... BTW: Beitrag "Re: Funktionsplan in VHDL übersetzen"
Erstmal danke für eure Anweisungen! Ich habe jetzt versucht das ganze als einen Zustandsautomat zu machen. Das Ergebnis im Vergleich zum richtigen wird um ein bit nach nach hinten verschoben. Und das wird erstmal wenn z zweimal komplett durchgelaufen wird. Hat jemand eine Idee woran es liegen kann? entity VectorDivision is Port(Clock : in std_logic; VectorA : in std_logic_vector(9 downto 0); VectorB : in std_logic_vector(9 downto 0); Ergebnis:out std_logic_vector(9 downto 0); Rest :out std_logic_vector(9 downto 0)); end VectorDivision; architecture Behavioral of VectorDivision is signal Nullen: std_logic_vector(8 downto 0):=(others=>'0'); signal tempA: std_logic_vector(18 downto 0); signal tempB: std_logic_vector(18 downto 0); signal tempC: std_logic_vector(27 downto 0); signal y: std_logic_vector(9 downto 0); signal z,zplus :integer:=9; begin Process (Clock) begin if rising_edge(Clock) then z <= zplus; if z=9 then tempA <= Nullen & VectorA; tempC <= Nullen & VectorB & Nullen; end if; tempB <= tempC(27-z downto 9-z); if tempA >= tempB then y(z) <= '1'; tempA <= tempA - tempB; else y(z)<='0'; end if; end if; end process; Process(z) begin case z is when 0=> zplus <= 9; Rest <= tempA(9 downto 0);Ergebnis<=y; when others => zplus <= z-1; end case; end process; end Behavioral;
So wird das Ergebniss rechtzeitig berechnet, aber trotzdem um ein Bit verschoben Process(z) begin case z is when 0 => zplus <= 9; when 9 => zplus <= z-1; Rest <=tempA(9 downto 0); Ergebnis<=y; when others => zplus <= z-1; end case; end process;
Du bemerkst das in der Simulation, richtig? Übliche Ursache für eigenartiges Verhalten in der simulation: die Sensitivliste eines kombinatorischen Prozesses ist unvollständig.
1 | Process(z) |
Hier gehört das temA und y auch mit rein, denn beim Zustand 9 hängt das Ergebnis auch von diesen beiden Werten ab:
1 | Process(z, tempa, y) |
2 | begin
|
3 | case z is |
4 | when 0 => zplus <= 9; |
5 | when 9 => zplus <= z-1; Rest <=tempA(9 downto 0); Ergebnis<=y; |
6 | when others => zplus <= z-1; |
7 | end case; |
8 | end process; |
Ja genau, das stelle ich durch die Simulation fest! Die Erweiterung der Sensitivliste hat leider nichts gebracht. Zusätzlich bei der Division mit Rest (z.B. 1000 durch 3) ergibt sich das falsche Ergebnis, das sich ständig je 10. Takt zwischen 166dec(0010100110 ist eigentlich 333dec um ein bit nach rechts verschoben) und 512dec(1000000000) wechselt. Wenn ich mein Code von Hand durchgehe dann soll alles stimmen, aber in der Realität.... Ich habe kein Plan:(
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.