Hi!
Ich hänge gerade mal wieder an folgendem Problem:
Ich habe mit "generate" mehrere Instanzen von einem Modul erzeugt:
1
// Irgendwo im Code
2
parameter N=4;
3
integer i;
4
wire reset_n[i];
5
6
generate
7
for(i=0; i<N; i=i+1) begin: generatedModules
8
meinModul meinModulInstanz
9
(
10
.reset_n_i (reset_n[i]),
11
...
12
);
13
end
14
endgenerate
Jetzt möchte ich in der Testbench auf verschiedene Signale von den
Instanzen zugreifen, zum Beispiel das reset_n_i mit force auf einen Wert
festlegen (oder Register lesen, egal). Nachdem ich N als Parameter auch
in der Testbench variabel lassen möchte, würde ich das mit einer
for-loop machen:
1
// Testbench
2
parameter N=4;
3
integer k;
4
5
initial begin
6
...
7
for(k=0; k<N; k=k+1) begin
8
force generatedModules[k].meinModulInstanz.reset_n_i = 1'b0;
9
// Verschiedene Tests
10
release ...;
11
end
12
end
Mein Simulator bringt mir aber folgende Meldung:
"Illegal operand for constant expression" und deutet auf das k in
"generatedModules[k].meinModulInstanz.reset_n_i".
Gibt es einen Weg das zu umgehen? Wie kann man das sauber lösen? Ich
möchte nicht alle einzeln ausschreiben müssen.
hiall schrieb:> auch generate verwenden?
Dann müsste ich das ja so schreiben:
1
genvar k;
2
3
generate
4
for(k=0; k<N; k=k+1) begin
5
initial begin
6
...
7
force generatedModules[k].meinModulInstanz.reset_n_i = 1'b0;
8
// Verschiedene Tests
9
release ...;
10
end
11
end
12
endgenerate
Wenn ich das richtig verstanden habe, würde dass dann praktisch N-mal
diesen inital-Block erzeugen.
Nachdem ich aber mit dem "// Verschiedene Tests" eben noch mehrere
Testfälle nacheinander abfragen will wäre das suboptimal. In dem Fall
müsste ich mir noch etwas einfallen lassen, dass die erzeugten
initial-Blöcke immer zur richtigen Zeit starten und nicht parallel
loslaufen. Oder übersehe ich da etwas?
Ich habe mich vielleicht etwas missverständlich ausgedrückt: Der Punkt
ist dass ich erst das reset_n_i von k=1 setzen möchte und wenn ich damit
alle Testfälle beendet habe, danach erst zum nächsten fortschreiten
möchte. Also ungefähr so:
0. k=0
1. force reset von Instanz k
2. Test
3. Warte auf Testende
4. k=k+1
5. k<N? Springe zu 1. : Ende
Ist reset_n_i ein signal? Eventuell mit reset_n[i] verwechselt das ein
signal ("wire") ist?
Für mich als verilog beinahe analpabet sieht das nach einem Port aber
nicht nach einem Signal aus. Üblicherweise klemmt man an jeden Port im
generate ein signal, und das signal kann dann mit force beeinflußt
werden.
MfG,
Sergej Schätzer schrieb:> Ist reset_n_i ein signal? Eventuell mit reset_n[i] verwechselt das ein> signal ("wire") ist?>> Für mich als verilog beinahe analpabet sieht das nach einem Port aber> nicht nach einem Signal aus. Üblicherweise klemmt man an jeden Port im> generate ein signal, und das signal kann dann mit force beeinflußt> werden.>> MfG,
Das ist ein Port - spielt aber meiner Meinung nach keine Rolle.
Beispielsweise funktioniert das, wie ich es erwarte:
1
force generatedModules[0].meinModulInstanz.reset_n_i = 1'b0;
Der Ausdruck erfordert eine Konstante für generatedModules[k], dein k
ist aber keine Konstante. Probier mal k als
1
parameter integer k;
zu definieren. Dann wäre vermutlich deine Fehlermeldung weg, aber eine
andere dafür da weil du das konstante k ändern willst.
Ich hab gerade in den Verilog2001 Standard geschaut, der sagt dass man
genvar im generate Block als variable verwenden soll, daher sollte
eigentlich dein generate im code schon einen Fehler werfen. Vielleicht
ist aber der Simulator auch grosszügig bei der auslegung des
Standards... Hilft dir aber auch nix :-)
So, viel erzählt und noch ne blöde Frage: warum forcest du nicht
reset_n[i]? Das sollte doch problemlos möglich sein?
abcd schrieb:> Ich hab gerade in den Verilog2001 Standard geschaut, der sagt dass man> genvar im generate Block als variable verwenden soll, daher sollte> eigentlich dein generate im code schon einen Fehler werfen. Vielleicht> ist aber der Simulator auch grosszügig bei der auslegung des> Standards... Hilft dir aber auch nix :-)
abcd, du hast natürlich recht, da haben sich ein paar Fehler in meinen
Beispielcode geschlichen... Das ist Problem wenn man nicht den Original
Code nimmt.
1
// Irgendwo im Code
2
parameter N=4;
3
genvar i; // tatsächlich genvar
4
wire [N-1:0] reset_n; // array
5
6
generate
7
for(i=0; i<N; i=i+1) begin: generatedModules
8
meinModul meinModulInstanz
9
(
10
.reset_n_i (reset_n[i]),
11
...
12
);
13
14
anderesModul ...
15
(
16
.reset_n_i (reset_n[i])
17
);
18
end
19
endgenerate
> So, viel erzählt und noch ne blöde Frage: warum forcest du nicht> reset_n[i]? Das sollte doch problemlos möglich sein?
Das wäre eine Möglichkeit die ich tatsächlich noch nicht in Betracht
gezogen habe. :-) Das Problem ist nur, dass dieses reset im tatsächlich
Code noch mit anderen Instanzen verbunden ist, die ich während dem Test
lieber unverändert sehen würde (ich habe das mal noch im Code ergänzt).
Mag sein, dass das was du vorhast irgendwie geht, ich kann mir
allerdings momentan keinen direkten Weg vorstellen der mit Verilog
beschrieben werden kann.
Du könntest höchstens in deinem Code den reset auf ein anderes Signal
(zb: reset_mein_n[]) zuweisen und dann nur dieses direkt forcen.
Funktional macht das keinen Unterschied, sollte dir aber deinen
gewünschten Test ermöglichen.
Ja gut, das würde dann auf einen zusätzlichen Port extra für die
Testbench hinauslaufen - oder? Das wollte ich auf jeden Fall vermeiden.
Ich denke ich werde es wohl doch so machen, dass ich die Instanzen
direkt anspreche. Vielleicht finde ich noch eine Möglichkeit dass man
das einigermaßen problemlos im Code ändern kann mit auskommentieren oder
so.
Vielen Dank allen für die Anregungen!
Was ist Dein Problem? Du erzeugst einfach eine Variable für jedes Deiner
Signale, und weist diese im Test zu. Mit force die Verbindung zwischen
Modulen zu treiben würde ich eher nicht empfehlen, da der Systemzustand
dann inkonsistent wird. Die Quelle des Signals sieht ja noch den alten
Wert. Deswegen unterscheidet man auch zwischen Block- und System-level
tests. Bei ersterem werden alle signale eines Blocks durch die Testbench
getrieben, beim letzteren nur teilweise.
--
Marcus
Marcus Harnisch schrieb:> Was ist Dein Problem? Du erzeugst einfach eine Variable für jedes Deiner> Signale, und weist diese im Test zu. Mit force die Verbindung zwischen> Modulen zu treiben würde ich eher nicht empfehlen, da der Systemzustand> dann inkonsistent wird. Die Quelle des Signals sieht ja noch den alten> Wert. Deswegen unterscheidet man auch zwischen Block- und System-level> tests. Bei ersterem werden alle signale eines Blocks durch die Testbench> getrieben, beim letzteren nur teilweise.>> --> Marcus
Das Problem ist, dass ich mehrere Module habe die miteinander
kommunizieren, wobei der Kanal fehlerbehaftet ist. Da die Fehler ein
wichtiger Bestandteil des Systems sind muss ich für eine vernünftige
Simulation eben auch Fehler reinbekommen. Das schaffe ich aber nur wenn
ich an den internen Signalen herumspiele (die Testbench ist auf einem
Level darüber, die nur die besagten Module steuert). Mit dem reset hätte
ich einfach eine 100% Fehlerquote simulieren können, das war aber nur
ein Beispiel. Für die Realität muss ich das natürlich noch feiner
abstufen, aber das Prinzip ist dann das gleiche, nur eben mit anderen
Signalen.
werilog schrieb:> Das Problem ist, dass ich mehrere Module habe die miteinander> kommunizieren, wobei der Kanal fehlerbehaftet ist. Da die Fehler ein> wichtiger Bestandteil des Systems sind muss ich für eine vernünftige> Simulation eben auch Fehler reinbekommen. Das schaffe ich aber nur wenn> ich an den internen Signalen herumspiele (die Testbench ist auf einem> Level darüber, die nur die besagten Module steuert).
...oder in einer block level Simulation mit Fehlern am Eingang.
Ich muss mich übrigens korrigieren. Wenn man mit force ein net treibt,
sehen natürlich alle angeschlossenen Module diesen Wert.