Forum: FPGA, VHDL & Co. [verilog] "Illegal operand for constant expression"


von werilog (Gast)


Lesenswert?

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.

von hiall (Gast)


Lesenswert?

auch generate verwenden?

von werilog (Gast)


Lesenswert?

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?

von werilog (Gast)


Lesenswert?

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

von Sergej Schätzer (Gast)


Lesenswert?

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,

von werilog (Gast)


Lesenswert?

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;

von abcd (Gast)


Lesenswert?

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?

von werilog (Gast)


Lesenswert?

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).

von abcd (Gast)


Lesenswert?

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.
1
// Irgendwo im Code
2
parameter  N=4;
3
genvar     i;        // tatsächlich genvar
4
wire [N-1:0] reset_n;       // array
5
wire [N-1:0] reset_mein_n;  // array
6
7
generate
8
  for(i=0; i<N; i=i+1) begin: generatedModules
9
10
    assign reset_mein_n[i] = reset_n[i];
11
12
    meinModul  meinModulInstanz
13
      (
14
        .reset_n_i  (reset_mein_n[i]),
15
        ...
16
      );
17
18
    anderesModul ...
19
      (
20
        .reset_n_i (reset_n[i])
21
      );
22
  end
23
endgenerate

von werilog (Gast)


Lesenswert?

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!

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

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

von werilog (Gast)


Lesenswert?

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.

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

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.

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.