Forum: FPGA, VHDL & Co. [VHDL] Subtrahieren in der FOR-Schleife


von Tandrael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

unsere Arbeit an der ALU ist beinahe beendet, die Addition wurde 
inzwischen mit einer FOR-Schleife realisiert, und das Ergebnis stimmt 
nun. Das einzige Problem ist unsere Subtraktion, die im Zweierkomplement 
stattfinden soll. Die Umrechnung ins Zweierkomplement klappt dabei 
problemlos, plötzlich funktioniert jedoch die Addition nicht. Statt 
einfach das Zweierkomplement von B + 000....0000 zu rechnen und somit 
unverändert das Zweierkomplement zu übernehmen, erhalten wir undefined. 
Wo liegt das Problem?


1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
library UNISIM;
6
use UNISIM.VComponents.all;
7
8
entity ALU is
9
    Port ( A : in  STD_LOGIC_VECTOR (31 downto 0);
10
           B : in  STD_LOGIC_VECTOR (31 downto 0);
11
           F : in  STD_LOGIC_VECTOR (2 downto 0);
12
           Y : out  STD_LOGIC_VECTOR (31 downto 0);
13
           Z : out  STD_LOGIC;
14
           Clock : in  STD_LOGIC
15
  );
16
  signal O: STD_LOGIC_VECTOR(32 downto 0) := (others => '0');
17
  signal Bh: STD_LOGIC_VECTOR(31 downto 0);
18
end ALU;
19
20
architecture Behavioral of ALU is
21
begin
22
  process (A, B, F, O, Clock)
23
  begin
24
    Z <= '0';
25
    case F is
26
      when "000" =>
27
        Y <= A AND B;
28
      when "001" =>
29
        Y <= A XOR B;
30
      when "010" =>
31
-- A + B
32
        for k in 0 to 31 loop
33
          if k = 0 then
34
            Y(k) <= A(k) XOR B(k);
35
            O(k) <= A(k) AND B(k);
36
          else
37
            Y(k) <= A(k) XOR B(k) XOR O(k-1);
38
            O(k) <= (A(k) AND B(k)) OR ((A(k) XOR B(k)) AND O(k-1));
39
          end if;
40
        end loop;
41
      when "100" =>
42
        Y <= A AND NOT B;
43
      when "101" =>
44
        Y <= A XOR NOT B;
45
      when "110" =>
46
-- A - B
47
        -- Umdrehen von B
48
        for k in 0 to 31 loop
49
          Bh <= NOT(B);
50
        end loop;
51
        -- Umgedrehtes B + 1
52
        for k in 0 to 31 loop
53
          if k = 0 then
54
            Bh(k) <= Bh(k) XOR '1';
55
            O(k) <= Bh(k) AND '1';
56
          else
57
            Bh(k) <= Bh(k) XOR O(k-1);
58
            O(k) <= Bh(k) AND O(k-1);
59
          end if;
60
        end loop;
61
        -- A - B negiert
62
        for k in 0 to 31 loop
63
          if k = 0 then
64
            Y(k) <= A(k) XOR Bh(k);
65
            O(k) <= A(k) AND Bh(k);
66
          else
67
            Y(k) <= A(k) XOR Bh(k) XOR O(k-1);
68
            O(k) <= (A(k) AND Bh(k)) OR ((A(k) XOR Bh(k)) AND O(k-1));
69
          end if;
70
        end loop;
71
      when "111" =>
72
-- A - 1
73
        for k in 0 to 31 loop
74
          if k = 0 then
75
            Y(k) <= A(k) XOR '1';
76
            O(k) <= A(k) AND '1';
77
          else
78
            Y(k) <= A(k) XOR '1' XOR O(k-1);
79
            O(k) <= (A(k) AND '1') OR ((A(k) XOR '1') AND O(k-1));
80
          end if;
81
        end loop;
82
      when others =>
83
    end case;
84
  end process;
85
end Behavioral;

von MaWin (Gast)


Lesenswert?

Meinst du nicht, daß hier

 for k in 0 to 31 loop
          Bh <= NOT(B);
        end loop;

die Verwendung von k fehlt ?

von P. K. (pek)


Lesenswert?

"Bh" nicht in der Sensitivity-Liste?

Und dann erst noch keine Default-Zuweisung, da gibt's ein Latch bei der 
Synthese.

von Tandrael (Gast)


Lesenswert?

MaWin schrieb:
> Meinst du nicht, daß hier
>
>  for k in 0 to 31 loop
>           Bh <= NOT(B);
>         end loop;
>
> die Verwendung von k fehlt ?

Alles klar, danke, da ist die Loop überflüssig, ändert aber nichts am 
Fehler.

Peter K. schrieb:
> "Bh" nicht in der Sensitivity-Liste?
>
> Und dann erst noch keine Default-Zuweisung, da gibt's ein Latch bei der
> Synthese.

Bh in die sensitivitylist einzutragen bringt nichts, das mit der 
Default-Zuweisung habe ich leider nicht ganz verstanden.

von P. K. (pek)


Lesenswert?

Tandrael schrieb:
> Bh in die sensitivitylist einzutragen bringt nichts, das mit der
> Default-Zuweisung habe ich leider nicht ganz verstanden.

Wenn Bh nicht in jedem Ast des Prozesses zugewiesen wird, ergibt sich 
ein nicht getakteter Speicher (= Latch).

wenn Du das "Bh <= NOT(B);" aus der Bedingung (case) rausnimmst und 
gleich nach dem "begin" des Prozesses einfügst, ist das mal gelöst.

Weil Du aber ein Signal zuweist (welches simulativ erst beim nächsten 
"Durchgang"/Tick des Prozesses ändert), muss "Bh" in die 
Sensitivity-Liste.

von Tandrael (Gast)


Lesenswert?

Peter K. schrieb:
> Tandrael schrieb:
>> Bh in die sensitivitylist einzutragen bringt nichts, das mit der
>> Default-Zuweisung habe ich leider nicht ganz verstanden.
>
> Wenn Bh nicht in jedem Ast des Prozesses zugewiesen wird, ergibt sich
> ein nicht getakteter Speicher (= Latch).
>
> wenn Du das "Bh <= NOT(B);" aus der Bedingung (case) rausnimmst und
> gleich nach dem "begin" des Prozesses einfügst, ist das mal gelöst.
>
> Weil Du aber ein Signal zuweist (welches simulativ erst beim nächsten
> "Durchgang"/Tick des Prozesses ändert), muss "Bh" in die
> Sensitivity-Liste.

Das Bh in die Sensitivitylist einzutragen haben wir versucht, es hat 
jedoch das Problem nicht gelöst.

von MaWin (Gast)


Lesenswert?

> Alles klar, danke, da ist die Loop überflüssig,
> ändert aber nichts am Fehler.

Nö, das war nur der erste Fehler, in dem Stil geht es weiter:

die

     for k in 0 to 31 loop
          if k = 0 then
            Bh(k) <= Bh(k) XOR '1';
            O(k) <= Bh(k) AND '1';
          else
            Bh(k) <= Bh(k) XOR O(k-1);
            O(k) <= Bh(k) AND O(k-1);
          end if;
        end loop;


kann doch nicht funktionieren, welches Bh(k) soll denn nach dem Takt 
gemeint sein, und woher soll die O(k-1) vor dem Takt kommen ?

Mir scheint, ihr habt die sequentielle Denkweise eines FOR aus einer 
Programmiersprache im Kopf, und nicht die parallele Anordnung von 
Funktionsblöcken in VHDL, macht also den typischen VHDL Denkfehler eines 
Informatikers statt eines Etechniks.

von Tandrael (Gast)


Lesenswert?

MaWin schrieb:
> Mir scheint, ihr habt die sequentielle Denkweise eines FOR aus einer
> Programmiersprache im Kopf, und nicht die parallele Anordnung von
> Funktionsblöcken in VHDL, macht also den typischen VHDL Denkfehler eines
> Informatikers statt eines Etechniks.

Das kann sehr gut sein, was würde das Problem denn lösen?

von Matthias (Gast)


Lesenswert?

Tandrael schrieb:
> Peter K. schrieb:
>> "Bh" nicht in der Sensitivity-Liste?
>>
>> Und dann erst noch keine Default-Zuweisung, da gibt's ein Latch bei der
>> Synthese.
>
> Bh in die sensitivitylist einzutragen bringt nichts, das mit der
> Default-Zuweisung habe ich leider nicht ganz verstanden.

Ohne Default-Zuweisung denkt er sich "Ok, Werte behalten". Da es sich um 
reine Kombinatorik handelt (keine Clock ala rising_edge), baut er ein 
Latch, das bestimmt nicht beabsichtigt ist...

Tandrael schrieb:
> entity ALU is
>     Port ( A : in  STD_LOGIC_VECTOR (31 downto 0);
>            B : in  STD_LOGIC_VECTOR (31 downto 0);
>            F : in  STD_LOGIC_VECTOR (2 downto 0);
>            Y : out  STD_LOGIC_VECTOR (31 downto 0);
>            Z : out  STD_LOGIC;
>            Clock : in  STD_LOGIC
>   );
>   signal O: STD_LOGIC_VECTOR(32 downto 0) := (others => '0');
>   signal Bh: STD_LOGIC_VECTOR(31 downto 0);
> end ALU;

Das auch Signale in der Entity vorkommen, ist mir neu.

"A+B" kannst du in einer Zeile berechnen. Auch Overflow & andere Flags 
kannst du trotzdem noch berechnen. Im Falle vom Overflow genügt es ein 
angehängtes Bit im Ergebnis mehr zu nehmen.

Bei "A-B" gilt ähnliches: Geht auch in ein,zwei Zeilen mit ggf 
notwendiger Erweiterung bzgl Flags(N,Z,C,O,..):
1
architec...
2
3
 pSUB : process(A,B,...
4
  variable v_zweierkomp : std_logic_vector(31 downto 0) := (others => '0');
5
  variable v_tmp : std_logic_vector(32 downto 0) := (others => '0');
6
 begin
7
  v_zweierkomp := std_logic_vector(unsigned(not B) + 1);
8
  v_tmp := ('0' & A) + ('0' & v_zweierkomp);   -- und eben Anpassung, dass     Flags passend gesetzt werden
9
 end process;
10
11
 Y <= v_tmp(31 downto 0);
12
 O <= v_tmp(32);
13
14
end

In der FOR-Schleifen müsstest variablen verwenden, da die den Wert 
gleich annehmen.

LG

von Tandrael (Gast)


Lesenswert?

Matthias schrieb:
> "A+B" kannst du in einer Zeile berechnen. Auch Overflow & andere Flags
> kannst du trotzdem noch berechnen. Im Falle vom Overflow genügt es ein
> angehängtes Bit im Ergebnis mehr zu nehmen.
>
> Bei "A-B" gilt ähnliches: Geht auch in ein,zwei Zeilen mit ggf
> notwendiger Erweiterung bzgl Flags(N,Z,C,O,..):

Das haben wir versucht, mit unsigned und was weiß ich nicht allem. Ging 
bei uns nie, deswegen die Forschleifen. Unser Programm hat ja auch schon 
mal komplett funktioniert, die Iverflows etc. waren kein Problem, nur 
ging die einfache Addition Z = A + B nicht, selbst A = A + 1 ging nicht. 
Andere Nutzer haben unser Programm über ALDEC ausprobiert, ging, aber 
bei uns kam immer Fehler raus. Nach der ersten Addition 0000....0000X, 
und danach immer nur XXXX....XXXX. Keine Ahnung, woran das liegt.

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


Lesenswert?

Dass das Bh ein Latch beschreibt ist hier unwichtig, denn für den zu 
betrachtenden Fall ist dieses Latch transparent...

Tandrael schrieb:
> Das Bh in die Sensitivitylist einzutragen haben wir versucht, es hat
> jedoch das Problem nicht gelöst.
Stochern im Nebel.

Leider ist diese (m.E. unsinnige) Beschreibung genau das Beispiel, in 
dem eine Variable angebracht wäre. Denn mit solchen Zuweisungen wie
1
   O(k) <= (A(k) AND B(k)) OR ((A(k) XOR B(k)) AND O(k-1));
muss der Prozess evtl. nach jedem einzelnen Schleifendurchlauf neu 
auferufen werden...

MaWin schrieb:
> kann doch nicht funktionieren, welches Bh(k) soll denn nach dem Takt
> gemeint sein, und woher soll die O(k-1) vor dem Takt kommen ?
Da ist weit&breit kein Takt im ganzen Design. Der Clock steht nur zur 
Verwirrung da (und sorgt für seltsames Verhalten)...

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.