Forum: FPGA, VHDL & Co. Lockerer Counter auf VHDL


von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

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!

von Mario R. (mario001) Benutzerseite


Lesenswert?

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 !!

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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?

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

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....

von Duke Scarring (Gast)


Lesenswert?

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

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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 :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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"

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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... :-(

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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 :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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;

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

Vielen dank!! es hat funktioniert :D! Ich bedanke mich bei euch alle 
sehr :)

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

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 :-)

von Samer A. (Firma: Personal) (thedestroyer)


Lesenswert?

OH MY GOD!! FALSHER POST HIER!!!

SORRY!!!

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.