Forum: FPGA, VHDL & Co. simple Addition zweier bit_vector(2 downto 0)


von Richard K. (richardk)


Lesenswert?

Hallo Leute

Ich wollte in VHDL zwei 3Bit Zahlen addieren.
Der Resultierende Vektor muss also 4Bit aufweisen damit
nichts verloren geht.

Hier mein Code:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
-------------------------------------------------------------------------------
5
6
entity unsigdAdd is
7
8
  port (
9
    signal Din1 : in  bit_vector(2 downto 0);  -- add value 1
10
    signal Din2 : in  bit_vector(2 downto 0);  -- add value 2
11
    signal summ : out bit_vector(2 downto 0)   -- added summ
12
    );
13
14
end unsigdAdd;
15
-------------------------------------------------------------------------------
16
17
architecture behav of unsigdAdd is
18
19
  signal temp : unsigned(2 downto 0);   -- internal temp
20
21
  
22
begin  -- behav
23
  
24
  temp <= unsigned(to_stdlogicvector(Din1)) + unsigned(to_stdlogicvector(Din2));
25
26
  summ <= to_bitvector(std_logic_vector(temp));
27
  
28
end behav;

Mache ich nun mein "summ" 4Bit breit, dann meckert
Modelsim. So wie im obrigen Code verliere ich jedoch
das 4te Bit :-(

Wie macht man so eine einfache
Addition korrekt?

Das selber Problem begegnet mir bei der
Multiplikation 3x3Bit = 9Bit

Gruss Richard

von Richard K. (richardk)


Lesenswert?

Hallo Leute

Sacht mal..  mein Problem an sich, habe ich nun gelöst.
Anbei die Lösung.

Das ist ja ziemlich hirnverbrannt, muss man das wirklich so
umständlich realisieren?

In der Literatur wird einem stets geraten möglichst wo es nur
geht bit und bit_vector zu verwenden. Das, ist aus meiner
Sicht die Konsequenz.

1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
-------------------------------------------------------------------------------
6
7
entity unsigdAdd is
8
9
  port (
10
    signal Din1 : in  bit_vector(2 downto 0);  -- add value 1
11
    signal Din2 : in  bit_vector(2 downto 0);  -- add value 2
12
    signal summ : out bit_vector(3 downto 0)   -- added summ
13
    );
14
15
end unsigdAdd;
16
17
-------------------------------------------------------------------------------
18
19
architecture behav of unsigdAdd is
20
21
  signal intVer : integer range 0 to 15;  -- internal temp
22
  
23
  
24
begin  -- behav
25
  
26
  intVer <= to_integer(unsigned(to_stdlogicvector(Din1))) + to_integer(unsigned(to_stdlogicvector(Din2)));
27
28
  summ <= to_bitvector(std_logic_vector(to_unsigned(intVer, summ'length)));
29
  
30
end behav;

Gruss Richard

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


Lesenswert?

> signal summ : out bit_vector(3 downto 0)
Kein Mensch verwendet den Typ bit_vector an der Schnittstelle.

Nimm std_logic_vector, dann sparst du dir eine Cast-Ebene.
Und mit Unsigned kannst du auch rechnen.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity unsigdAdd is
6
  port (
7
    signal Din1 : in  std_logic_vector(2 downto 0);  -- add value 1
8
    signal Din2 : in  std_logic_vector(2 downto 0);  -- add value 2
9
    signal summ : out std_logic_vector(3 downto 0)   -- added summ
10
    );
11
end unsigdAdd;
12
13
architecture behav of unsigdAdd is
14
begin  -- behav
15
  summ <= std_logic_vector(unsigned(Din1)+unsigned(Din2));
16
end behav;

> Das ist ja ziemlich hirnverbrannt, muss man das wirklich so
> umständlich realisieren?
Durch die strenge Typprüfung macht es Sinn, sich um die Schnittstellen 
zu kümmern, und dort geeignete Typen zu verwenden. Ganz einfach wärs so:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity unsigdAdd is
6
  port (
7
    signal Din1 : in  unsigned(2 downto 0);  -- add value 1
8
    signal Din2 : in  unsigned(2 downto 0);  -- add value 2
9
    signal summ : out unsigned(3 downto 0)   -- added summ
10
    );
11
end unsigdAdd;
12
13
architecture behav of unsigdAdd is
14
begin  -- behav
15
  summ <= Din1 + Din2;
16
end behav;
Dann hat auch die Entity ihren Namen verdient ;-)

von Richard K. (richardk)


Lesenswert?

Hallo Lothar

Vielen Dank für deinen Antwort.

Mit deiner Antwort habe ich nun ein wenig an
mir selbst gezweifelt, ich dachte mindestens deine
erste Version mit:
1
summ <= std_logic_vector(unsigned(Din1)+unsigned(Din2));

Hätte ich bereits schon selbst einmal getestet.
Nun habe ich beide deiner Versionen noch ausprobiert.
Entweder habe ich einen zweiten Fehler in der Toolchain
oder deine beiden Varianten funktionieren nicht?

Ich habe meine lauffähige Version an deine 1. angepasst.

Altera Quartus II (Standart Synthese Altera) meldet:
"Error expression has 3 elements, but must have 4 elements"

Und nein Quartus meint damit nicht etwa "summ" sondern die
beiden Din's. Passe ich summ auf (2 downto 0) an funktionierts.
Dann stimmt aber die Addition nicht mehr. 3bit vec + 3bit vec = 4bit vec

Nun gut...

Zur Sicherheit habe ich noch Synplify befragt:
"Error Width mismatch, location has width 4, value 3"

Dann konnte ich gar nix mehr glauben...
Zur Sicherheit habe ich Copy & Paste deine überarbeitete Version
aus dem Forum genommen. Fehlanzeige, auch deine zweite
Variante mit unsigned definierten Port's brachte das selbe
Resultat.

Hast du noch eine Idee, was da ev. in der Toolchain
fehlerhaft sein könnte?

Gruss Richard

PS. Xilinx ISE meldet keinen Error, nur eine Warning.
    Schlimm ist jedoch, das im RTL der summ Vector an GND
    angebunden wird! :-( Dann lieber ein klarer Error.

von Duke Scarring (Gast)


Lesenswert?

Laut
http://www.eda.org/comp.lang.vhdl/FAQ1.html#4.8.1
1
unsigned add; length of result = max(length of 1st par, length of 2nd par)

Also musst Du noch ein Bit dranhängen, damit es klappt:
1
summ <= std_logic_vector(unsigned("0" & Din1) + unsigned("0" & Din2));

Duke

von Gast (Gast)


Lesenswert?

dafür gibt's die Funktion "resize" !

von Richard K. (richardk)


Lesenswert?

Hallo Leute

1
summ <= std_logic_vector(unsigned("0" & Din1) + unsigned("0" & Din2));

Diese Verion gefällt mir!

Danke auch für den Link...


Gruss Richard

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


Lesenswert?

> unsigned add; length of result = max(length of 1st par, length of 2nd par)
Demanch reicht also auch die Erweiterung nur eines Vektors:
1
summ <= std_logic_vector(unsigned('0' & Din1) + unsigned(Din2));
Ausprobiert:  Es geht ;-)

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.