Forum: FPGA, VHDL & Co. VHDL: Problem bei assert Anweisung


von Jonas B. (holocron)


Lesenswert?

Hallo,
ich musste einen 4 Bit Vergleicher in VHDL entwerfen und mit assert in 
der testbench das ganze prüfen, allerdings klappt das nicht so recht. Es 
kommt für eine bestimmte Belegung (der Fall a<b) assert zu Folge immer 
ein Fehler (obwohl alles stimmt) - wenn ich hingegen tatsächlich mit 
Absicht einen Fehler einbaue, ist nach assert alles richtig. Hat jemand 
eine Idee, woran das liegen könnte? Hier wäre ein Auszug der Testbench. 
Der vollständige Code ist im Link unten:
1
begin
2
TEST: entity forBitComperator port map(a, b, c1, c0);
3
  process
4
  begin
5
    for i in 0 to 2**4 loop
6
        for k in 0 to 2**4 loop
7
            a <= std_logic_vector(to_unsigned(i, 4));
8
            b <= std_logic_vector(to_unsigned(k, 4));
9
            
10
            if unsigned(a) > unsigned(b) then
11
              assert(c1 = '1' and c0 ='0')
12
              report "error";
13
             
14
             elsif unsigned(a) < unsigned(b) then
15
               assert(c1 = '0' and c0 ='1')
16
               report "error" ;
17
               
18
             elsif unsigned(a) = unsigned(b) then
19
               assert(c1 = '0' and c0 ='0')
20
               report "error" ;

https://www.edaplayground.com/x/4c2n

Danke im Voraus.

Grüße,
Holocron

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Jonas B. schrieb:
> for i in 0 to 2**4 loop
>         for k in 0 to 2**4 loop

spontant ist mir nur aufgefallen, dass du vermutlich 2**4-1 meinst.

for i in 0 to 3 zählt 0, 1, 2, 3 und 2**4 ist mehr als 4 bit.

von Jonas B. (holocron)


Lesenswert?

Oh stimmt, danke. Ein Problem wäre damit gelöst.
Aber es tritt immer noch eine Assert Meldung auf. Allerdings nur in 
Zeile 29, weswegen ich nicht wirklich sehe warum speziell Zeile 29 Ärger 
macht.

: Bearbeitet durch User
von Daniel__m (Gast)


Lesenswert?

Hi, ich denke, das hat etwas mit Deltazyklen zu tun. Der Prozess wird 
gestartet, sobald sich ein Signal ändert (zb a oder b). Zu diesem 
Zeitpunkt sind c0 und c1 noch nicht evaluiert, da die auch erst durch a 
bzw. b getriggert werden. Der Testprozess wird also (mind.) 2x 
durchlaufen und beim ersten mal noch mit alten c-Werten.

von Jonas B. (holocron)


Lesenswert?

Ah okay, das macht natürlich Sinn. Könnte ich das lösen, indem ich ein 
wait statement einbaue?
Hatte überlegt es vor der assert Zuweisung einzubauen, das hat 
allerdings nichts geholfen.

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


Angehängte Dateien:

Lesenswert?

Jonas B. schrieb:
> forBitComperator
Du kannst dort als Namen auch deutsche Worte verwenden, wenn du dir mit 
dem Englischen ein etwas schwer tust. Denn ein Vierbitkomparator heißt 
bei den Angelsachsen eher FourBitComparator (four von vier und 
comparator von compare).

> for i in 0 to 2**4 loop
16 passt nicht in 4 Bits, du hast da den gern verwendeten off-by-one 
Fehler produziert. Da gehört eigentlich ein "... to 2**4-1 loop" hin.

> report "error" ;
Wäre es nicht sinnvoll, dort für unterschiedliche Fehler auch 
unterschiedliche Fehlermeldungen auszugeben. Denn so kannst du ja den 
einen vom anderen Fehler gar nicht unterscheiden. Dass dann die Ports 
der Komparatoren nichtssagende einbuchstabige Namen haben, macht die 
Sache nicht wesentlich durchschaubarer. Und dass die Fehler im Prinzip 
auch keine Fehler sind, verbessert die Lage nicht grundlegend...

> Hat jemand eine Idee, woran das liegen könnte?
Ich würde da mal ein "wait" einbauen:
1
    for i in 0 to 2**4-1 loop
2
        for k in 0 to 2**4-1 loop
3
            a <= std_logic_vector(to_unsigned(i, 4));
4
            b <= std_logic_vector(to_unsigned(k, 4));
5
6
            wait for 0 ns;
7
8
            if unsigned(a) > unsigned(b) then
Denn in einem Prozess übernehmen Signale erst beim nächsten wait oder am 
Prozessende den jeweils zuletzt zugewiesenen Zustand. Ohne dieses wait 
wird der Prozess immer mit den Defaultwerten "0000" und "1011" 
durchlaufen.

Wenn man statt nur "error" auch noch die Werte der verglichenen Zahlen 
ausgibt, dann wird das klarer:
https://www.edaplayground.com/x/2cPn

: Bearbeitet durch Moderator
von Jonas B. (holocron)


Lesenswert?

Hallo,
danke für das ausführliche Feedback, ich hab dementsprechend meinen Code 
ein wenig angepasst. Allerdings bekomme ich nach wie vor die assert 
Meldungen, aber sieht für mich sehr danach aus, als wäre mein VHDL Code 
fehlerhaft (muss nur noch finden, wo er gescheitert ist).

: Bearbeitet durch User
von Jonas B. (holocron)


Lesenswert?

Ich bin nochmal den Code durchgegangen und es war tatsächlich ein Fehler 
drin, jetzt ist alles korrekt. Assert zu Folge sind allerdings jetzt 
alle 256 Eingangsbelegungen falsch (was natürlich nicht korrekt ist, da 
ich von Hand ein paar simuliert hab). Die Testbench ist auch 
entsprechend der Hinweise korrigiert. Ist vielleicht playground einfach 
defekt/hat einen Server Bug beim simulieren?
1
begin
2
TEST: entity forBitComperator port map(a, b, c1, c0);
3
  process
4
  begin
5
    for i in 0 to 2**4-1 loop --a
6
        for k in 0 to 2**4-1 loop --b
7
            a <= std_logic_vector(to_unsigned(i, 4));
8
            b <= std_logic_vector(to_unsigned(k, 4));
9
10
            wait for 0 ns;
11
12
            if i > k then
13
              assert(c1 = '1' and c0 = '0')
14
              report "error " & integer'image(i) 
15
                     & ">" & integer'image(k);
16
(...)
17
end;

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


Lesenswert?

Jonas B. schrieb:
> Assert zu Folge sind allerdings jetzt alle 256 Eingangsbelegungen falsch
Was machen denn überhaupt diese nicht näher beschriebenen c0 und c1?

Und warum packst du die Abfragen nicht einfach in 3 Abfragen ohne die if 
und else?
So etwa:
1
              assert(i>k and c1='1' and c0='0')
2
                 report "error at " & integer'image(i) & ">" & integer'image(k);
3
4
              assert(i<k and c1='0' and c0='1')
5
                 report "error at " & integer'image(i) & "<" & integer'image(k);

: Bearbeitet durch Moderator
von Jonas B. (holocron)


Lesenswert?

c0 und c1 sind die Outputs meines Schaltkreises. Die Spezifikation ist, 
dass man zwei 4-Bitwörter a,b hat und die Schaltung 10 (also c1=1, c0=0) 
ausgibt, falls a > b; 01 (c1=0, c0=1) falls a < b und 00 (c1=c0=0) falls 
a=b gilt.

Oh das geht, war mir nicht sicher ob das korrekt ist. Danke für den 
Tipp.

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


Angehängte Dateien:

Lesenswert?

Jonas B. schrieb:
> Oh das geht, war mir nicht sicher ob das korrekt ist.
Es geht schon, ist aber hier nicht so richtig zielführend.

Jonas B. schrieb:
> Assert zu Folge sind allerdings jetzt alle 256 Eingangsbelegungen falsch
Das liegt noch am "wait for 0 ns". Da muss offenbar mehr Zeit rein, dass 
der Simulator seine Deltazyklen abhandeln kann.

> (was natürlich nicht korrekt ist, da ich von Hand ein paar simuliert hab).
Da hast du scheinbar ein "glückliches Händchen" gehabt. Mit einem "wait 
for 1 ns" werden jetzt "nur" noch etwa die Hälfte der Abfragen 
angemäkelt. Trotzdem funktioniert der Komparator nicht annähernd so gut, 
wie du es erwartest:
https://www.edaplayground.com/x/5DSP

von Jonas B. (holocron)


Angehängte Dateien:

Lesenswert?

Hallo,
oh stimmt, ja das war noch eine ältere Version vom Code, da war die 
logische Funktion für c1 und c0 falsch. Jetzt funktioniert alles, vielen 
Dank für die Hilfe.

Gibt es irgendeine Regel, wie groß man am besten die wait Zyklen setzen 
sollte?

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Jonas B. schrieb:
> Gibt es irgendeine Regel, wie groß man am besten die wait Zyklen setzen
> sollte?

In der Simulation deiner Testbench dürfte das egal sein.

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


Lesenswert?

Mampf F. schrieb:
> In der Simulation deiner Testbench dürfte das egal sein.
Ich würde auf jeden Fall mehr als "0 ns" nehmen, damit die Deltazyklen 
alle abgearbeitet sind...

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.