Forum: FPGA, VHDL & Co. constant value of 0 in block <.>. This FF/Latch will be trimmed during the optimization process


von Klaus S. (klasch)


Lesenswert?

Hallo,

ich Versuche gerade verzweifelt die Warnungen der Synthese für das 
Trimmen von Optimieren von FF/Latches weg zu bekommen. Vorab die Signale 
verändern sich und in der Simulation mit ISim erhalte ich auch das 
gewünschte Ergebnis.

Kurze Erklärung zum Verhalten: Ich verwende zwei Puffer (rd, wr) die von 
einem A/D-Bus Daten erhalten bzw. bereit stellen. Mit einem zusätzlichen 
Signal wird ein Datenaustausch zwischen den Puffern und einem 
nachgeschalteten Element ebenfalls über einen A/D-Bus angeregt. Die 
Signalerzeugung hierfür wird durch eine FSM vorgenommen.
Die Pufferschaltung und das nachgeschaltete Element sollen vervielfacht 
werden, so dass mit einem  Signal ein zeitgleicher Datenaustausch der 
vorgehaltenen Daten durchgeführt werden kann.
1
architecture rtl of bufqd is
2
  --data buffer
3
  type dbuffer is array (0 to DATASET_SIZE-1) of std_logic_vector(BUF_D_SIZE-1 downto 0); 
4
  signal buf_rd, buf_wr : dbuffer;
5
.
6
.
7
.
8
begin
9
  buffer_wr_proc: process
10
  begin
11
    wait until rising_edge(clk_i);
12
    if (rst_i = '1') then
13
      buf_wr <= (others => (others => '0'));
14
      buf_rd <= (others => (others => '0'));
15
    elsif (en_i = '1') then
16
      if ((To_integer(unsigned(buf_addr_i(15 downto 8))) = BUF_A_BASE) and (buf_we_i = '1')) then
17
        buf_wr(To_integer(unsigned(buf_addr_i(1 downto 0)))) <= buf_di_i;
18
      end if;
19
      
20
      if ((quad_oe = '1') and (quad_addr = '0')) then
21
        buf_rd(0) <= qd_di_i(15 downto 0);
22
        buf_rd(1) <= qd_di_i(31 downto 16);          
23
      elsif ((quad_oe = '1') and (quad_addr = '1')) then
24
        buf_rd(0) <= qd_di_i(15 downto 0);
25
        buf_rd(1) <= qd_di_i(31 downto 16);  
26
      end if;      
27
    end if;
28
  end process buffer_wr_proc;
29
.
30
.
31
.
32
end rtl;

Synthetisiere ich das Projekt alleine, gibt es keine entsprechenden 
Warnings. Baue ich die gesamte Schaltung zusammen erhalte ich die 
folgenden Warnings (kurzer Auszug, gilt natürlich für alle Elemente von 
Buf_wr und buf_rd):
1
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <C_BUFQD_QD/C_BUFQD/buf_wr_2_12> (without init value) has a constant value of 0 in block <rt_sense_v3_min>. This FF/Latch will be trimmed during the optimization process.
2
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <C_BUFQD_QD/C_BUFQD/buf_wr_2_11> (without init value) has a constant value of 0 in block <rt_sense_v3_min>. This FF/Latch will be trimmed during the optimization process.
3
4
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <buf_rd_3_14> (without init value) has a constant value of 0 in block <bufqd>. This FF/Latch will be trimmed during the optimization process.
5
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <buf_rd_3_13> (without init value) has a constant value of 0 in block <bufqd>. This FF/Latch will be trimmed during the optimization process.

Ich würde mich über einen Tipp sehr, denn mir erschließt es sich im 
Moment nicht.

Grüße,
Klaus

PS: rst_i ist angeschlossen und auch nicht dauerhaft auf '1' gehängt.

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

ich sehe, wie du buf_rd(0) und buf_rd(1) Daten zuweist. Aber buf_rd(3) 
scheint auch zu existieren und wird für mich nicht erkennbar auf andere 
Werte als 0 gesetzt.

Ich kann es auch als Frage formulieren: welchen Wert hat DATASET_SIZE

von Klaus S. (klasch)


Lesenswert?

Hallo Achim,

da hast Du natürlich recht, vor lauter herumprobieren hatte das jetzt 
nicht gestimmt. Richtig sollte das natürlich so heißen:
1
generic(
2
...
3
DATASET_SIZE  : integer := 4;
4
...
5
);
1
...
2
      if ((quad_oe = '1') and (quad_addr = '0')) then
3
        buf_rd(0) <= qd_di_i(15 downto 0);
4
        buf_rd(1) <= qd_di_i(31 downto 16);          
5
      elsif ((quad_oe = '1') and (quad_addr = '1')) then
6
        buf_rd(2) <= qd_di_i(15 downto 0);
7
        buf_rd(3) <= qd_di_i(31 downto 16);  
8
      end if; 
9
10
...



Danke.

: Bearbeitet durch User
von Klaus S. (klasch)


Lesenswert?

Damit ist das Problem aber nicht gelöst, die korrekten Werte für die 
Zuweisung  hatte ich zuvor bereits. Der Fehler entstand nur durch 
Umstellungen innerhalb des Prozesses, um die Warnings weg zu bwkommwn. 
Sie sind aber weiterhin vorhanden.

von Daniel M. (daniel__m)


Lesenswert?

Klaus S. schrieb:
> Synthetisiere ich das Projekt alleine, gibt es keine entsprechenden
> Warnings. Baue ich die gesamte Schaltung zusammen erhalte ich die
> folgenden Warnings

Dann lieg das Problem vermutlich nicht im Codeauszug, sondern in der 
restlichen Schaltung. Und die Warnung muss nicht zwangläufig auf ein 
Problem hinweisen, viel mehr erkennt das Synthese-Tool, dass von "oben" 
nicht alle Signale toggeln (evtl. Konstante?, Resize, ...) und es daher 
optimieren kann.

grüße

von Achim S. (Gast)


Lesenswert?

Daniel M. schrieb:
> Dann lieg das Problem vermutlich nicht im Codeauszug, sondern in der
> restlichen Schaltung.

das sehe ich auch so.

Schreib doch mal eine Testbench, in der du durch externe Stimuli für die 
Gesamtschaltung dafür sorgst, dass <buf_rd_3_14> einen Wert ungleich 0 
annimmt und in dem dieser Wert<>0 auch eine Folgewirkung auf Ausgänge 
der Gesamtschltung hat. Laut Snthesetool sollte dir das nicht gelingen. 
Vielleicht merkst du bei dem Versuch, woran es hängt.

PS: in den gezeigten Warnungen sind nur hohe Bitpositionen genannt. Es 
gibt nicht vielleicht einen Mismatch zwischen BUF_D_SIZE und der Breite 
des AD-Bus?

von Klaus S. (klasch)


Lesenswert?

Achim S. schrieb:
> Daniel M. schrieb:
>> Dann lieg das Problem vermutlich nicht im Codeauszug, sondern in der
>> restlichen Schaltung.

Dachte ich auch. Die Adresse und Daten kommen direkt von einem GPMC_Core 
und dort liegt keines der Signale dauerhaft auf einem Level.

> Schreib doch mal eine Testbench, in der du durch externe Stimuli für die
> Gesamtschaltung dafür sorgst, dass <buf_rd_3_14> einen Wert ungleich 0
> annimmt und in dem dieser Wert<>0 auch eine Folgewirkung auf Ausgänge
> der Gesamtschltung hat. Laut Snthesetool sollte dir das nicht gelingen.
> Vielleicht merkst du bei dem Versuch, woran es hängt.

Habe ich gemacht und die Simulation funktioniert auch einwandfrei. Es 
werden alle Adressen der Puffer mit Daten beschrieben bzw. Daten können 
gelesen werden.


> PS: in den gezeigten Warnungen sind nur hohe Bitpositionen genannt. Es
> gibt nicht vielleicht einen Mismatch zwischen BUF_D_SIZE und der Breite
> des AD-Bus?

BUF_D_SIZE bekommt bei der Instanzierung die Busbreite über den selben 
generic wie das GPMC-Modul, also sollte ein Mismatch ausgeschlossen 
sein. Es betrifft auch nicht nur die hohen Bitpositionen.
1
<C_BUFQD_QD/C_BUFQD/buf_wr_1_15> (without init value) has a constant value of 0
2
<C_BUFQD_QD/C_BUFQD/buf_wr_1_14> (without init value) has a constant value of 0
3
<C_BUFQD_QD/C_BUFQD/buf_wr_1_13> (without init value) has a constant value of 0
4
<C_BUFQD_QD/C_BUFQD/buf_wr_1_12> (without init value) has a constant value of 0
5
<C_BUFQD_QD/C_BUFQD/buf_wr_1_11> (without init value) has a constant value of 0
6
<C_BUFQD_QD/C_BUFQD/buf_wr_1_10> (without init value) has a constant value of 0
7
<C_BUFQD_QD/C_BUFQD/buf_wr_1_9> (without init value) has a constant value of 0 
8
<C_BUFQD_QD/C_BUFQD/buf_wr_1_8> (without init value) has a constant value of 0 
9
<C_BUFQD_QD/C_BUFQD/buf_wr_1_7> (without init value) has a constant value of 0 
10
<C_BUFQD_QD/C_BUFQD/buf_wr_1_6> (without init value) has a constant value of 0 
11
<C_BUFQD_QD/C_BUFQD/buf_wr_1_5> (without init value) has a constant value of 0 
12
<C_BUFQD_QD/C_BUFQD/buf_wr_1_4> (without init value) has a constant value of 0 
13
<C_BUFQD_QD/C_BUFQD/buf_wr_1_3> (without init value) has a constant value of 0 
14
<C_BUFQD_QD/C_BUFQD/buf_wr_1_2> (without init value) has a constant value of 0 
15
<C_BUFQD_QD/C_BUFQD/buf_wr_1_1> (without init value) has a constant value of 0 
16
<C_BUFQD_QD/C_BUFQD/buf_wr_1_0> (without init value) has a constant value of 0

Die einzige Ungereimtheit dir mir noch auffällt ist, das alle Bits von 
buf_wr_0 nicht betroffen sind. Das würde dafür sprechen das sich die 
Adresse nicht ändert oder etwas am Typcast hier nicht stimmt:
1
buf_wr(To_integer(unsigned(buf_addr_i(1 downto 0)))) <= buf_di_i;

von Achim S. (Gast)


Lesenswert?

nochmal zur Sicherheit die Nachfrage:

Klaus S. schrieb:
> Es
> werden alle Adressen der Puffer mit Daten beschrieben bzw. Daten können
> gelesen werden.

Heißt das, dass nach der Synthese auch Daten aus buf_wr(2) ausgelesen 
werden und sicher eine Wirkung auf Ausgänge auf top-level haben? Wenn 
die Daten nur gespeichert, aber nie wirklich benutzt werden, kann der 
Synthesizer sie ebenfalls ignorieren (wobei die Warnung dann 
wahrscheinlich etwas anders lauten würde).

Im allerschlimmsten Fall musst du uns halt mal mehr als die bisherigen 
Codeschnipsel zeigen.

von Klaus S. (klasch)


Lesenswert?

Achim S. schrieb:
> nochmal zur Sicherheit die Nachfrage:
>
> Klaus S. schrieb:
>> Es
>> werden alle Adressen der Puffer mit Daten beschrieben bzw. Daten können
>> gelesen werden.

Schande über mein Haupt und tausendmal Sorry. Die Elemente 1-3 wurde 
durch die Synthese tatsächlich getrimmt und sind in der Simulation 
zunächst nicht aufgefallen, da nur das Element 0 (Controlwort zur 
Konfiguration) benötigt und übermittelt wurde.

Ursache ist die anscheinend dauerhaft '0' zeigende Adresse addr_o. Kann 
mir jemand bitte erklären warum diese Dauerhaft '0' sein soll? Bin zwar 
kein ganz blutiger Anfänger mehr aber auch noch nicht so erfahren.
Danke vorab!

1
architecture rtl of gpmc is
2
  signal csn     : std_logic_vector(3 downto 0);
3
  signal oen     : std_logic;
4
  signal wen     : std_logic;
5
  signal len     : std_logic;
6
begin
7
  signal_proc: process
8
  begin
9
    wait until rising_edge(clk_i);    
10
    if rst_i = '1' then
11
      len <= '1';
12
      oen <= '1';
13
      wen <= '1';
14
      csn <= (others => '1');
15
    else  
16
      csn <= csn(2 downto 0) & gpmc_csn_i;  
17
      oen <= gpmc_oen_i;
18
      wen <= gpmc_wen_i;
19
      len <= gpmc_len_i;      
20
    end if;
21
  end process signal_proc;
22
  
23
  gpmc_ad_io <= data_i when ((csn(3) = '0') and (len = '1') and (oen = '0') and (wen = '1')) else (others => 'Z');
24
  addr_o <= gpmc_ad_io when ((csn(3) = '0') and (len = '0') and (oen = '1') and (wen = '1')) else (others => '0');
25
  data_o <= gpmc_ad_io when ((csn(3) = '0') and (len = '1') and (oen = '1') and (wen = '0')) else (others => '0');
26
  
27
  we_o <= not wen;
28
  oe_o <= not oen;
29
end rtl;

von Schlumpf (Gast)


Lesenswert?

Vielleicht liegt in deinem Core gpmc_len_i dauerhaft auf '1'?

von Klaus S. (klasch)


Lesenswert?

Schlumpf schrieb:
> Vielleicht liegt in deinem Core gpmc_len_i dauerhaft auf '1'?

Leider nicht! Kommt direkt von außen durch einen Pin rein (Schnittstelle 
zum µC).

: Bearbeitet durch User
von Valko Z. (hydravliska)


Lesenswert?

Hast du schon mal die Pinbelegung überprüft (Schnittstelle zum µC)?

Gruß

von Achim S. (Gast)


Lesenswert?

Klaus S. schrieb:
> when ((csn(3) = '0') and (len = '0') and (oen = '1') and (wen = '1'))

Wenn diese Bedingung erfüllt ist, dann schreibst du deine Adresse.

Wenn diese Bedingung nicht erfüllt ist (z.B. wenn du gerade Daten 
schreiben willst), dann setzt du die Adresse wieder auf 0 zurück (der 
else Pfad) der Abfrage.

-> das Daten-Schreiben geht immer auf Adresse 0.

von Achim S. (Gast)


Lesenswert?

Ach ja, der Lösungsvorschlag fehlt ja noch:

mach aus addr_o ein getaktetes Flipflop (d.h. pack es in den getakteten 
Prozess).

Überschreibe addr_o immer dann, wenn die Bedingungen dafür erfüllt sind.
if ((csn(3) = '0') and (len = '0') and (oen = '1') and (wen = '1'))

Wenn diese Bedingungen nicht erfüllt sind: mache keine Zuweisung an 
addr_o, so dass der zuvor zugewiesene Wert gespeichert bleibt.

von Klaus S. (klasch)


Lesenswert?

Achim S. schrieb:
> mach aus addr_o ein getaktetes Flipflop (d.h. pack es in den getakteten
> Prozess).

Das hatte ich zuvor so und es hat funktioniert. Dachte nur, dass die 
andere Lösung eleganter ist, da man sich die Initialisierung beim Reset 
für die entsprechenden Ausgänge sparrt und immer ein definierter Wert 
vorhanden ist.

Dank dir Achim!

von Klaus S. (klasch)


Lesenswert?

Valko Zapalko schrieb:
> Hast du schon mal die Pinbelegung überprüft (Schnittstelle zum µC)?
>
> Gruß

Ist noch nicht in Hardware umgesetzt, befinden mich noch bei der 
Simulation.

von Klaus S. (klasch)


Lesenswert?

1
addr_o <= gpmc_ad_io when ((csn(3) = '0') and (len = '0') and (oen = '1') and (wen = '1')) else (others => '0');
Warum dies bei der Synthese als dauerhaft '0' interpretiert wird ist mir 
trotzdem nicht klar.

Gleiches Problem auch hier:
1
y_o <= x_o(to_integer(unsigned(s_i))) when en_i = '1' else (others => '0');

Sowohl en_i als auch die anderen Steuersignale zuvor ändern sich.

Verstehe ich etwas Grundlegendes nicht?

von Achim S. (Gast)


Lesenswert?

Klaus S. schrieb:
> Warum dies bei der Synthese als dauerhaft '0' interpretiert wird ist mir
> trotzdem nicht klar.

Es ist nicht dauerhaft Null. Es ist aber während des Schreibzugriffs 
Null (weil dann wen=0 ist und der else-Zweig dafür sorgt, dass addr_o 
Null wird).

Und weil addr_o wahrscheinlich nur während des Schreibzugriffs relevant 
ist, kann es auch gleich immer auf Null gesetzt werden.

Anders gesagt: du speicherst die Adresse nicht für den später folgenden 
Schreibzugriff. Das musst du aber tun (in einem Flipflop).

von Achim S. (Gast)


Lesenswert?

Achim S. schrieb:
> Es ist aber während des Schreibzugriffs
> Null

gemeint war natürlich der Schreibzugriff auf die Daten (we=0), nicht der 
Schreibzugriff auf die Adresse (le=0).

von Klaus S. (klasch)


Lesenswert?

Oh man, bin ich ein I....! Klar wird das als dauerhaft Null angesehen, 
den wie du sagst:

Achim S. schrieb:
> Anders gesagt: du speicherst die Adresse nicht für den später folgenden
> Schreibzugriff. Das musst du aber tun (in einem Flipflop).

Sorry für den Aufwand, der Groschen ist gefallen.

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.