Hallo Community,
ich bin wie viele vor mir auch schon relativ neu im Gebiet VHDL / FPGA.
Ich versuche mir einen LED counter (ich weiß, gab's bestimmt schon
tausendmal) zu basteln.
Mein ISE-Projekt besteht aus 2 Files:
- main.vhd
- pins.ucf
Erst mal das VHDL-File:
entity MAIN is
port(
CLK: in std_logic;
RESET: in std_logic;
LED: out std_logic_vector(7 downto 0)
);
end MAIN;
--- MAIN architecture
architecture BEHAVIORAL of MAIN is
signal COUNTER: std_logic_vector (7 downto 0) := "00000000";
signal PRESCALER: std_logic_vector (20 downto 0) :=
"000000000000000000000";
begin
--- COUNTER process
COUNTER_PROCESS:process(CLK, RESET)
begin
if rising_edge(CLK) and CLK = '1' then
if RESET = '1' then
PRESCALER <= (others => '0');
COUNTER <= (others => '0');
elsif PRESCALER < "10111110101111000010000000" then
PRESCALER <= PRESCALER + 1;
else
PRESCALER <= (others => '0');
COUNTER <= COUNTER + 1;
end if;
end if;
end process;
LED <= COUNTER;
end BEHAVIORAL;
Nun das UCF:
NET "CLK" LOC = "E12" | IOSTANDARD = LVCMOS33 | PERIOD = 20.000 ;
########################################################################
######
# Discrete Indicators (LED)
########################################################################
######
NET "LED<0>" LOC = "R20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<1>" LOC = "T19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<2>" LOC = "U20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<3>" LOC = "U19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<4>" LOC = "V19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<5>" LOC = "V20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<6>" LOC = "Y22" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "LED<7>" LOC = "W21" | IOSTANDARD = LVCMOS33 | DRIVE = 8 |
SLEW = SLOW ;
NET "RESET" LOC = "T16" | IOSTANDARD = LVCMOS33 | PULLDOWN ;
Beim Implementierungsprozess kommen immer folgende Warnungen:
WARNING:PhysDesignRules:367 - The signal <CLK_IBUF> is incomplete. The
signal
does not drive any load pins in the design.
WARNING:PhysDesignRules:367 - The signal <RESET_IBUF> is incomplete. The
signal
does not drive any load pins in the design.
WARNING:Par:288 - The signal CLK_IBUF has no load. PAR will not attempt
to route this signal.
WARNING:Par:288 - The signal RESET_IBUF has no load. PAR will not
attempt to route this signal.
WARNING:Par:283 - There are 2 loadless signals in this design. This
design will cause Bitgen to issue DRC warnings.
Ich habe schon ewig danach gegoogelt, aber nichts gefunden, was ich
bisher meinem Problem zuordnen könnte.
Wie gesagt, bin Anfänger :D
Könnte mir jemand helfen, dieses Problem zu verstehen?
Vielen Dank im Voraus!!!
holyfetzer schrieb:> if rising_edge(CLK) and CLK = '1' then
Ui....copy-paste Fehler? Hast du das mal simuliert? Oder zimindest mal
versucht, dir vorzustellen, wie ein Signal aussieht, das High ist und
gleichzeitig eine Low-High Flanke hat?
Ich vermute der optimiert alles weg, weil die Bedingung eh niemals
erfüllt ist.
Ich muss mich korrigieren, es heißt natürlich nur
if rising_edge(CLK)
ich habe vorhon das geändert und so wie ich es gepostet habe ist es
nicht richtig.
------------------------------------------------------------------------
-
--- MAIN architecture
architecture BEHAVIORAL of MAIN is
signal COUNTER: std_logic_vector (7 downto 0) := "00000000";
signal PRESCALER: std_logic_vector (20 downto 0) :=
"000000000000000000000";
begin
--- COUNTER process
COUNTER_PROCESS:process(CLK, RESET)
begin
if rising_edge(CLK) then
if RESET = '1' then
PRESCALER <= (others => '0');
COUNTER <= (others => '0');
elsif PRESCALER < "10111110101111000010000000" then
PRESCALER <= PRESCALER + 1;
else
PRESCALER <= (others => '0');
COUNTER <= COUNTER + 1;
end if;
end if;
end process;
LED <= COUNTER;
end BEHAVIORAL;
------------------------------------------------------------------------
-
Aber das Problem bleibt bestehen
Und nein ich habe es noch nicht getestet, mangels HW diese Woche.
Aber ich will nächste Woche, wenn ich anfange nicht blind irgendwas
machen.
Trotzdem wundert mich diese Meldung.
Ich kann sie halt nicht interpretieren
Christian R. schrieb:>> if rising_edge(CLK) and CLK = '1' then> Ui....copy-paste Fehler? Hast du das mal simuliert?
Halb so schlimm, im rising_edge steht ..and CLK='1'.. eh schon mit
drin. Dann steht da eben ..and CLK='1' and CLK='1'..
Das ändert laut Boolscher Algebra nichts am Ergebnis... ;-)
Haste den Reset extra synchron gemacht?
Eigentlich sollte ein Reset das einzige Signal sein, dass asynchron sein
darf. Bei dir müsste es dann lauten:
--- COUNTER process
COUNTER_PROCESS:process(CLK, RESET)
begin
if RESET = '1' then
PRESCALER <= (others => '0');
COUNTER <= (others => '0');
elsif rising_edge(CLK) then
if PRESCALER < "10111110101111000010000000" then
PRESCALER <= PRESCALER + 1;
else
PRESCALER <= (others => '0');
COUNTER <= COUNTER + 1;
end if;
end if;
end process;
Vielen Dank für den Support erstmal.
Geändert hat das aber leider nicht.
Meine Frage:
Ist diese Meldung überhaupt schlimm? Ich meine es ist ja "nur" eine
Warning...
Da fällt mir auf du schreibst:
PRESCALER <= PRESCALER + 1;
COUNTER <= COUNTER + 1;
für std_logic_vector-Signale. Somit dürfte dein System Latches
produzerien. Versuch es mal mit Variablen und den dementsprechenden
Konvertierungen bei der Zuweisung auf "LED";)
Siehe auch:
http://www.mikrocontroller.net/articles/VHDL#Grundregeln_f.C3.BCr_synthetisierbaren_VHDL-Code
Speziell: "Jedes Ausgangssignal muss in jedem if-Zweig einen von sich
selbst verschiedenen Wert zugewiesen bekommen, damit keine Latches
entstehen (mein_signal <= mein_signal; ist unzulässig!) ".
Und nochmal was: Wie soll sich dein PRESCALER-Wert ändern? Du erhöhst
ihn nur wenn folgendes gilt:
elsif PRESCALER < "10111110101111000010000000" then
PRESCALER <= PRESCALER + 1;
Aber wie soll der jemals diesen Binärwert erreichen, wenn du ihn nur
unter dieser Bedingung inkrementierst?...
Das spuckt mir ModelSim Compile für dein System aus:
** Error:
C:/MentorGraphics/HDS2010.2a/examples/hds_scratch/scratch_lib/hdl/asdf_a
sdf.vhd(37): No feasible entries for infix operator "+".
** Error:
C:/MentorGraphics/HDS2010.2a/examples/hds_scratch/scratch_lib/hdl/asdf_a
sdf.vhd(37): Type error resolving infix expression "+" as type
ieee.std_logic_1164.STD_LOGIC_VECTOR.
** Error:
C:/MentorGraphics/HDS2010.2a/examples/hds_scratch/scratch_lib/hdl/asdf_a
sdf.vhd(40): No feasible entries for infix operator "+".
** Error:
C:/MentorGraphics/HDS2010.2a/examples/hds_scratch/scratch_lib/hdl/asdf_a
sdf.vhd(40): Type error resolving infix expression "+" as type
ieee.std_logic_1164.STD_LOGIC_VECTOR.
** Error:
C:/MentorGraphics/HDS2010.2a/examples/hds_scratch/scratch_lib/hdl/asdf_a
sdf.vhd(47): VHDL Compiler exiting
Also jeweils die "+" Zuweisungen...
Lothar Miller schrieb:> Christian R. schrieb:>>> if rising_edge(CLK) and CLK = '1' then>> Ui....copy-paste Fehler? Hast du das mal simuliert?> Halb so schlimm, im rising_edge steht ..and CLK='1'.. eh schon mit> drin. Dann steht da eben ..and CLK='1' and CLK='1'..> Das ändert laut Boolscher Algebra nichts am Ergebnis... ;-)
Hm, natürlich richtig. War schon spät, da hatte ich erst mal angenommen,
der könnte das eventuell wegoptimieren, hatte keine Lust mehr, das Ding
mal schnell zu simulieren.
Michl schrieb:> Eigentlich sollte ein Reset das einzige Signal sein, dass asynchron sein> darf.
Eigentlich sollte nicht mal ein Reset asynchron sein (denn asynchrone
Signale können vom Timinganalyzer nicht bewertet werden!)
Oder bestenfalls nach genauer Betrachtung der Zielplattform. Siehe z.B.
den legendären Beitrag "Xilinx und die Resets"
Wenn schon eine asynchrone Beschreibung, dann muss auf jeden Fall der
Reset einsynchronisiert werden! Denn sonst wird das Deaktivieren des
Resets interessant: ein paar Flipflops einer FSM sehen noch den Reset,
die anderen sind schon bei der Arbeit. Ein ungünstiger Start in den
Arbeitstag...
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html> Eigentlich sollte ein Reset das einzige Signal sein, dass asynchron sein> darf.
Auch wenn es in fast allen Büchern so beschrieben ist, muss es nicht
unbedingt stimmen...
Vielen Dank für die rege Diskussion. Aber leider bin ich der Lösung von
meinem Problem (gefühlt) noch nicht näher gekommen.
Ich habe mal den Code wie folgt geändert, mit dem Ziel die Takteilung
und den Counter zu trennen:
--- MAIN architecture
architecture BEHAVIORAL of MAIN is
signal SLOW_CLK : std_logic;
signal COUNTER: std_logic_vector (7 downto 0) := "00000000";
signal CLK_DIVIDER: std_logic_vector (22 downto 0) :=
"00000000000000000000000";
begin
--- Clock division
CLK_DIVISION : PROCESS (CLK, CLK_DIVIDER)
begin
if (CLK = '1' and CLK'EVENT) then
CLK_DIVIDER <= CLK_DIVIDER + 1;
end if;
SLOW_CLK <= CLK_DIVIDER(22);
end process;
--- COUNTER process
COUNTER_PROCESS:process(SLOW_CLK, RESET, COUNTER)
begin
if RESET = '1' then
COUNTER <= (others => '0');
else
if (SLOW_CLK = '1' and SLOW_CLK'EVENT) then
COUNTER <= COUNTER + 1;
end if;
end if;
end process;
end BEHAVIORAL ;
Dies behebt die Warnungen wirklich. Aber was ist wirklich der Knackpunkt
hierbei?
holyfetzer schrieb:> Aber was ist wirklich der Knackpunkt hierbei?
Dass du offenbar die Antwortposts nicht gelesen und oder verstanden
hast! Warum sollte man dir antworten, wenn du immer noch asynchrone
Resets verwendest und vor allem immer noch mit std_logic rechnest?
BTW: eine VHDL-Beschreibung fängt ganz oben an. Wie soll man wissen, als
was dein std_logic_vector interpretiert wird, wenn man nicht weiß,
welche Libs du verwendest?
Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"> if (CLK = '1' and CLK'EVENT) then> if (SLOW_CLK = '1' and SLOW_CLK'EVENT) then
Und jetzt verwendest du auch noch einen abgeleiteten Takt. Mehr dazu im
Beitrag "Re: Frequency divider Ausgang als Clock"
Sorry, wenn ich etwas unbeholfen rüberkomme. Es ist einfach nur so, dass
am Anfang nicht alles automatisch logisch ist. Besonders, wenn man aus
der Programmierecke kommt, wo eigentlich alles erst mal mehr oder
weniger richtig ist, solange die Syntax und die abstrakte Verwendung
stimmt :D
Bei FPGAs muss man eben sehr viel mehr über (Programm-)Strukturen und
Ansätze nachdenken, um etwas zu erreichen. Und ich möchte einfach die
wichtigsten Ansätze und Hintergründe verstehen, um danach, wenn ich mit
der HW arbeite, auch zu verstehen wieso etwas funktioniert (oder eben
nicht funktioniert) und wo man nach Fehlern suchen muss.
Es geht mir natürlich nicht primär darum, irgendwelche Lichtlein blinken
zu sehen. Es geht ums Verstehen.
Auch dieses Library-Wirrwarr ist natürlich etwas verwirrend zu Beginn.
Ich frage mich, warum, obwohl doch offenbar Hersteller-abhängig, werden
diese Packages sehr häufig trotzdem benutzt.
Gerade IEEE.STD_LOGIC_ARITH ist doch (von mir gefühlt) mehr Regel als
Ausnahme in allen möglichen Tutorials etc.
Naja, also ich habe nochmal etwas gelesen und den Code dahingehend
modifiziert, dass ich u.a. IEEE.STD_LOGIC_ARITH nicht mehr verwende.
Teile dieses Ansatzes kommen von der Website von Lothar Miller.
Auch dieses nicht so prickelnde Clock heruntertakten habe ich wieder
entfernt.
Den Reset habe ich nun mal komplett Clock-synchron eingeführt. Ich
denke, dass dies der bessere Weg ist.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity MAIN is
Port ( CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
LED : out STD_LOGIC_VECTOR (7 DOWNTO 0)
);
end MAIN;
architecture BEHAVIORAL of MAIN is
signal C : integer range 0 to 24999999 := 0; -- 0,5s bei 50MHz fosc
signal X : integer range 0 to 7 := 0; --- 8 bit value
begin
COUNTER : process(CLK) -- Clock process
begin
if (CLK = '1' and CLK'EVENT) then
if (RESET = '1') then -- Synchroner Reset
C <= 0; --
X <= 0;
elsif (c<24999999) then -- 0…24999999 = 25000000 Takte = 1/2
Sekunde bei 50MHz
C <= C+1; -- wenn kleiner: weiterzählen
else -- wenn Zählerende erreicht:
C <= 0; -- Zähler zurücksetzen
X <= X+1; -- und Signal x hochählen
end if;
end if;
end process;
LED <= std_logic_vector(to_unsigned(X, LED'LENGTH));-- Signal x an
LED ausgeben
Zumindest jetzt bin ich erst mal Warning-frei geworden, was sich gut
anfühlt.
holyfetzer schrieb:> Gerade IEEE.STD_LOGIC_ARITH ist doch (von mir gefühlt) mehr Regel als> Ausnahme in allen möglichen Tutorials etc.
Ja, genauso wie der asynchrone Reset...
Und sogar im von mir gern empfohlenen Buch steht noch son Zeuch vom
letzten Jahrtausend drin. Siehe den
Beitrag "Re: Verständnisproblem Xilinx XC9572 CPLD"
Im ursprünglichen Code ist der Prescaler 21 Bits breit, während der
Vergleichswert (elsif PRESCALER < "10111110101111000010000000") 26 Bit
breit ist, die Bedingung ist also vermutlich immer erfüllt und wird in
der Synthese rausgekuerzt.
Vielleicht war das das Problem?