Hallo zusammen,
ich arbeite mit einem iCE5LP von Lattice. Zum Synthetisieren nutze ich
Synplify Pro. Meinen Code habe ich angehängt. Dieser soll eine
verlangsamte Clock (Port: CP) und einen einmaligen Start-Puls (Port:
START) ausgeben. Der START-Puls soll dann ausgegeben werden, wenn an
START_in eine positive Flanke auftrat. Das CP-Signal soll die ganze Zeit
laufen.
Aus meiner Sicht für das Problem irrelevant, aber der Vollständigkeit
halber noch diese Infos:
Den Port clk_en brauche ich, um den externen Oszillator zu enablen.
Dieser gibt dann ein Clock-Signal an clk. Später soll die clock noch
ausgeschaltet werden können, aber für den Anfang habe ich clk_en erstmal
konstant auf HIGH gesetzt.
Meine Frage: Beim Synthetisieren bekomme ich folgende Warnung:
@W: CL169 :" --Dateipfad-- \main.vhd":48:1:48:2|Pruning unused register
START_reg. Make sure that there are no unused intermediate registers.
Was bedeutet diese Warnung?
Eine kleinere Frage noch nebenbei zu den Zeilen 55 und 56:
Brauche ich diese wirklich? Ich habe das jetzt zur Sicherheit gemacht,
damit START_reg von Anfang an definiert ist. Oder hält der FPGA den Port
automatisch auf Low, solange er undefiniert ist?
Wäre super, wenn mir da jemand weiterhelfen könnte.
Fritz W. schrieb:> Oder hält der FPGA den Port automatisch auf Low, solange er undefiniert> ist?
Was steht denn im Datenblatt?
Wenn du ein Signal deklarierst und keinen Defaultwert angibst, dann
wird das üblicherweise mit '0' initialisiert. Allerdings darf der
Synthesizer auch gern von einem beliebigen Wert ausgehen und auch mal
etwas mehr wegoptimieren. An dieser Stelle kann es dann passieren, dass
sich die Simulation und die Realität unterschiedlich verhalten.
> Was bedeutet diese Warnung?
Kurz und bündig: du verwendest keine Defaultwerte.
Die längere Version:
Xilinx XST sagt zu deinem Code
1
WARNING:Xst:647 - Input <reset> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
2
WARNING:Xst:647 - Input <START_in> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
Hoppla, START_in nicht verwendet? Der hat das alles wegoptimiert?
Klar, kann er. Denn du hast keinen Defaultwert und keinen Resetwert für
deine Signale angegeben. Deshalb darf er davon ausgehen, dass
startreceived dauerhaft auf '1' ist. Und dann wird START_in nicht
gebraucht, und dann ergeben sich noch weitere lustige Effekte...
Nach dieser Änderung hier:
1
signalCP_reg:std_logic:='0';
2
signalCP_cnt:integerrange0to1000:=0;
3
signalSTART_reg:std_logic:='0';
4
signalstartreceived:std_logic:='0';
5
signalstartsend:std_logic:='0';
Kommt dann ein
1
ERROR:Xst:827 - line 46: Signal START_reg cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
Also drehen wir die Reihenfolge dieser Beschreibung mal so um, dass auch
der Synthesizer die Struktur erkennt und nicht ein nachrangiger Reset
beschrieben wird:
1
ifstartreceived='0'then
2
START_reg<='0';
3
elsifrising_edge(CP_reg)then
4
:
5
START_reg<='1';
6
:
7
endif;
Dann verbleiben nur noch 2 Warnungen:
1
WARNING:Xst:1426 - The value init of the FF/Latch startreceived hinder the constant cleaning in the block top.
2
You should achieve better results by setting this init to 1.
3
WARNING:Xst:1426 - The value init of the FF/Latch startsend hinder the constant cleaning in the block top.
4
You should achieve better results by setting this init to 1.
Die besagen, dass man mit einem "besseren Defautlwert" so einiges
wegoptimieren könnte. Aber da kommen wir ja her... ;-)
BTW1:
Schreib nicht überall ein elsif hin:
1
ifstartsend='0'then
2
START_reg<='1';
3
startsend<='1';
4
elsifstartsend='1'then-- unnötig und gefährlich!!!
5
START_reg<='0';
6
endif;
Denn auf diese Art bleiben 7 der Zustände eines std_logic
unberücksichtigt!
Schreibe einfach ein else und fertig.
BTW2:
Dein Design hat viel zu viele Takte. Ein Drittel sollte reichen...
Wenn du einen Takt hast, dann steht nur der im gesamten Design hinter
einem rising_edge. Die restlichen Signale werden auf diesen Takt
synchronisiert und dann taktsynchron mit diesem einen Takt verarbeitet.
BTW3:
So werden in einem FPGA keine Takte erzeugt:
1
CP_reg<=notCP_reg;
Nicht umsonst hast du da auch Taktmanager mitgekauft. Oder besser noch:
arbeite mit 1 Takt und Clock-Enables.
BTW4:
Dein Zähler zählt 1001 Schritte. Der allseits beliebte off-by-one
Fehler...
BTW5:
> Aus meiner Sicht für das Problem irrelevant, aber der Vollständigkeit> halber noch diese Infos:> Den Port clk_en brauche ich, um den externen Oszillator zu enablen.> Dieser gibt dann ein Clock-Signal an clk. Später soll die clock noch> ausgeschaltet werden können
Du drehst dir damit selber den "Pulsschlag" ab. Warum das?
BTW6:
Wo ich das "main.vhd" so sehe: du programmierst dein FPGA so, wie du
einen µC programmieren würdest. Das geht schief.
Nicht umsonst heißt es VH-D-L. Du solltest zuerst mal eine Vorstellung
oder ein Bild von deiner gewünschten Hardware haben. Und diese Hardware
dann mit VHDLbeschreiben.
Danke erstmal! Das hat mich vorrangebracht.
Synplify Pro unterstützt, wie es aussieht, keine Initialwerte. Ich bekam
folgende Warnung:
@W: FX1039 :" --dateipfad-- main.vhd":35:1:35:2|User-specified initial
value defined for instance CP_cnt[9:0] is being ignored.
analog kam diese Warnung natürlich für die anderen Signale.
Ich werde mal Lattice LSE probieren. Das braucht aber Zeit, weil glaube,
dass ich die Constraint-Files dafür umschreiben muss.
Nur für mein Verständnis:
Lothar M. schrieb:> Schreib nicht überall ein elsif hin:> if startsend = '0' then> START_reg <= '1';> startsend <= '1';> elsif startsend = '1' then -- unnötig und gefährlich!!!> START_reg <= '0';> end if;> Denn auf diese Art bleiben 7 der Zustände eines std_logic> unberücksichtigt!> Schreibe einfach ein else und fertig.
Mit dem elsif wollte ich sicherstellen, dass die Zeile darunter NUR dann
ausgeführt wird, wenn startsend auch wirklich 1 ist. Alle anderen
Zustände wollte ich bewusst ausschließen. Sonst könnte die Zeile
darunter ja auch ausgeführt werden, wenn startsend einen der anderen
Zustände hat, oder?
Außerdem gibt später im FPGA doch nur die Zustände 1 und 0, die übrigen
Zustände sind doch nur für die Simulation, oder?
Fritz W. schrieb:> Außerdem gibt später im FPGA doch nur die Zustände 1 und 0, die übrigen> Zustände sind doch nur für die Simulation, oder?
Richtig, und aus diesem Grund kannst du das bedenkenlos zugunsten der
Leserlichkeit weglassen.
> Alle anderen Zustände wollte ich bewusst ausschließen.
Weil es sie nicht gibt musst du sie auch nicht beachten.
Sieh dir einfach mal anderenVHDL-Code an. Und besonders das Handbuch
zum Synthesizer. Dort steht drin, was er versteht und in Hardware
umsetzen kann, und auch, wie es dafür beschrieben sein muss.
> Sonst könnte die Zeile darunter ja auch ausgeführt werden
Schon wieder der Programmierer, dessen "Code ausgeführt" wird. Da wird
nichts "ausgeführt", sondern deine Beschreibung wird in Hardware
umgesetzt. In dieser Hardware ist jede "Codezeile" immer vorhanden und
die zugehörigen logischen Verknüfpungen werden jederzeit parallel
"ausgeführt", und die resultierenden Signale stämdig aus den aktuellen
Signalen neu "berechnet". Stell dir einfach ein UND-Gatter vor: das
"durchläuft" die UND-Funktion nicht nur bei jeder Signaländerung,
sondern es erzeugt das Ergebnis auch dann, wenn sich die Signale nicht
ändern. Aber bleib einfach dran, dann wird das schon noch... ;-)
> wenn startsend einen der anderen Zustände hat, oder?
Und was müsste dein Code machen, wenn so ein "anderer Zustand"
auftaucht? Die Augen zu und ignorieren?
Ich habe den Code jetzt mal angepasst.
Lothar M. schrieb:> So werden in einem FPGA keine Takte erzeugt: CP_reg <= not CP_reg;
zur Erzeugung des CP-Signals habe ich diese Zeile wieder benutzt. Wenn
ich dich richtig verstanden habe ist so etwas nur für interne
Clock-Signale ungünstig.
Jetzt funktioniert mein START-Signal aber garnicht mehr. Es wird immer
nur 0 ausgegeben. Woran kann das liegen? Ich kann mir das überhaupt
nicht erklären. Das CP-Signal funktioniert einwandfrei. Auch der
FPGA-Pin ist in Ordnung, ich habe das START-Signal mal an einem anderen
Pin ausgeben lassen, da war es aber das Selbe.
Synthetisieren mit Lattice LSE funktioniert. Ich bekomme aber die
Warnungen:
Warning: The terminal connectivity clk_en_pad:OUTPUTENABLE is removed
because the PIN_TYPE is configured as 011001
Warning: The terminal connectivity START_pad:OUTPUTENABLE is removed
because the PIN_TYPE is configured as 011001
Warning: The terminal connectivity CP_pad:OUTPUTENABLE is removed
because the PIN_TYPE is configured as 011001
Warning: The terminal connectivity clk_pad:OUTPUTENABLE is removed
because the PIN_TYPE is configured as 000001
WARNING - synthesis: There are no design constraints in the file
--Dateipfad-- /constraint/synthesis_settings.sdc
WARNING - synthesis: .. --Dateipfad-- main.vhd(46): Register
startreceived_40 is stuck at One. VDB-5014
WARNING - synthesis: .. --Dateipfad-- main.vhd(64): Register
startsend_44 is stuck at One. VDB-5014
WARNING - synthesis: ..--Dateipfad-- main.vhd(64): Register START_reg_43
is stuck at Zero. VDB-5013
vielleicht hat das ja etwas damit zu tun. Woher kommen eigendlich die
Nummern hinter den Signalen, z. B. startreceived_40? es gibt bei mir
doch nur ein startreceived.
Fritz W. schrieb:> because the PIN_TYPE is configured as 011001
Was hast du denn im Constraint-File angegeben?
Ich habe dein Design nochmal etwas umgearbeitet und ein komplett
synchrones Design daraus gemacht. Mir scheint auch ein Zurücksetzen des
Vorteilers im "Wartezustand" sinnvoll...
> Woher kommen eigendlich die Nummern hinter den Signalen, z. B.> startreceived_40?
Das ist eine interne Nummerierung für die verwendeten Flipflops.
BTW:
Empfiehlt das Handbuch zum Synthesizer diese Art von Clock-Enable:
1
elsifrising_edge(clk)andclock_en='1'then
2
...
Oder sollte da nicht die traditionelle Variante stehen:
1
elsifrising_edge(clk)then
2
ifclock_en='1'then
3
...
BTW2:
Hast du eine Testbench für dieses Design? Oder simulierst du das gar
nicht?
Meine beiden constraint-files habe ich mal angehängt. Ich glaube, dass
011001 für die Einstellung "-io_std SB_LVCMOS -pullup no" bei einem
Output steht, aber was soll mir diese Warnung sagen?
Eine Testbench habe ich nicht, ich teste direkt in der Hardware.
Ich habe mir auch mal mein Package View in iCECube angesehen. Das
clk-Signal war anfangs noch grün, dann habe ich die pinning.pcf neu
importiert, jetzt sind alle Inputs weiß (Screenshot liegt anbei). Die
Outputs konnte ich auch per drag and drop zuweisen, das funktioniert mit
den Inputs nicht.
Mein CP-Signal funktioniert auch nicht mehr.
Die fehlenden Input-Zuweisungen sind bestimmt die Erklärung. Aber was
ist an den Einstellungen denn noch falsch?
Fritz W. schrieb:> Ich glaube, dass 011001 für die Einstellung "-io_std SB_LVCMOS -pullup> no" bei einem Output steht, aber was soll mir diese Warnung sagen?
Dass du den da nicht verwenden kannt. Denn der hat offenbar was mit
differentieller LVDS-IO zu tun. Sowas hast du in deinem Design aber
nicht...
Ich würde da was im Stil von LVCMOS33 erwarten und einsetzen.