Hi,
wie schreibt man am besten seinen Testbench? Ich bin langsam am
verzweifeln. Den TB sequential machen wie: assert(), wait for ...,
maches jenes, assert(), wait ... klappt nur bei einfachen Dingen imo.
Bei komplizierten, sequentiell zeitlichen Zusammenhängen wird's
schnell hässlich, wenn man dann noch etwas ändert war ist die ganze
Mühe u.U. futsch, da die sorgsam eingefügten waits nicht mehr an der
Stelle stehen, wo sie sollten.
Mit reset zB. bin ich gut klargekommen mit
jetzt wollte ich das auch mal für Signalzuweisungen machen, und später
für asserts, aber es klappt leider nicht:
1
architecturebehavioroftb_edge_triggeris
2
constantPERIOD:time:=10ns;
3
signalclk:std_logic:='0';
4
...
5
typeedge_tis
6
record
7
at:natural;
8
rise:std_logic_vector(7downto0);
9
fall:std_logic_vector(7downto0);
10
mask:std_logic_vector(7downto0);
11
endrecord;
12
typeedges_tisarray(8downto0)ofedge_t;
13
signaledges:edges_t;
14
begin
15
uut:...
16
17
cond_setup_proc:process
18
begin
19
edges(0).at<=0;
20
edges(0).rise<=b"0000_0000";
21
edges(0).fall<=b"0000_0000";
22
edges(0).mask<=b"0000_0000";
23
24
edges(1).at<=1;
25
edges(1).rise<=b"0000_0001";
26
edges(1).fall<=b"0000_0000";
27
edges(1).mask<=b"0000_0001";
28
...
29
endprocess;
30
31
tb:process
32
begin
33
reset<='1',
34
'0'after1*PERIOD,
35
'1'after3*PERIOD,
36
'0'after4*PERIOD,
37
'1'after6*PERIOD,
38
'0'after7*PERIOD;
39
40
foriinedges'lowtoedges'highloop
41
-- HIER SOLLTE DIE SIGNALZUWEISUNG REIN, geht das?
42
endloop;
43
44
-- und hier klappt es einfach nicht
45
trigger_rising<=edges(0).rise,
46
edges(1).riseafteredges(1).at*PERIOD;
47
48
...
49
endprocess;
50
51
end;
Bei letzter Variante kommt nach run sogar:
Delay in signal assignment is not ascending.
was ich nicht nachvollziehen kann, da at hierbei 1 ist. Die
Signalzuweisung wird auch einfach nicht durchgeführt.
Viele Grüße
Olaf
so, jetzt wollte ich mal ganz clever sein, und einzelne Tests in einen
process packen. Allerdings zerrren jetzt die einzelnen procs
(reset_proc und test_proc) untereinander an den Signalen, hier konkret
trigger_xxxx:
1
architecturebehavioroftb_edge_triggeris
2
constantPERIOD:time:=10ns;
3
signalclk:std_logic:='0';
4
signalreset:std_logic:='0';
5
...
6
signaltrigger_rise:std_logic_vector(7downto0);
7
signaltrigger_fall:std_logic_vector(7downto0);
8
signaltrigger_mask:std_logic_vector(7downto0);
9
10
signalmatch:std_logic:='0';
11
begin
12
13
uut:entity...
14
15
clock_proc:...
16
17
probe:...
18
19
...
20
21
reset_block:block
22
begin
23
reset_proc:process(reset)
24
begin
25
if(reset='1')then
26
trigger_rise<=b"0000_0000"afterPERIOD;
27
trigger_fall<=b"0000_0000"afterPERIOD;
28
trigger_mask<=b"0000_0000"afterPERIOD;
29
endif;
30
endprocess;
31
time_reset_proc:process
32
begin
33
reset<='1',
34
'0'after1*PERIOD,
35
'1'after3*PERIOD,
36
'0'after4*PERIOD,
37
'1'after6*PERIOD,
38
'0'after7*PERIOD;
39
wait;
40
endprocess;
41
endblock;
42
43
test_proc:process
44
constantDELAY:integer:=1;
45
begin
46
trigger_rise<=b"0000_0001"afterDELAY*PERIOD;
47
trigger_fall<=b"0000_0000"afterDELAY*PERIOD;
48
trigger_mask<=b"0000_0001"afterDELAY*PERIOD;
49
wait;
50
endprocess;
51
52
end;
Wie bekomme ich das nun wieder korrekt hin? Da Modelsim kein Schematics
anzeigt, habe ich keine Ahnung, was 'draus gemacht wurde.
Innerhalb der Tests wollte ich dann mit assert die Ergebnisse testen
(evtl. muss ich auch einen block 'draus machen mit "stimuli" und
"check").
Viele Grüße
Olaf
Man kann die Frage bzgl. obigen Ansatzes auch vereinfachen:
Wie kann ich in VHDL (nicht Target spezifisch) die event list (angelegt
mit
1
foo<='0','1'afterX,'0'afterY....
) in verschiedenen processes erweitern; tja, ohne die alten events zu
überschreiben bzw. ohne Kolisionen durch die Erweitung in den einzelnen
processes?
Es taucht öfters mal in den fremden sources das keyword "transport"
auf - dies hilft aber auch nicht (wenn ich es recht verstanden habe
verschiebt es ja nur die events).
Viele Grüße
Olaf
@ope
schreib doch mal, wie Du Dir den Test des LAs vorstellst!
Nicht als VHDL, sondern verbal.
Ich könnte mir vorstellen, dass man für einzelne Module
jeweils eine TB anlegt und dann erstmal ein Modul testet.
Am Schluss gibt es eine TB für das Gesamtdesign.
Da gibt es nun mehrere Möglichkeiten. Entweder man macht
für jeden Test ein eigenes File (Stimuli_test1.vhd,
stimuli_test2.vhd ...) oder man packt eben alles in eine TB
oder ...es gibt zig weitere Varianten : TCL-Script...)
Für eine Serie von Tests würde ich mir ein Signal nehmen, dass
meine Test-Nummer speichert, z.B.:
type TEST_TYPE is (test1, test2 ...);
Dann könnte man die Testnummer entweder basierend auf der Zeit
oder auf Events hochzählen, je nachdem, wie der Testablauf
sein soll.
Alle Prozesse, die am Test beteiligt sind, können sich nun
auf dieses Signal synchronisieren. Z.B. könnte man alle Parameter
die zu Beginn des Tests gesetzt werden sollen abh. von der Test-
nummer setzen
case test_nummer is
when test_1 => Input_Params <= Param_Set1;
when test_2 => ...;
Natürlich dürfen verschiedene Prozesse nicht auf 1 Signal
zugreifen, aber dafür sehe ich auch keinen Grund.
Vielleicht hilft Dir auch eine Statemachine in der Testbench.
So kompliziert kann der LA doch nicht sein, dass man dafür
keine einfache TB schreiben kann.
>Ich könnte mir vorstellen, dass man für einzelne Module>jeweils eine TB anlegt und dann erstmal ein Modul testet.>Am Schluss gibt es eine TB für das Gesamtdesign.
so handhabe ich es derzeit auch - jede entity (zB. trigger_edge,
trigger_pattern) hat ihren eigenen Testbench TB_xyz, wobei ich einem
Bottom-up Entwurf fröne. Somit bekommen die Top entity (zB. trigger,
instanziert trigger_edge, trigger_pattern u.a.) einen weiteren, eigenen
TB.
Exemplarisch versuche ich es mal mit dem edge_trigger, da dazu schon
etwas in vhdl hier steht. Der Test geht zB. auf
* die Erkennung von rising edge vom sample bit0 in bitmuster (bm) #0,
anschl.
* Erkennung falling edge sample bit 3 in bm #1
* Erkennung rise/falling edge sample bit 2,3 in bm #2
* Erkennung any edge edge sample bit 5 in bm #3
* Erkennung rise/falling/any edge sample bit 0,2,6,5,8 in bm #4
Somit habe ich versch. Kombis durch. Das Bitmuster generiert derzeit
einfach nur ein counter (d.h. ist einfach eine Binärzahl), der
TB_trigger läuft mit einem prbs signal.
clock läuft hoch und bietet mir immer neue pattern, auf die ich
triggere - eben sequentiell. Das heisst, das Timing bzw. die
Reihenfolge wie ich den vhdl TB schreibe ist sehr starr und unflexibel.
Eine Änderung darin und schon stimmt es nicht mehr und das assert (will
nicht immer waves anschauen) ist an der falschen Stelle - das ist mir
nun zu oft passiert.
Daher die Idee, diese fünf Bitmuster jeweils einzeln als absolute Zeit
in einem process anzugeben - dies geschieht ja bei der event Vergabe
mit after ...
>Natürlich dürfen verschiedene Prozesse nicht auf 1 Signal>zugreifen, aber dafür sehe ich auch keinen Grund.
Dies ist der Grund für meinen Ärger oben. Anscheinend gehts wirklich
nicht, daher sind Alternativen gesucht.
>schreib doch mal, wie Du Dir den Test des LAs vorstellst!>Nicht als VHDL, sondern verbal.
OK, also. In einer Stelle, process, file, entity setze ich jeweils die
5 Testkonditions, zB cond_1:
1
trigger_rise<=b"0000_1010";
2
trigger_fall<=b"0000_1001";
3
trigger_mask<=b"0000_1011";
4
time:=30ns;
Diese signale werden zur absoluten Zeit (t0+time ns) aktiv. Damit kann
ich zu jedem beliebigen Zeitpunkt meine trigger pattern setzen. Das uut
triggert zB. mit steigender clk Flanke und setzt den output match auf
'1' mit der fallenden Flanke clk. Mit der nächsten steigenden soll
assert prüfen, ob es true ist - also genau einen Taktzyklus später.
Anschliessend muss ich das uut wieder reseten um den Urzustand wieder
herzustellen, oder div. enable signal zu setzten und kann mit der
nächsten cond weiter machen (derweil mein bm generator ja weiter zählt
und andere bitmuster liefert).
Ziel ist also, diese 5 mini TB, bei denen es einzeln geschrieben und
gestartet keine Probleme geben würde, in einem grossen zu verpacken, so
dass ich weitere Testfälle vorne oder hinten anhängen kann.
Je mehr entities ich in den Tops instanziert habe, desto komplizierter
werden die Testfälle, da nun zB. "edges match, pattern matches for 5
clk cycles" etc. als cond. auftreten können. Alles kann ich nicht
testen, aber zumindest das Offensichtliche.
Viele Grüße
Olaf