Hallo,
Ich habe ein an sich übersichtliches VDHL-Design, welches in der
Behavorial-Simulation funktioniert.
Wird, es jedoch Synthetisiert, so erscheinen viele Warnungen der Sorte:
[Synth 8-3332] Sequential element (\SPI/timestamp_reg[47] ) is unused
and will be removed from module Main.
Dabei werden alle Signale zu Beginn mittels reset initialisiert und
ihnen vielfach Werte zugewiesen.
Durch Attribute wie "keep" oder "dont touch" ergibt sich keinerlei
Ändeung, die Signale werden weiterhin als unused erkannt und entfernt.
Selbst wenn die Signale herausführt und direkt auf Pins gegeben werden,
so sind sei weiterhin unused.
Habt ihr ideen woran es liegen könnte?
Wahrscheinlich werden die Signale nicht benutzt -.-
Wenn du ein Signal hast, das immer 0 ist, wird der entsprechende Pin auf
Masse gelegt und das Signal wegoptimiert.
Warum das so ist, ist nicht immer einfach herauszufinden. Ich hatte das
Problem auch mal und habe relativ lange gesucht, bis ich rausgefunden
habe, warum das Signal nicht geändert wird.
Dussel schrieb:> Wenn du ein Signal hast, das immer 0 ist, wird der entsprechende Pin auf> Masse gelegt und das Signal wegoptimiert.
Die betreffenden Signale ändern ihren Zustand in der
Behavorial-Simulation, sonst könnte die Schaltung auch nicht
funktionieren.
Wie kann die Synthese dann fest stellen dass sie ihren Zustand nicht
ändern?
Matze schrieb:> Wie kann die Synthese dann fest stellen dass sie ihren Zustand nicht> ändern?
Der Synthesizer bemängelt nicht, dass sie ihren Zustand nicht ändern,
sondern, dass sie unbenutzt sind. Du kannst ein riesiges Design
machen, aber wenn du keine Ausgänge hast, wird alles "wegoptimiert",
denn egal was gemacht wird, aussen merkt es ja niemand, dass da was
fehlt.
Matze schrieb:> Ich habe ein an sich übersichtliches VDHL-Design, welches in der> Behavorial-Simulation funktioniert.
Das sagt nicht viel. In der Simulation funktioniert sogar eine "wait for
10 ms;" Anweisung tadellos.
> Dabei werden alle Signale zu Beginn mittels reset initialisiert und> ihnen vielfach Werte zugewiesen.
Das sollte man mal mit eigenen Augen sehen. Oder andersrum: bisher hatte
bei mir der Synthesizer mit solchen einfachen Behauptungen (...is
unused...) immmer Recht...
Genauere Aussagen gibt es nur, wenn du die paar Quelldateien deines "an
sich übersichtlichen" Desgins mal postest. So viele können das ja nicht
sein.
Matze schrieb:> Dussel schrieb:>> Wenn du ein Signal hast, das immer 0 ist, wird der entsprechende Pin auf>> Masse gelegt und das Signal wegoptimiert.>> Die betreffenden Signale ändern ihren Zustand in der> Behavorial-Simulation, sonst könnte die Schaltung auch nicht> funktionieren.>> Wie kann die Synthese dann fest stellen dass sie ihren Zustand nicht> ändern?
Wenn ich dich recht verstehe stellt die Synthese garnicht fest das deren
Zustand konstant ist, sondern das dieser Zustand nirgends benutzt wird,
also der Ausgang des FF o.ä. nicht verdrahtet ist.
Mglw führen deine Register ja auf ein SPI modul was nicht angeschlossen
nach draussen verdrahtet ist.
Wenn du eine alternative synthesetool verwenden kannst (XST) dann
versuch das mal mit diesem.
Im Zusammenhang mit Chipscope irrt sich die Synthese gelegentlich
bezüglich des unused, da das chipscope-modul im design ohne ausgänge
erscheint, der JTAG-Port steckt nur in der Netzliste. Aber das scheint
hier nicht der Fall zu sein.
Problem ähnlicher Art könnte man bei SOC-FPGA's wie Zynq erwarten, wenn
Module genutzt werden die nicht im FPGA-Anteil realisiert sind sondern
als Hardcore bspw. Peripherals.
MfG,
Lothar M. schrieb:> Matze schrieb:>> Wie kann die Synthese dann fest stellen dass sie ihren Zustand nicht>> ändern?> Der Synthesizer bemängelt nicht, dass sie ihren Zustand nicht ändern,> sondern, dass sie unbenutzt sind. Du kannst ein riesiges Design> machen, aber wenn du keine Ausgänge hast, wird alles "wegoptimiert",> denn egal was gemacht wird, aussen merkt es ja niemand, dass da was> fehlt.
Bei mir war damals das Problem, dass sich Signale wegen eines Fehlers
nicht geändert haben. Deswegen wurde der entsprechende Ausgang auf einen
festen Wert gelegt. Darauf hat der Synthesizer erkannt, dass der Ausgang
auf einem festen Wert liegt und das entsprechende Signal unbenutzt ist
und hat den ganzen Rest wegoptimiert. Da kam auch die Meldung mit dem
unbenutzten Signal, aber die eigentliche Ursache war, dass das Signal
konstant war.
Hier wurde ja das Signal auf einen Ausgang gelegt, wird aber trotzdem
noch als unbenutzt wegoptimiert. Deshalb denke ich, dass hier der
gleiche Fehler wie bei mir damals vorliegen könnte.
Lothar M. schrieb:> Das sollte man mal mit eigenen Augen sehen. Oder andersrum: bisher hatte> bei mir der Synthesizer mit solchen einfachen Behauptungen (...is> unused...) immmer Recht...
Ja, sollte man:
Hier mal der Quellcode des SPI-Empfängers:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useieee.std_logic_unsigned.all;
4
5
entityQSPI_Analyzer_Inputis
6
Port(
7
SYS_CLK:inSTD_LOGIC;-- 100MHZ-Clk
8
SCLK:inSTD_LOGIC;-- clk des SPI-Bus
9
DATA:inSTD_LOGIC_VECTOR(3downto0);-- Daten des SPI-Bus
SYS_CLK=>CLK100MHZ,--!!! wird im Moment nicht benötigt
72
SCLK=>SCLK_pin,--: in STD_LOGIC; -- clk des SPI-Bus
73
DATA=>SDATA,--: in STD_LOGIC_VECTOR (3 downto 0); -- Daten des SPI-Bus
74
CS=>SCS_IBUF,--: in STD_LOGIC; -- CS-Leitung des SPI-Bus
75
reset=>reset_qspi_analyzer_input,--: in Std_logic; -- Reset des QSPI-Interface
76
out_reg=>aout_reg,--: out STD_LOGIC_VECTOR (15 downto 0); -- 3 SPI-Worte in 1 16-Bit-Wort, Bit 15 ist frei
77
wren_out_reg=>wren_out_reg);--: out STD_LOGIC; -- ausgabe fuer "Daten gueltig"
78
79
Disp:Seg_DispPortmap
80
(clk=>CLK100MHZ,--: in STD_LOGIC;
81
disp_data=>adisp_data,
82
led_out=>C,--: out STD_LOGIC_VECTOR (7 downto 0);
83
an_out=>AN);--: out STD_LOGIC_VECTOR (7 downto 0));
84
85
endBehavioral;
Somit sollen die Daten wenn kein Reset anliegt, und der CS auf '0' ist
sowohl auf die LED's als auch auf der 7-Seg-Anzeige ausgegeben werden.
Problem ist, dass die Fehlermeldung
für alle 8-Bits [0..7] des 7-Segment-Decoders erscheint.
Nicht jedoch für die LED's welche dann aber eigentlich auch "UNUSED"
sein müssten.
Wird z.b. ein Counter auf die 7-Segment-Anzeige ausgegeben, dann treten
die Warnungen nicht auf:
1
disp_data(7downto0)<=disp_data(7downto0)+'1';
2
disp_data(39downto8)<=disp_data(39downto8)+'1';
3
--adisp_data(7 downto 0) <= aout_reg;
4
--adisp_data(39 downto 8) <= x"00000000";
Wie kann es also sein, dass "aout_reg" für die LED's "used" ist, bei
Anzeige auf 7-Segment jedoch keine zustandsänderung erfolgen soll?
Wiederspricht sich dass nicht?
Matze schrieb:> Problem ist, dass die Fehlermeldung[Synth 8-3332] Sequential element> (\adisp_data_reg[0] ) is unused and will be removed from module Main.> für alle 8-Bits [0..7] des 7-Segment-Decoders erscheint.> Nicht jedoch für die LED's welche dann aber eigentlich auch "UNUSED"> sein müssten.
erst mal zur Begriffsklärung: deine Ausgänge "LED" hängen nicht von
adisp_data ab sondern nur von areg. Wenn DispData auf etwas einen
Einfluss haben sollte, dann auf die Ausgänge "C".
Ob Dispdata einen wirklichen Einfluss auf C hat sieht man nicht, weil
das in der nicht gezeigten Komponente Seg_Disp festgelegt wird. Also:
wie sieht Seg_Disp intern aus? Bei den Warnings sind Bits 39..4 von
disp_data immer auf 0, beim Beispiel mit dem Counter ist das nicht der
Fall. Macht das den Unterschied für Seg_Disp?
Noch eine Anmerkung zu deiner SPI-Komponente: deine Beschreibung mit
rising_edge(sclk) ist unsauber (gibt es hierzu keine Warnings? Evtl.
steckt schon hier der Grund für deine Warnung bei disp_data). Nutze
lieber die 100MHz-Clock um sauber mit getakteten FlipFlops zu arbeiten,
und machen an SCLK eine Flankenerkennung, wann die Werte von Data
übernommen werden sollen.
Achim S. schrieb:> deine Beschreibung mit rising_edge(sclk) ist unsauber (gibt es hierzu> keine Warnings?
Ich würde hier wenigstens eine Meldung in Richtung "this is no good
design practice" erwarten.
Man kann das mit dem lokalen Takt schon so machen. Allerdings sollte man
sich dann ausführlich Gedanken zur Übergabe der Daten an die 100MHz
Clock-Domäne machen.
Wenn im vorigen Absatz zu viele unbekannte Worte waren, dann empfehle
ich streng synchrones Design (im gesamten Design nur 1 einziger Takt:
der Oszillatortakt), wo alle externen Eingänge (auch die, die einen
Namensteil "-clock" haben) einfach erst mal einsynchronisiert werden.
Lothar M. schrieb:> Man kann das mit dem lokalen Takt schon so machen. Allerdings sollte man> sich dann ausführlich Gedanken zur Übergabe der Daten an die 100MHz> Clock-Domäne machen.
Ist in diesem Fall imho noch etwas problematischer, weil das
"rising_edge(sclk)" innerhalb eines geschachtelten if-then-else steht
(ein äußeres Konstrukt für den asynchronen Reset, aber drunter noch eine
Abfrage für das CS und erst abhängig davon kommt das rising_edge). Ich
bin mir nicht sicher, ob die geschachtelten if-then-else in die
Generierung eines Reset-Signals zusammengefasst werden können (für
wren_out ein Reset abhängig vom externen Signal Reset, für outreg ein
Reset abhängig von den externen Signalen Reset und CS).
Wenn das nicht passiert, macht er mit SCLK hier nicht nur eine zweite
Taktdomäne auf, sondern es wird noch verwickelter.
Danke für eure bisherigen Ratschläge ;)
Achim S. schrieb:> Ob Dispdata einen wirklichen Einfluss auf C hat sieht man nicht, weil> das in der nicht gezeigten Komponente Seg_Disp festgelegt wird. Also:> wie sieht Seg_Disp intern aus?
Hier ist es, ein gewöhnlicher Multiplexer für 7Segment-Anzeigen:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useieee.std_logic_unsigned.all;
4
5
entitySeg_Dispis
6
Port(clk:inSTD_LOGIC;
7
disp_data:inSTD_LOGIC_VECTOR(39downto0);
8
led_out:outSTD_LOGIC_VECTOR(7downto0);
9
an_out:outSTD_LOGIC_VECTOR(7downto0));
10
endSeg_Disp;
11
12
architectureBehavioralofSeg_Dispis
13
signalcount:std_logic_vector(19downto0);
14
15
16
componentBcd_Dec
17
Port(hex:inSTD_LOGIC_VECTOR(3downto0);
18
bcd:outSTD_LOGIC_VECTOR(7downto0));
19
endcomponent;
20
signalhex:std_logic_vector(3downto0);
21
signalbcd:std_logic_vector(7downto0);
22
begin
23
24
Seg_Disp:process(clk)
25
variablecount_disp:integer;
26
begin
27
28
if(rising_edge(clk))then
29
count<=count+1;
30
ifcount=x"20000"then
31
count<=x"00000";
32
casecount_dispis
33
when0=>
34
count_disp:=count_disp+1;
35
an_out<="01111111";
36
hex<=disp_data(3downto0);
37
led_out(6downto0)<=bcd(6downto0);
38
led_out(7)<=notdisp_data(39);
39
when1=>
40
count_disp:=count_disp+1;
41
an_out<="11111110";
42
hex<=disp_data(7downto4);
43
led_out(6downto0)<=bcd(6downto0);
44
led_out(7)<=notdisp_data(32);
45
when2=>
46
count_disp:=count_disp+1;
47
an_out<="11111101";
48
hex<=disp_data(11downto8);
49
led_out(6downto0)<=bcd(6downto0);
50
led_out(7)<=notdisp_data(33);
51
when3=>
52
count_disp:=count_disp+1;
53
an_out<="11111011";
54
hex<=disp_data(15downto12);
55
led_out(6downto0)<=bcd(6downto0);
56
led_out(7)<=notdisp_data(34);
57
when4=>
58
count_disp:=count_disp+1;
59
an_out<="11110111";
60
hex<=disp_data(19downto16);
61
led_out(6downto0)<=bcd(6downto0);
62
led_out(7)<=notdisp_data(35);
63
when5=>
64
count_disp:=count_disp+1;
65
an_out<="11101111";
66
hex<=disp_data(23downto20);
67
led_out(6downto0)<=bcd(6downto0);
68
led_out(7)<=notdisp_data(36);
69
when6=>
70
count_disp:=count_disp+1;
71
an_out<="11011111";
72
hex<=disp_data(27downto24);
73
led_out(6downto0)<=bcd(6downto0);
74
led_out(7)<=notdisp_data(37);
75
when7=>
76
count_disp:=count_disp+1;
77
an_out<="10111111";
78
hex<=disp_data(31downto28);
79
led_out(6downto0)<=bcd(6downto0);
80
led_out(7)<=notdisp_data(38);
81
count_disp:=0;
82
whenothers=>an_out<="11111111";
83
endcase;
84
endif;
85
endif;
86
endprocess;
87
88
G1_Bcd_Dec:Bcd_Decportmap(hex,bcd);
89
90
endBehavioral;
Er benutzt diesen BCD-Decoder:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
4
entityBcd_Decis
5
Port(hex:inSTD_LOGIC_VECTOR(3downto0);
6
bcd:outSTD_LOGIC_VECTOR(7downto0));
7
endBcd_Dec;
8
9
architectureBehavioralofBcd_Decis
10
begin
11
BCD_Proc:Process(hex)
12
begin
13
casehexis
14
when"0000"=>bcd<="01000000";--0
15
when"0001"=>bcd<="01111001";--1
16
when"0010"=>bcd<="00100100";--2
17
when"0011"=>bcd<="00110000";--3
18
when"0100"=>bcd<="00011001";--4
19
when"0101"=>bcd<="00010010";--5
20
when"0110"=>bcd<="00000011";--6
21
when"0111"=>bcd<="01111000";--7
22
when"1000"=>bcd<="00000000";--8
23
when"1001"=>bcd<="00011000";--9
24
when"1010"=>bcd<="00001000";--A --> "01110111"
25
when"1011"=>bcd<="00000011";--B --> "01111100"
26
when"1100"=>bcd<="01000110";--C --> "00111001"
27
when"1101"=>bcd<="00100001";--D --> "01011110"
28
when"1110"=>bcd<="00000110";--E --> "01111001"
29
when"1111"=>bcd<="00001110";--F --> "01110001"
30
whenothers=>bcd<="00000000";
31
endcase;
32
endprocess;
33
endBehavioral;
Achim S. schrieb:> Also:> wie sieht Seg_Disp intern aus? Bei den Warnings sind Bits 39..4 von> disp_data immer auf 0, beim Beispiel mit dem Counter ist das nicht der> Fall. Macht das den Unterschied für Seg_Disp?
Tatsächlich, mann müsste erwarten dass die Bits 4..39 immer auf 0 sind
und deshalb unused und ab 8 auch undriven sind. Allerdings kommt die
Meldung unused für die Bits 0..7, lediglich für die Bits 8..39 gibt es:
[Synth 8-3295] tying undriven pin Disp:disp_data[37] to constant 0
Wobei das undriven nachvollziebar ist, das unused von 0..3 finde ich
nicht nachvollziehbar.
Achim S. schrieb:> Nutze> lieber die 100MHz-Clock um sauber mit getakteten FlipFlops zu arbeiten,> und machen an SCLK eine Flankenerkennung, wann die Werte von Data> übernommen werden sollen.
Wie meinst du dass?
Ich möchte nur Daten übernehmen, wenn die der CLK sich sinvoll ändert.
Darüber geben die 100MHZ je keine Information. Auch wünsche ich mir
keine "Überabtastung" mit hoher Frequenz und meist den selben Werten.
Deshalb gibt es an SCLK, welches ein CLK-Eingang ist, eine
Pflankenerkennung.
Mein langfristiges Ziel ist die aufgenommenen Daten in ein FIFO zu
schreiben. So hätte ich alles vor dem FIFO mit SCLK eingetacktet und die
daten mit 100MHZ herausgeholt.
Warnings gibt es deshalb keine.
Lothar M. schrieb:> Man kann das mit dem lokalen Takt schon so machen. Allerdings sollte man> sich dann ausführlich Gedanken zur Übergabe der Daten an die 100MHz> Clock-Domäne machen.
Die Übergabe soll letztendlich über einen FIFO passieren.
So sollte es doch keine Probleme geben?
Achim S. schrieb:> Ist in diesem Fall imho noch etwas problematischer, weil das> "rising_edge(sclk)" innerhalb eines geschachtelten if-then-else steht> (ein äußeres Konstrukt für den asynchronen Reset, aber drunter noch eine> Abfrage für das CS und erst abhängig davon kommt das rising_edge). Ich> bin mir nicht sicher, ob die geschachtelten if-then-else in die> Generierung eines Reset-Signals zusammengefasst werden können (für> wren_out ein Reset abhängig vom externen Signal Reset, für outreg ein> Reset abhängig von den externen Signalen Reset und CS).>> Wenn das nicht passiert, macht er mit SCLK hier nicht nur eine zweite> Taktdomäne auf, sondern es wird noch verwickelter.
Dass dachte ich auch schon.
Würde gerne weniger Abfragen von Signalen mit rising_edge's quasi
&-Verknüpft haben wollen.
Aber wie wird so etwas 'vereinfacht'?
Matze schrieb:> Mein langfristiges Ziel ist die aufgenommenen Daten in ein FIFO zu> schreiben. So hätte ich alles vor dem FIFO mit SCLK eingetacktet und die> daten mit 100MHZ herausgeholt.
ok, kannst du machen (wenn SCLK auf einen CLK-Eingang geht und wenn du
auf das Framing mit CS verzichten willst - denn du wirst ggf. nur
SCLK-Flanken bekommen, während CS low ist, und den Anfang/das Ende eines
Frames nicht erkennen können).
Ich hatte Bedenken, dass das geschaltete if-then-else um die rising_edge
Abfrage nicht zu einem Reset aufgelöst wird. Aber die Bedenken haben
sich zerstreut, als ich eben deinen SPI-Code in Vivado eingegeben und
mir das Synthese-Ergebnis angeschaut habe (siehe Anhang). Die
geschachtelte if-then-else wird tatsächlich in eine Kombinatorik zur
Erzeugung eines Resets aufgelöst, du hast also eine "saubere" zweite
Taktdomäne.
Matze schrieb:> Dass dachte ich auch schon.> Würde gerne weniger Abfragen von Signalen mit rising_edge's quasi> &-Verknüpft haben wollen.>> Aber wie wird so etwas 'vereinfacht'?
indem du alles mit SYSCLK taktest und eine Flankenerkennung auf SCLK
machst, die das Abspeichern der Eingänge steuert.
http://www.lothar-miller.de/s9y/categories/18-FlankenerkennungMatze schrieb:> Hier ist es, ein gewöhnlicher Multiplexer für 7Segment-Anzeigen:
Tja, dem sehe ich auf die Schnelle ehrlich gesagt auch nicht an, wieso
LED_out dieser Komponente / C des topmoduls nicht mit echten Daten
getrieben werden sollten. Vielleicht kannst du dich ja mal durch die
Ergebnisse deiner Synthese durcharbeiten (z.B. per schematic view) um zu
sehen, wer laut Syntheseergebnis C treibt.
ok, ich denke jetzt hab ich den Grund für die Warnung gefunden.
adisp_out(3..0) und led_out(3..0) sind genau die identischen Daten. Es
gibt keinen Grund, zwei identische Kopien unter zwei verschiedenen Namen
zu führen. Deswegen wird adisp_out(3..0) wegoptimiert.
adisp_out(39..4) ist konstant 0 und braucht deswegen auch keine eigenen
Flipflops.