Guten Tag :) erstens entschuldige mein Deutsch, ich bin kein Deutscher aber wohne in Deutschland. Ich fand dieses Forum auf Google und wollte hier meine Frage stellen :) ich bin ganz neu auf VHDL (ich bin C++ programmer). Ich lerne VHDL mit einfachen Beispielen, die ich auf meinem Xilinx Spartan 3AN Starter Kit implementiere. Ich habe einen einfachen Counter geschrieben auf VHDL. Den Code kann der Compiler ohne probleme compilieren, aber ein Problem kommt Am Schriit "Place & Route" in ISE Project Navigator. Die Simulation von meiner Code mit ISE hat keine Probleme. Hier ist der Code meines Counters: ------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity CounterMdl is generic( Bits : integer := 8 ); Port ( output : out STD_LOGIC_VECTOR(Bits-1 downto 0); clk : in STD_LOGIC ); end CounterMdl; architecture Behavioral of CounterMdl is signal tempNum: STD_LOGIC_VECTOR (Bits-1 downto 0) := (others => '0'); begin process(clk) begin if (clk='1' and clk'event) then tempNum <= tempNum + 1; output <= tempNum; end if; end process; end Behavioral; ------------------------------------------------- Das Problem passiert wenn ich es versuche, das Signal "clk" mit einem Switch assign zu lassen. Hier ist die UCF datei meiner Projekt: ##################################### NET "output[0]" LOC = R20; NET "output[1]" LOC = T19; NET "output[2]" LOC = U20; NET "output[3]" LOC = U19; NET "output[4]" LOC = V19; NET "output[5]" LOC = V20; NET "output[6]" LOC = Y22; NET "output[7]" LOC = W21; # PlanAhead Generated physical constraints NET "clk" LOC = V8; ####################################### V8 ist ein Switch auf dem Board. Weil ich ein Anfänger bin, weiß ich nicht wie ich das Clock langsamer machen kann, damit ich das Signal auf den LEDs sehe (natürlich kann man 50 MHz nicht sehen auf LEDs". Also, ich wollte dass ich mit jeder Änderung von diesem Switch, die nächste Nummer auf den LEDs sehen. Wenn ich die Zeile NET "clk" LOC = V8; entferne, das Synthesis bis zum Ende funktioniert es ohne Probleme. Das Error, dass ich bekomme ist: ERROR:Place:1018 - A clock IOB / clock component pair have been found that are not placed at an optimal clock IOB / clock site pair. The clock component <clk_BUFGP/BUFG> is placed at site <BUFGMUX_X1Y0>. The IO component <clk> is placed at site <IPAD279>. This will not allow the use of the fast path between the IO and the Clock buffer. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .ucf file to demote this message to a WARNING and allow your design to continue. However, the use of this override is highly discouraged as it may lead to very poor timing results. It is recommended that this error condition be corrected in the design. A list of all the COMP.PINs used in this clock placement rule is listed below. These examples can be used directly in the .ucf file to override this clock rule. < NET "clk" CLOCK_DEDICATED_ROUTE = FALSE; > und ich bekomme auch ein Warning danach: WARNING:Par:100 - Design is not completely routed. There are 23 signals that are not completely routed in this design. See the "CounterMdl.unroutes" file for a list of all unrouted signals. Check for other warnings in your PAR report that might indicate why these nets are unroutable. These nets can also be evaluated in FPGA Editor by selecting "Unrouted Nets" in the List Window. Könnt ihr mir bitte sagen warum es nicht funktioniert? was soll ich damit tun? Vielen Dank
Samer Afach schrieb: > Guten Tag :) Hallo! > Ich habe einen einfachen Counter geschrieben auf VHDL. Den Code kann der > Compiler ohne probleme compilieren, aber ein Problem kommt Am Schriit > "Place & Route" in ISE Project Navigator. Die Simulation von meiner Code > mit ISE hat keine Probleme. > > ------------------------------------------------- > > library IEEE; > use IEEE.STD_LOGIC_1164.ALL; > use IEEE.NUMERIC_STD.ALL; > use IEEE.STD_LOGIC_ARITH.ALL; > use IEEE.STD_LOGIC_UNSIGNED.ALL; Zuersmal vergiss die ieee.std_logic_* Bibliotheken. Die sind veraltet. Beschränk Dich auf use IEEE.NUMERIC_STD.ALL; Alle Rechenoperationen sind damit möglich. Allerdings musst Du bei Deinem Counter ein wenig casten, um die '+' Addition hinzubekommen. Siehe dazu: http://www.lothar-miller.de/s9y/uploads/Bilder/Usage_of_numeric_std.pdf > entity CounterMdl is > generic( Bits : integer := 8 ); > Port ( output : out STD_LOGIC_VECTOR(Bits-1 downto 0); > clk : in STD_LOGIC > ); > end CounterMdl; > > architecture Behavioral of CounterMdl is > signal tempNum: STD_LOGIC_VECTOR (Bits-1 downto 0) := (others => '0'); > begin > process(clk) > begin > if (clk='1' and clk'event) then > tempNum <= tempNum + 1; > output <= tempNum; > end if; > end process; > end Behavioral; > > V8 ist ein Switch auf dem Board. Weil ich ein Anfänger bin, weiß ich > nicht wie ich das Clock langsamer machen kann, damit ich das Signal auf > den LEDs sehe (natürlich kann man 50 MHz nicht sehen auf LEDs". Also, > ich wollte dass ich mit jeder Änderung von diesem Switch, die nächste > Nummer auf den LEDs sehen. > > Wenn ich die Zeile > > NET "clk" LOC = V8; > > entferne, das Synthesis bis zum Ende funktioniert es ohne Probleme. Das > Error, dass ich bekomme ist: > > > ERROR:Place:1018 - A clock IOB / clock component pair have been found > that are not placed at an optimal clock IOB / > clock site pair. The clock component <clk_BUFGP/BUFG> is placed at > site <BUFGMUX_X1Y0>. The IO component <clk> is > placed at site <IPAD279>. This will not allow the use of the fast > path between the IO and the Clock buffer. If this > sub optimal condition is acceptable for this design, you may use the > CLOCK_DEDICATED_ROUTE constraint in the .ucf > file to demote this message to a WARNING and allow your design to > continue. However, the use of this override is > highly discouraged as it may lead to very poor timing results. It is > recommended that this error condition be > corrected in the design. A list of all the COMP.PINs used in this > clock placement rule is listed below. These > examples can be used directly in the .ucf file to override this clock > rule. > < NET "clk" CLOCK_DEDICATED_ROUTE = FALSE; > > > und ich bekomme auch ein Warning danach: > > > WARNING:Par:100 - Design is not completely routed. There are 23 signals > that are not > completely routed in this design. See the "CounterMdl.unroutes" file > for a list of > all unrouted signals. Check for other warnings in your PAR report > that might > indicate why these nets are unroutable. These nets can also be > evaluated > in FPGA Editor by selecting "Unrouted Nets" in the List Window. > > > Könnt ihr mir bitte sagen warum es nicht funktioniert? was soll ich > damit tun? > > Vielen Dank ... ich glaube die Ursache des Problems ist das Folgende: Es können nur bestimmte Pins des FPGAs verwendet werden um einen Clock anzulegen. Du musst auf jeden Fall den Clock der vom Osziallator/Quarz auf Deinem Evaluation Board erzeugt wird als Clock über die dafür vorgesehenen Pins ins FPGA führen. Diesen (und nur diesen) Clock darfst Du dann in der Sinsitivity Liste Deines Prozesses verwenden. Das hast Du ja auch schon richtig gemacht: > process(clk) Wichtig ist dabei auch, aber auch dass hast Du ja schon richtig gemacht, dass Du anschließend auf rising/falling edge dieses Clocks abfragst: > begin > if (clk='1' and clk'event) then Den Zustand eines Schalters einzulesen ist nicht soooo einfach, wie Du Dir das vielleicht gedacht hast. Ganz gut ist das Thema hier behandelt: http://www.lothar-miller.de/s9y/archives/2-Tastenentprellung.html Gruß aus Bremen und viel Erfolg!
Hallo und willkommen im Forum! Wie Heinrich schon richtig vermutet hat, können nur bestimmte IOs als Clock-Signale verwendet werden, da diese intern auf spezielle, schnellere Routing-Leitungen gehen. In den Pin-Listen der Xilinx-FPGAs sind diese mit dem Kürzel 'GC' versehen (Global Clocks). Für deine einfachen Tests kannst du das umgehen, wenn du in deinem UCF-File noch folgende Zeile angibst: NET "clk" CLOCK_DEDICATED_ROUTE = FALSE; Dann umgeht er diesen Fehler und gibt nur eine Warnung aus. Das Design sollte dann durchlaufen. Viel Erfolg !!
Vielen Dank für eure nette Antworten, und für die Information über die Operators in VHDL :), ich habe jetzt verstanden warum das Problem passiert. Ich werde morgen im Büro die Zeile in die UCF datei schreiben und probieren :). Aber es ist mir noch nicht klar, wie der Compiler wissen kann ob das Signal ein Clock sein soll oder ein normaler Bit das von einem Schalter gesteuert sein kann? einfach sollen alles auf sensitivity list Clock Signals sein? Was wenn ich, zum Beispiel, ein Reset input auf sensitivity list anstellen möchte (wie in manche Counters oder D-Flip Flops)? ich habe solche beispiele online gesehen ohne besondere Codes. Sollen sie auch diese schnelle Leitung haben? Könnten Ihr bitte mehr erklären was die Limits für das Sensitivity list sind?
Samer Afach schrieb: > Vielen Dank für eure nette Antworten, und für die Information über die > Operators in VHDL :), > > ich habe jetzt verstanden warum das Problem passiert. Ich werde morgen > im Büro die Zeile in die UCF datei schreiben und probieren :). Aber es > ist mir noch nicht klar, wie der Compiler wissen kann ob das Signal ein > Clock sein soll oder ein normaler Bit das von einem Schalter gesteuert > sein kann? Das Synthesewerkzeug (also der Compiler) hat Hintergrundinformationen über den FPGA den Du verwendest. Er weiss genau welcher Pin für einen Clock geeignet ist. Im FPGA selber wird die Hardware hinter diesem Pin (also am Pad) anders aussehen, als hinter einem "normalen" Pin. > einfach sollen alles auf sensitivity list Clock Signals sein? In der Sensitivity List solltest Du Dich erstmal auf Clock und Reset Signale beschränken. Es sei denn Du möchtest anstatt eines sequentiellen Prozesses einen kombinatorischen Prozess erzeugen. > > Was wenn ich, zum Beispiel, ein Reset input auf sensitivity list > anstellen möchte (wie in manche Counters oder D-Flip Flops)? ich habe > solche beispiele online gesehen ohne besondere Codes. Sollen sie auch > diese schnelle Leitung haben? Ja. > Könnten Ihr bitte mehr erklären was die > Limits für das Sensitivity list sind? Im Grunde gibt es nicht viele Möglichkeiten für eine Sensitivity List (oder?) - clock -> sequentieller Prozess, kein Reset - clock und reset -> sequentieller Prozess, asynchroner/synchroner Reset (s.u.) - alle sich ändernde Signale -> kombinatorischer Prozess Das Grundgerüst für einen sequentiellen Prozess mit asynchronem Reset sieht so aus:
1 | -- purpose: Sequentieller Prozess, asynchroner Rest
|
2 | -- type : sequential
|
3 | -- inputs : clk_s, rst_s
|
4 | -- outputs:
|
5 | seq_p: process (clk_s, rst_s) is |
6 | begin -- process asdf |
7 | if rst_s = '1' then -- asynchronous reset (active high) |
8 | |
9 | elsif rising_edge(clk_s) then -- rising clock edge |
10 | |
11 | end if; |
12 | end process seq_p; |
Das Grundgerüst für einen sequentiellen Prozess mit synchronem Reset sieht so aus:
1 | -- purpose: Sequentieller Prozess, synchroner Rest
|
2 | -- type : sequential
|
3 | -- inputs : clk_s, rst_s
|
4 | -- outputs:
|
5 | seq_p : process (clk_s, rst_s) is |
6 | begin -- process asdf |
7 | |
8 | elsif rising_edge(clk_s) then -- rising clock edge |
9 | if rst_s = '1' then -- synchronous reset (active high) |
10 | |
11 | else
|
12 | |
13 | end if; |
14 | end if; |
15 | end process seq_p; |
Am Anfang würde ich Dir vielleicht raten, Dich auf sequentielle Prozesse zu beschränken. Im Allgemeinen wird im Moment empfohlen bei einem sequentiellen Prozess einen synchronen Reset zu verwenden. Gruß, H
Heinrich H. schrieb: >> use IEEE.STD_LOGIC_1164.ALL; >> use IEEE.STD_LOGIC_ARITH.ALL; >> use IEEE.STD_LOGIC_UNSIGNED.ALL; > Zuersmal vergiss die ieee.std_logic_* Bibliotheken. Die sind veraltet. Naja, die use IEEE.STD_LOGIC_1164.ALL; kann schon drinbleiben... Samer Afach schrieb: > Könnten Ihr bitte mehr erklären was die > Limits für das Sensitivity list sind? Die Sensitiv-Liste ist NUR für den Simulator interessant!!! Der berechnet dann den Prozess neu, wenn sich der Zustand eines der Signale ändert. Ein fehlendes Signal in der Sensitivliste ergibt unbedingt eine falsche Simulation. Die Synthese gibt bei einer unvollständigen Sensitivliste eine Warnung/Info aus und fügt das Signal selbständig ein.
Lothar Miller schrieb: > Heinrich H. schrieb: >>> use IEEE.STD_LOGIC_1164.ALL; >>> use IEEE.STD_LOGIC_ARITH.ALL; >>> use IEEE.STD_LOGIC_UNSIGNED.ALL; >> Zuersmal vergiss die ieee.std_logic_* Bibliotheken. Die sind veraltet. > Naja, die > use IEEE.STD_LOGIC_1164.ALL; > kann schon drinbleiben... Das ist natürlich richtig... **Schäm > > Samer Afach schrieb: >> Könnten Ihr bitte mehr erklären was die >> Limits für das Sensitivity list sind? > Die Sensitiv-Liste ist NUR für den Simulator interessant!!! Das wusste ich nicht. Ich dachte basierend auf der kompletten Prozessstruktur INKLUSIVE Sensitivity List erzeugt das Synthesetool mir die gewünschte HW. Kann ich dann im Umkehrschluss in der Sensitivity List irgendwelche Signale packen, clock und reset explizit nicht mit aufnehmen und dann auf clock/reset abfragen? > Der berechnet dann den Prozess neu, wenn sich der Zustand eines der > Signale ändert. Ein fehlendes Signal in der Sensitivliste ergibt > unbedingt eine falsche Simulation. Die Synthese gibt bei einer > unvollständigen Sensitivliste eine Warnung/Info aus und fügt das Signal > selbständig ein. Verstehe. Damit ist obige Frage wohl auch beantwortet....
Heinrich H. schrieb: > Kann ich dann im Umkehrschluss in der Sensitivity List irgendwelche > Signale packen, clock und reset explizit nicht mit aufnehmen und dann > auf clock/reset abfragen? Ja kannst Du. Ist aber nur lehrreich um zu sehen, daß sich der Simulator dann "komisch" verhält. Duke
Vielen Dank, die Lösung von UCF detei Zeile hat funktioniert :) Aber der Counter funktioniert falsch (es zählt nicht so einfach als +1), weil wie Heinrich gesagt hat, die Schalter sind kompliziert. Also werde bis zum Ende des Tages versuchen es zum Laufen zu kriegen, und wenn ich ein Problem habe, poste ich es hier! Danke wieder :)
Heinrich H. schrieb: > Kann ich dann im Umkehrschluss in der Sensitivity List irgendwelche > Signale packen, clock und reset explizit nicht mit aufnehmen und dann > auf clock/reset abfragen? Das hatten wir schon ein paar mal: http://www.mikrocontroller.net/search?query=sensitivity+list+unvollständige http://www.mikrocontroller.net/search?query=sensitivliste+unvollständige Und Xilinx (und andere auch) hat da auch Probleme z.B. mit Variablen in Prozessen und der zugehörigen Sensitiv-Liste: Beitrag "Re: Variable vs Signal"
Hallo wieder :) Ich hab ein noch 3 Fragen :). Also die erste ist mit einem Counter, der jede Sekunde zählt. Ich habs so Codiert wie das Folgende. Die Frage ist, gibt es eine schlauere Methode, damit man eine Sekunde warten kann? ---------------------------------------------------------- -- Clock ist 50 MHz entity CounterMdl is generic( Bits : integer := 8 ); Port ( output : out STD_LOGIC_VECTOR(Bits-1 downto 0); clk : in STD_LOGIC ); end CounterMdl; architecture Behavioral of CounterMdl is signal tempNum: STD_LOGIC_VECTOR (Bits-1 downto 0) := (others => '0'); signal clkCounter : integer range 0 to 1000001; signal clkCounter2: integer range 0 to 51; begin process(clk) begin if rising_edge(clk) then clkCounter <= clkCounter + 1; if clkCounter >= 1000000 then clkCounter <= 0; clkCounter2 <= clkCounter2 + 1; if clkCounter2 >= 50 then tempNum <= tempNum + 1; output <= tempNum; clkCounter <= 0; clkCounter2 <= 0; end if; end if; end if; end process; end Behavioral; ----------------------------------------------------------- Die zweite Frage ist mit dem vorherigen Beispiel. Ich habe es mit einem Push-Button gemacht, aber mit einem Clock. Bitte siehe den folgenden Code: ----------------------------------------------------------- entity CounterMdl is generic( Bits : integer := 8 ); Port ( output : out STD_LOGIC_VECTOR(Bits-1 downto 0); clk : in STD_LOGIC; inKey : in STD_LOGIC ); end CounterMdl; architecture Behavioral of CounterMdl is signal tempNum: STD_LOGIC_VECTOR (Bits-1 downto 0) := (others => '0'); signal inKeyOld : STD_LOGIC; signal counter : integer range 0 to 1000001 := 0; constant timeToWait : integer := 50000; begin process(clk) begin if rising_edge(clk) then if(counter >= 1000000) then counter <= timeToWait; else counter <= counter + 1; end if; if (inKey='1' and inKeyOld='0' and counter >= timeToWait) then tempNum <= tempNum + 1; output <= tempNum; counter <= 0; end if; inKeyOld <= inKey; end if; end process; end Behavioral; -------------------------------------------------------------- Es gibt damit anscheinend ein Problem von Prellen mit dem Push-Button, manchmal wenn ich drücke, zählt es zwei oder drei mal zusammen. Den Code hab ich geschrieben, damit es nicht schnell zählt (mit dem Variable timeToWait), es funktioniert aber nicht gut genug. Was könnt ihr für solches Problem vorschlägen? :) -------------------------------------------------------------- Letzte Frage ist mit NUMERIC_STD. Das kann man doch nicht benutzen mit VHDL93, oder? als ich STD_LOGIC_* entfernt habe, hat das Sythesiswerkzeug ein Problem und hat den Operator nicht akzeptiert. Ich benutze VHDL93 weil ich ein Buch befolge! Vielen Dank!
Samer Afach schrieb: > Die Frage ist, > gibt es eine schlauere Methode, damit man eine Sekunde warten kann? Im Prinzip nicht. Du brauchst einen Zähler, der die Sekunde durchzählt. > Letzte Frage ist mit NUMERIC_STD. Das kann man doch nicht benutzen mit > VHDL93, oder? Doch, klar geht das. > als ich STD_LOGIC_* entfernt habe, hat das Sythesiswerkzeug ein Problem > und hat den Operator nicht akzeptiert. Nein, DU hast ein Problem. Nämlich das, zu erkennen, dass die numeric_std keine 2 std_logic Vektoren addieren kann. Du mußt dafür unsigned/singed nehmen oder den std_logic Vektor entsprechend casten. Wie das geht, wurde schon im Beitrag "Re: Lockerer Counter auf VHDL" angesprochen. Du mußt nur mal die Links ansehen. Samer Afach schrieb: > Es gibt damit anscheinend ein Problem von Prellen mit dem Push-Button, > manchmal wenn ich drücke, zählt es zwei oder drei mal zusammen. Das nennt sich Tasterprellen. Dafür Brauchst du eine Tasterentprellung. > Den Code hab ich geschrieben, damit es nicht schnell zählt > (mit dem Variable timeToWait), es funktioniert aber nicht gut genug. Ja, das ist Murks. > Was könnt ihr für solches Problem vorschlägen? Leis mal den Beitrag "Re: Lockerer Counter auf VHDL" Als kleiner Tipp: du mußt nur mal die Links ansehen. Mal eine Frage: Liest du die Antworten überhaupt durch? Schon in der ersten Antwort auf deine Frage sind beide hier aufgetretenen Fragen beantwortet... :-(
Vielen Dank für die Antwort. Ja man, ich lese sie, und schaue die links. Die Idee vom Zweiten Counter hab ich von einem Link von Heinrich genommen, es funktioniert aber nicht gut genug und deswegen hab ich die frage gestellt. Aber über die Letzte Frage, ich dachte das numric_std alles tun kann, war falsch. Vielleicht hab ich es falsch verstehen weil Deutsch nicht gut genug ist, das kommt vor xD Vielen Dank Leute :)
Samer Afach schrieb: > ich dachte das numeric_std alles tun kann Nein, numeric_std kennt nur die Datentypen integer, signed/unsigned Vektoren und std_logic_vector. Und Rechnen kann man nur mit integer oder den signed/unsigned Vektoren. Samer Afach schrieb: > Die Idee vom Zweiten Counter hab ich von einem Link von Heinrich genommen, > es funktioniert aber nicht gut genug Was funktioniert da nicht? Was sagt die Simulation?
Die Simulation funktioniert wie es sollte, aber wenn ich den Push-Button drücke auf dem Board (für die Binär nummer auf LEDs hochzuzahlen), zählt es manchmal mehr als +1, vielleicht 2 or 3 Zahlen höher!
Samer Afach schrieb: > aber wenn ich den Push-Button > drücke auf dem Board (für die Binär nummer auf LEDs hochzuzahlen), zählt > es manchmal mehr als +1, vielleicht 2 or 3 Zahlen höher! Das kommt daher, dass ein Taster beim Betätigen prellt, und schnell nacheinenader (<10ms) mehrere steigende Flanken produziert. Probiers einfach mal so:
1 | entity CounterMdl is |
2 | generic( Bits : integer := 8 ); |
3 | Port ( output : out STD_LOGIC_VECTOR(Bits-1 downto 0); |
4 | clk : in STD_LOGIC; |
5 | inKey : in STD_LOGIC |
6 | );
|
7 | end CounterMdl; |
8 | |
9 | architecture Behavioral of CounterMdl is |
10 | signal tempNum: unsigned (Bits-1 downto 0) := (others => '0'); |
11 | signal inKeyOld : STD_LOGIC; |
12 | signal counter : integer range 0 to 499999 := 0; |
13 | begin
|
14 | |
15 | process(clk) begin |
16 | if rising_edge(clk) then |
17 | if(counter < 499999) then -- 10ms Zähler |
18 | counter <= counter + 1; |
19 | else
|
20 | counter <= 0; |
21 | if (inKey='1' and inKeyOld='0') then |
22 | tempNum <= tempNum + '1'; |
23 | -- output <= tempNum; -- das ergibt einen Tastendruck LATENCY!!!
|
24 | end if; |
25 | inKeyOld <= inKey; |
26 | end if; |
27 | end if; |
28 | end process; |
29 | |
30 | output <= std_logic_vector(tempNum); -- Zuweisung an Ausgang als Concurrent Statement!!! |
31 | |
32 | end Behavioral; |
Dmit wird nicht in JEDEM Takt nach einer steigenden Flanke geschaut,
sondern der Taster wird nur noch 1x pro 500000 Zählschritte (bei 50MHz
also 10ms) abgefragt.
> gibt es eine schlauere Methode, damit man eine Sekunde warten kann?
1 | ----------------------------------------------------------
|
2 | -- Clock ist 50 MHz
|
3 | |
4 | entity CounterMdl is |
5 | generic( Bits : integer := 8 ); |
6 | Port ( output : out STD_LOGIC_VECTOR(Bits-1 downto 0); |
7 | clk : in STD_LOGIC |
8 | );
|
9 | end CounterMdl; |
10 | |
11 | architecture Behavioral of CounterMdl is |
12 | signal tempNum: unsigned (Bits-1 downto 0) := (others => '0'); |
13 | signal ThisIsOneSecond : STD_LOGIC; |
14 | signal clkCounter : integer range 0 to 49999999; |
15 | begin
|
16 | process(clk) begin -- 1 Sekunde erzeugen |
17 | if rising_edge(clk) then |
18 | if clkCounter < 49999999 then -- 1 sec Zähler |
19 | clkCounter <= clkCounter + 1; |
20 | ThisIsOneSecond <= '0'; |
21 | else
|
22 | clkCounter <= 0; |
23 | ThisIsOneSecond <= '1'; |
24 | end if; |
25 | end if; |
26 | end process; |
27 | |
28 | process(clk) begin -- 1x pro Sekunde Zähler hochzählen |
29 | if rising_edge(clk) then |
30 | if ThisIsOneSecond = '1' then |
31 | tempNum <= tempNum + '1'; |
32 | end if; |
33 | end if; |
34 | end process; |
35 | |
36 | output <= std_logic_vector(tempNum); -- Zuweisung an Ausgang |
37 | |
38 | end Behavioral; |
Vielen dank!! es hat funktioniert :D! Ich bedanke mich bei euch alle sehr :)
Hallo wieder :-), ich habe viele änderungen gemacht, nachdem ich die Seiten gelesen habe, die du mir vorgeschlagen hast :-). Im bezug von kombinatorischen Schleifen, ich habe es gesehen, dass das Synthesiswerkzeug automatisch die auf einen Addierer konvertiert. Es sagt während des Synthesisprozess: "Found 32-bit adder for signal <conv_pulse_counter_var$addsub0000> created at line 115." Alle kombinatorische Schleifen bekommen diese Behandlung. Vorher, als ich eine Frage über einen Counter hier gestellt habe, hat jemand diese Webseite mir gegeben> http://www.lothar-miller.de/s9y/archives/2-Tastenentprellung.html damit ich einen Counter mit Switch machen kann ohne Prellen. Darin gibt es eine kombinatorische Schleife. Ich verstehe nicht warum dort es erlaubt ist, und hier nicht. Kannst du bitte erklären? Ich habe auch das State machine in einem Process geschrieben, nicht mehr zwei :-), und die großgeschriebene Namen habe ich korrigiert :-), nur konstante haben großgeschriebene Buchstaben. Kannst du bitte einen Augenblick auf dem neuen Code haben, und mir sagen ob solcher Code für den SPI funktionieren würde, den man im User Guide auf Seite 76 findet? Die Simulation zeigt gute Ergebnisse. Ich mache mir sorge nur um das erste Input von Analog voltage Vin1. Das BarOut ist der Ergebnis, den ich als Bar graph auf 8 leds sehen möchte, für jeden Analog input. Hier ist das User Guide: http://www.xilinx.com/support/documentation/boards_and_kits/ug334.pdf Ich bekomme gute Ergebnisse auf Simulation (angeblich), aber trotzdem gibt das Synthesiswerkzeug komische Warnungen. Es sagt dass, z.B., BarOut_0 ein Konstant ist. Und auch dataBuffer1_VAR unverbunden ist... ich verstehe nicht wie das konstant sein kann, wenn es durch ein State geändert werden würde!!! WARNING:Xst:1710 - FF/Latch <BarOut_0> (without init value) has a constant value of 0 in block <ADCModule>. This FF/Latch will be trimmed during the optimization process. WARNING:Xst:2677 - Node <dataBuffer1_VAR_2> of sequential type is unconnected in block <ADCModule>. WARNING:Xst:2677 - Node <dataBuffer1_VAR_0> of sequential type is unconnected in block <ADCModule>. WARNING:Xst:2677 - Node <dataBuffer1_VAR_1> of sequential type is unconnected in block <ADCModule>. ... Vielen Dank. Hier ist der Code und das Test Bench:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use STD.textio.all; |
4 | use IEEE.std_logic_textio.all; |
5 | |
6 | -- Uncomment the following library declaration if using
|
7 | -- arithmetic functions with Signed or Unsigned values
|
8 | use IEEE.NUMERIC_STD.ALL; |
9 | |
10 | -- Uncomment the following library declaration if instantiating
|
11 | -- any Xilinx primitives in this code.
|
12 | --library UNISIM;
|
13 | --use UNISIM.VComponents.all;
|
14 | |
15 | entity ADCModule is |
16 | Generic(BarSteps : Integer := 8; regBits : Integer := 14); |
17 | Port ( ad_conv : OUT STD_LOGIC; |
18 | SPI_SCK : OUT STD_LOGIC; |
19 | AD_DOUT : IN STD_LOGIC; |
20 | BarOut : OUT STD_LOGIC_VECTOR(BarSteps-1 downto 0); |
21 | CLK : IN STD_LOGIC |
22 | );
|
23 | end ADCModule; |
24 | |
25 | architecture Behavioral of ADCModule is |
26 | CONSTANT AD_CONV_PULSE_LENGTH : INTEGER := 0; --constants defining number of pulsess for each state |
27 | CONSTANT AD_CONV_WAIT_LENGTH : INTEGER := 0; |
28 | CONSTANT SPI_CLK_EN_LENGTH : INTEGER := 0; |
29 | CONSTANT DATA_AC1_LENGTH : INTEGER := 14; |
30 | CONSTANT DATA_AC_WAIT_LENGTH : INTEGER := 0; |
31 | CONSTANT DATA_AC2_LENGTH : INTEGER := 14; |
32 | CONSTANT SPI_CLK_END_LENGTH : INTEGER := 0; |
33 | CONSTANT SPI_END_WAIT_LENGTH : INTEGER := 3; |
34 | |
35 | |
36 | TYPE states is (ad_conv_pulse_state, ad_conv_wait_state, spi_clk_en_state, data_ac1_state, data_ac_wait_state, data_ac2_state, spi_clk_end_state, spi_end_wait_state); |
37 | SIGNAL pr_state : states := ad_conv_pulse_state; |
38 | SIGNAL nx_state: states; |
39 | SIGNAL spi_clk_en, ad_conv_en : STD_LOGIC; --bits defining the state of SPI_CLK and ad_conv being enabled or disabled. Usage is defined in StateControl process. |
40 | SIGNAL dataBuffer1, dataBuffer2 : STD_LOGIC_VECTOR(regBits-1 downto 0) := (others => '0'); |
41 | SIGNAL temp : INTEGER := 0; |
42 | |
43 | |
44 | |
45 | -- states description:
|
46 | |
47 | -- I defined here a Zero state as the state where both SPI_SCK and ad_conv = 0.
|
48 | |
49 | -- ad_conv_pulse_state: State defined in Fig. 9-6 by the pulse, whose length is minimum equals 4 ns.
|
50 | -- ad_conv_wait_state: State defined in Fig. 9-6, by the Zero state between the pulse of ad_conv and the first pulse of SPI_SCK.
|
51 | -- spi_clk_en_state: Stated that has SPI_SCK enabled till the beginning of data reception.
|
52 | -- data_ac1_state: State that receives the first bunch of data.
|
53 | -- data_ac_wait_state: Stated defined in Fig. 9-6 by the Zero state between the reception of the two bunches of data.
|
54 | -- data_ac2_state: State that receives the second bunch of data.
|
55 | -- spi_clk_end_state: State that keeps the remenant of SPI_CLK pulses there.
|
56 | -- spi_end_wait_state: A Zero state till the repetition of the whole operation.
|
57 | begin
|
58 | ad_conv <= ad_conv_en; |
59 | SPI_SCK <= clk AND spi_clk_en; |
60 | StateContol: |
61 | process(clk) |
62 | VARIABLE dataBuffer1_VAR, dataBuffer2_VAR : STD_LOGIC_VECTOR(regBits-1 downto 0) := (others => '0'); |
63 | VARIABLE ad_conv_en_var, spi_clk_en_var : STD_LOGIC := '0'; |
64 | VARIABLE conv_pulse_counter_var : INTEGER := 0; -- counter for every state for timing |
65 | VARIABLE ad_conv_wait_counter_var : INTEGER := 0; |
66 | VARIABLE spi_clk_en_counter_var : INTEGER := 0; |
67 | VARIABLE data_ac1_counter_var : INTEGER := 0; |
68 | VARIABLE data_ac_wait_counter_var : INTEGER := 0; |
69 | VARIABLE data_ac2_counter_var : INTEGER := 0; |
70 | VARIABLE spi_clk_end_counter_var : INTEGER := 0; |
71 | VARIABLE spi_end_wait_counter_var : INTEGER := 0; |
72 | |
73 | variable my_line : line; |
74 | begin
|
75 | |
76 | if (rising_edge(clk)) then |
77 | |
78 | pr_state <= nx_state; |
79 | |
80 | |
81 | case pr_state is -- in every state, all counters are reset to avoid having latches, but not the one getting counted over in the current state |
82 | when ad_conv_pulse_state => |
83 | ad_conv_wait_counter_var := 0; |
84 | spi_clk_en_counter_var := 0; |
85 | data_ac1_counter_var := 0; |
86 | data_ac_wait_counter_var := 0; |
87 | data_ac2_counter_var := 0; |
88 | spi_clk_end_counter_var := 0; |
89 | spi_end_wait_counter_var := 0; |
90 | |
91 | ad_conv_en_var := '1'; |
92 | spi_clk_en_var := '0'; |
93 | if (conv_pulse_counter_var < AD_CONV_PULSE_LENGTH) then |
94 | --write(my_line, conv_pulse_counter_var);
|
95 | --writeline(output, my_line);
|
96 | conv_pulse_counter_var := conv_pulse_counter_var + 1; |
97 | --write(my_line, conv_pulse_counter_var);
|
98 | --writeline(output, my_line);
|
99 | else
|
100 | nx_state <= ad_conv_wait_state; |
101 | end if; |
102 | |
103 | |
104 | when ad_conv_wait_state => |
105 | conv_pulse_counter_var := 0; |
106 | spi_clk_en_counter_var := 0; |
107 | data_ac1_counter_var := 0; |
108 | data_ac_wait_counter_var := 0; |
109 | data_ac2_counter_var := 0; |
110 | spi_clk_end_counter_var := 0; |
111 | spi_end_wait_counter_var := 0; |
112 | |
113 | ad_conv_en_var := '0'; |
114 | spi_clk_en_var := '0'; |
115 | if (ad_conv_wait_counter_var < AD_CONV_WAIT_LENGTH) then |
116 | --write(my_line, ad_conv_wait_counter_var);
|
117 | --writeline(output, my_line);
|
118 | ad_conv_wait_counter_var := ad_conv_wait_counter_var + 1; |
119 | else
|
120 | nx_state <= spi_clk_en_state; |
121 | end if; |
122 | |
123 | --write(my_line, string'("Hello"));
|
124 | --writeline(output, my_line);
|
125 | |
126 | |
127 | when spi_clk_en_state => |
128 | conv_pulse_counter_var := 0; |
129 | ad_conv_wait_counter_var := 0; |
130 | data_ac1_counter_var := 0; |
131 | data_ac_wait_counter_var := 0; |
132 | data_ac2_counter_var := 0; |
133 | spi_clk_end_counter_var := 0; |
134 | spi_end_wait_counter_var := 0; |
135 | |
136 | ad_conv_en_var := '0'; |
137 | spi_clk_en_var := '1'; |
138 | if (spi_clk_en_counter_var < SPI_CLK_EN_LENGTH) then |
139 | spi_clk_en_counter_var := spi_clk_en_counter_var + 1; |
140 | else
|
141 | nx_state <= data_ac1_state; |
142 | end if; |
143 | |
144 | |
145 | when data_ac1_state => |
146 | conv_pulse_counter_var := 0; |
147 | ad_conv_wait_counter_var := 0; |
148 | spi_clk_en_counter_var := 0; |
149 | data_ac_wait_counter_var := 0; |
150 | data_ac2_counter_var := 0; |
151 | spi_clk_end_counter_var := 0; |
152 | spi_end_wait_counter_var := 0; |
153 | |
154 | ad_conv_en_var := '0'; |
155 | spi_clk_en_var := '1'; |
156 | if (data_ac1_counter_var < DATA_AC1_LENGTH) then |
157 | --if (data_ac1_counter_var < regBits) then
|
158 | -- write(my_line, data_ac1_counter_var);
|
159 | -- writeline(output, my_line);
|
160 | -- write(my_line, DATA_AC1_LENGTH);
|
161 | -- writeline(output, my_line);
|
162 | -- write(my_line, DATA_AC1_LENGTH);
|
163 | -- writeline(output, my_line);
|
164 | --
|
165 | dataBuffer1_VAR(regBits - data_ac1_counter_var - 1) := AD_DOUT; |
166 | --end if;
|
167 | data_ac1_counter_var := data_ac1_counter_var + 1; |
168 | else
|
169 | nx_state <= data_ac_wait_state; |
170 | end if; |
171 | |
172 | |
173 | when data_ac_wait_state => |
174 | conv_pulse_counter_var := 0; |
175 | ad_conv_wait_counter_var := 0; |
176 | spi_clk_en_counter_var := 0; |
177 | data_ac1_counter_var := 0; |
178 | data_ac2_counter_var := 0; |
179 | spi_clk_end_counter_var := 0; |
180 | spi_end_wait_counter_var := 0; |
181 | |
182 | ad_conv_en_var := '0'; |
183 | spi_clk_en_var := '1'; --here switch back to 1 during tests |
184 | if (data_ac_wait_counter_var < DATA_AC_WAIT_LENGTH) then |
185 | data_ac_wait_counter_var := data_ac_wait_counter_var + 1; |
186 | else
|
187 | nx_state <= data_ac2_state; |
188 | end if; |
189 | |
190 | |
191 | when data_ac2_state => |
192 | conv_pulse_counter_var := 0; |
193 | ad_conv_wait_counter_var := 0; |
194 | spi_clk_en_counter_var := 0; |
195 | data_ac1_counter_var := 0; |
196 | data_ac_wait_counter_var := 0; |
197 | spi_clk_end_counter_var := 0; |
198 | spi_end_wait_counter_var := 0; |
199 | |
200 | ad_conv_en_var := '0'; |
201 | spi_clk_en_var := '1'; |
202 | if (data_ac2_counter_var < DATA_AC2_LENGTH) then |
203 | --if (data_ac2_counter_var < regBits) then
|
204 | dataBuffer2_VAR(regBits - data_ac2_counter_var - 1) := AD_DOUT; |
205 | --end if;
|
206 | data_ac2_counter_var := data_ac2_counter_var + 1; |
207 | else
|
208 | nx_state <= spi_clk_end_state; |
209 | end if; |
210 | |
211 | |
212 | when spi_clk_end_state => |
213 | conv_pulse_counter_var := 0; |
214 | ad_conv_wait_counter_var := 0; |
215 | spi_clk_en_counter_var := 0; |
216 | data_ac1_counter_var := 0; |
217 | data_ac_wait_counter_var := 0; |
218 | data_ac2_counter_var := 0; |
219 | spi_end_wait_counter_var := 0; |
220 | |
221 | ad_conv_en_var := '0'; |
222 | spi_clk_en_var := '1'; |
223 | if (spi_clk_end_counter_var < SPI_CLK_END_LENGTH) then |
224 | spi_clk_end_counter_var := spi_clk_end_counter_var + 1; |
225 | else
|
226 | nx_state <= spi_end_wait_state; |
227 | end if; |
228 | |
229 | when spi_end_wait_state => |
230 | conv_pulse_counter_var := 0; |
231 | ad_conv_wait_counter_var := 0; |
232 | spi_clk_en_counter_var := 0; |
233 | data_ac1_counter_var := 0; |
234 | data_ac_wait_counter_var := 0; |
235 | data_ac2_counter_var := 0; |
236 | spi_clk_end_counter_var := 0; |
237 | |
238 | ad_conv_en_var := '0'; |
239 | spi_clk_en_var := '0'; |
240 | if (spi_end_wait_counter_var < SPI_END_WAIT_LENGTH) then |
241 | spi_end_wait_counter_var := spi_end_wait_counter_var + 1; |
242 | else
|
243 | nx_state <= ad_conv_pulse_state; |
244 | end if; |
245 | end case; |
246 | temp <= conv_pulse_counter_var; |
247 | ad_conv_en <= ad_conv_en_var; |
248 | spi_clk_en <= spi_clk_en_var; |
249 | if(pr_state = spi_end_wait_state) then |
250 | dataBuffer1 <= dataBuffer1_VAR; |
251 | dataBuffer2 <= dataBuffer2_VAR; |
252 | end if; |
253 | end if; |
254 | end process; |
255 | process(ad_conv_en) |
256 | VARIABLE barVec : STD_LOGIC_VECTOR(barSteps-1 downto 0) := (others => '0'); |
257 | VARIABLE count : INTEGER := 0; |
258 | begin
|
259 | if (rising_edge(ad_conv_en)) then |
260 | For count in 0 to barSteps - 1 loop |
261 | if (unsigned(dataBuffer1) < (2048*count)) then |
262 | barVec(count) := '1'; |
263 | else
|
264 | barVec(count) := '0'; |
265 | end if; |
266 | end loop; |
267 | BarOut <= barVec; |
268 | end if; |
269 | end process; |
270 | end Behavioral; |
-----------------Test Bench-----------------------
1 | LIBRARY ieee; |
2 | USE ieee.std_logic_1164.ALL; |
3 | use STD.textio.all; |
4 | use IEEE.std_logic_textio.all; |
5 | |
6 | -- Uncomment the following library declaration if using
|
7 | -- arithmetic functions with Signed or Unsigned values
|
8 | USE ieee.numeric_std.ALL; |
9 | |
10 | ENTITY ADCModuleTestBench IS |
11 | END ADCModuleTestBench; |
12 | |
13 | ARCHITECTURE behavior OF ADCModuleTestBench IS |
14 | |
15 | -- Component Declaration for the Unit Under Test (UUT)
|
16 | |
17 | COMPONENT ADCModule |
18 | PORT( |
19 | AD_CONV : OUT std_logic; |
20 | SPI_SCK : OUT std_logic; |
21 | AD_DOUT : IN std_logic; |
22 | BarOut : OUT std_logic_vector(7 downto 0); |
23 | CLK : IN std_logic |
24 | );
|
25 | END COMPONENT; |
26 | |
27 | |
28 | --Inputs
|
29 | signal AD_DOUT : std_logic := '0'; |
30 | signal CLK : std_logic := '0'; |
31 | |
32 | --Outputs
|
33 | signal AD_CONV : std_logic; |
34 | signal SPI_SCK : std_logic; |
35 | signal BarOut : std_logic_vector(7 downto 0); |
36 | constant numtoconv : std_logic_vector(13 downto 0) := std_logic_vector(to_unsigned(10922,14)); |
37 | |
38 | -- Clock period definitions
|
39 | constant CLK_period : time := 20 ns; |
40 | |
41 | BEGIN
|
42 | |
43 | -- Instantiate the Unit Under Test (UUT)
|
44 | uut: ADCModule PORT MAP ( |
45 | AD_CONV => AD_CONV, |
46 | SPI_SCK => SPI_SCK, |
47 | AD_DOUT => AD_DOUT, |
48 | BarOut => BarOut, |
49 | CLK => CLK |
50 | );
|
51 | |
52 | -- Clock process definitions
|
53 | CLK_process :process |
54 | begin
|
55 | CLK <= '0'; |
56 | wait for CLK_period/2; |
57 | CLK <= '1'; |
58 | wait for CLK_period/2; |
59 | end process; |
60 | |
61 | |
62 | -- Stimulus process
|
63 | stim_proc: process(AD_CONV,SPI_SCK) |
64 | variable clk_count : integer := 0; |
65 | variable indexcount : integer := 14; |
66 | variable my_line : line; |
67 | begin
|
68 | -- hold reset state for 100 ns.
|
69 | if(rising_edge(ad_conv))then |
70 | clk_count := 0; |
71 | indexcount := 14; |
72 | end if; |
73 | if(rising_edge(spi_sck))then |
74 | write(my_line, clk_count); |
75 | writeline(output, my_line); |
76 | write(my_line, indexcount); |
77 | writeline(output, my_line); |
78 | |
79 | If (clk_count < 2) then |
80 | clk_count := clk_count + 1; |
81 | else
|
82 | if (indexcount = 0) then |
83 | --clk_count := 0;
|
84 | --indexcount := 14;
|
85 | else
|
86 | AD_DOUT <= numtoconv(indexcount - 1); |
87 | indexcount := indexcount - 1; |
88 | end if; |
89 | end if; |
90 | |
91 | -- insert stimulus here
|
92 | end if; |
93 | end process; |
94 | |
95 | END; |
Ich bedanke mich sehr bei deinem Geduld :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.