Forum: FPGA, VHDL & Co. LED-Zähler mit Xilinx CPLD


von Holger (Gast)


Lesenswert?

Hallo,

für ein größeres Projekt möchte ich erstmal etwas kleiner Anfangen:

Also in ein Xilinx CPLD 9536 oder 9572 soll ein 8-Bit Binärzähler rein.
Die 8 Bits sollen direkt eine Low-Current-LED antreiben.

Eingangssignale:
-Clock
-Reset

Ausgang:
-8*LED

Dieser Zähler soll dann später auf 16 oder sogar 32 Bit erweitert
werden.


Wie läßt sich das mit VHDL realisieren? Welche Bücher/Tutorials sind
empfehelendswert?


Gruß
Holger

von Xenu (Gast)


Lesenswert?

>Wie läßt sich das mit VHDL realisieren?

Na so:


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity counter is

  port
  (
    clk : in std_logic;
    rst : in std_logic;
    q   : out std_logic_vector(7 downto 0)
  );

end counter;
------------------------------------------------
architecture counter_arch of counter is

  signal count : std_logic_vector(7 downto 0);

begin
------------------------------------------------
process (clk,rst)
begin

  if(rst = '0') then
     count <= (others => '0');
  elsif(rising_edge(clk)) then
     count <= count + 1;
  end if;

end process;
------------------------------------------------
  q <= count;
------------------------------------------------
end counter_arch;

von Holger (Gast)


Lesenswert?

OK, danke. Wie lege ich denn nun noch die Pins fest?

Gruß
Holger

von Xenu (Gast)


Lesenswert?

In der UCF-Datei, die Du Deinem Projekt hinzufügen musst.

Am besten Du liest Dir mal das hier durch, da steht alles drin, was Du
für den Anfang wissen musst:

http://www.xilinx.com/publications/products/cpld/logic_handbook.pdf

von Daniel R. (daniel_r)


Lesenswert?

So werden alle LEDs immer an sein...Du brauchst noch einen
Clockvorteiler(außer Du taktest den CPLD direkt mit 10Hz oder so ;)).

von Holger (Gast)


Lesenswert?

Hallo, danke für die Tipps. Bisher habe ich alles verstanden. Nun kann
ich doch auch einfach das ganze um 8 LEDs auf 16 erweitern -oder?

"q   : out std_logic_vector(15 downto 0)"


Nun möchte ich aber nicht 16 LEDs sondern 8 und mittels Schalter
zwischen den oberen und unteren 8 Bits schalten. Geht das auch?

Gruß
Holger

von Xenu (Gast)


Lesenswert?

>um 8 LEDs auf 16 erweitern -oder?

Richtig.

>mittels Schalter zwischen den oberen und unteren 8 Bits schalten.
>Geht das auch?

Klaro:

  q <= count(15 downto 8) when (Schalter = '1') else count(7 downto
0);


Wobei "Schalter" ein std_logic-Eingang ist.

von Holger (Gast)


Lesenswert?

mmm, sieht ja einfacher aus als erwartet. Wie MHz kann denn so ein CPLD
bei diesem Zähler verarbeiten?

Gruß
Holger

von Daniel R. (daniel_r)


Lesenswert?

Ich kenne mich mit CPLDs nicht aus...Irgendwie ist das bei denen anders
als bei FPGAs, aber ich denke 50 MHz sollten auf jeden Fall drin sein.


Daniel

von Xenu (Gast)


Lesenswert?

>Wie MHz kann denn so ein CPLD bei diesem Zähler verarbeiten?

Kommt natürlich auf CPLD und Geschwindigkeitsgrad an.
Am einfachsten wäre es du synthetisierst das Ganze mal und
schaust nach was Dir die ISE sagt.

von Holger (Gast)


Lesenswert?

Hallo,

ich habe jetzt den Zähler auf 32-Bit aufgebaut (CPLD 9572). Dazu
insgesamt 4 Schalter für die vier Bytes sowie ein enable-Schalter.

Könnt Ihr Euch das mal anschauen. Macht das so Sinn?


mfg
Holger


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity zaehler is
    Port ( rst : in  STD_LOGIC;
           clk : in  STD_LOGIC;
           sw1 : in  STD_LOGIC;
           sw2 : in  STD_LOGIC;
           sw3 : in  STD_LOGIC;
           sw4 : in  STD_LOGIC;
           enable : in  STD_LOGIC;
           q : out  STD_LOGIC_VECTOR (7 downto 0));
end zaehler;

architecture Behavioral of zaehler is
   signal count : std_logic_vector(31 downto 0);
begin
process (clk,rst)
begin
  if(rst = '0') then count <= (others => '0');
  elsif(rising_edge(clk)) and (enable = '0') then count <= count +
1;
  end if;
end process;

process (sw1,sw2,sw3,sw4)
begin
  if(sw4 = '1') then q <= count(31 downto 24);
  elsif(sw3 = '1') then q <= count(23 downto 16);
  elsif(sw2 = '1') then q <= count(15 downto 8);
  elsif(sw1 = '1') then q <= count(7 downto 0);
  end if;
end process;

end Behavioral;

von Daniel R. (daniel_r)


Lesenswert?

Mach am besten alles in einem Prozess. Den Reset machste am besten
synchron(nach rising_edge...).

Man taktet einen Prozess niemals direkt mit Schaltern oder sonstigem
Zeug. Immer den Clock nehmen und die Signale dann synchron abfragen.

Ich schreib Dir noch schnell ein Beispiel...
Moment bitte.

von Daniel R. (daniel_r)


Angehängte Dateien:

Lesenswert?

Das Design ist nicht getestet... Dürfte so aber gehen.
Es befindet sich auch noch im Anhang, falls die Gliederung durch das
Forum-Format draufgeht.


entity counter is
port(
    clk        : in std_logic;
    reset        : in std_logic;
    switches      : in std_logic_vector(3 downto 0);
    q          : out std_logic_vector(7 downto 0)
   );
end counter;

architecture Behavioral of counter is
signal count    : std_logic_vector(31 downto 0);

begin

process(clk)
begin
  if rising_edge(clk) then
    if reset = '1' then
      q <= (others => '0');
      count <= (others => '0');
    else
      if count = x"FFFFFFFF" then
        count <= (others => '0');
      else
        count <= count +1;
      end if;

      case switches is
        when "0001" =>
          q <= count(7 downto 0);
        when "0010" =>
          q <= count(15 downto 8);
        when "0100" =>
          q <= count(23 downto 16);
        when "1000" =>
          q <= count(31 downto 24);
        when others =>
          q <= (others => '0');
      end case;
    end if;
  end if;
end process;

end Behavioral;

von Holger (Gast)


Lesenswert?

Super. Das habe ich mal durchlaufen lassen. 40 Makrozellen werden
benötigt und das ganze läuft bis 66MHz und passt in einen 9572. Das ist
ja schon was!!! Also Daniel erst einmal vielen Dank!!!

Nur eines noch: Gezählt soll nur wenn der Enable-Pin = 0. Also das muss
da noch mit rein. Reset und das Ausgeben soll jedoch jederzeit möglich
sein. Also unabhängig von Enable.

Gruß
Holger

von Rainer (Gast)


Lesenswert?

Hallo Daniel!

Ist denn die explizite Zuweisung der 0 notwendig, wenn der Zähler
überläuft? std_logic_vector sollte doch brav durchzählen! Aber ISE
sollte das eh optimieren!

Grüße
Rainer

von Holger (Gast)


Lesenswert?

So, und noch eine Frage und zwar zu den Zeilen:

case switches is
        when "0001" =>
          q <= count(7 downto 0);
        when "0010" =>
          q <= count(15 downto 8);
        when "0100" =>
          q <= count(23 downto 16);
        when "1000" =>
          q <= count(31 downto 24);
        when others =>
          q <= (others => '0');
      end case;

Könnte man, den Ausgang im Falle "when others" auch als Tristate
hochohmig schalten?


Gruß
Holger

von Daniel R. (daniel_r)


Lesenswert?

@Holger

>Nur eines noch: Gezählt soll nur wenn der Enable-Pin = 0. Also das
muss
>da noch mit rein. Reset und das Ausgeben soll jedoch jederzeit
möglich
>sein. Also unabhängig von Enable.

Code folgt...

>Könnte man, den Ausgang im Falle "when others" auch als Tristate
>hochohmig schalten?

Selbstverständlich. Ich packs gleich in den Code mit rein.

@Rainer

>Ist denn die explizite Zuweisung der 0 notwendig, wenn der Zähler
>überläuft? std_logic_vector sollte doch brav durchzählen! Aber ISE
>sollte das eh optimieren!

Richtig, der Counter resetted normalerweise selbstständig. De
Vollständigkeit halber habe ich den reset dazugeschrieben.



Daniel

von Holger (Gast)


Lesenswert?

Hallo, Tristate geht mit 'Z' -oder? Nach Möglichkeit sollte der Reset
aber von Clock unabhängig sein.



Gruß
Holger

von Daniel R. (daniel_r)


Angehängte Dateien:

Lesenswert?

Hier der Code:
Bei "when others" wird der Ausgang jetzt auf Tristate geschaltet.
Außerdem habe ich den manuellen Reset des Counters nun
auskommentiert(unwirksam gemacht). Wie Rainer sagte, resettet der
Counter ja von selbst. Das spart Resourcen(von denen ein CPLD ja
sowieso nicht viel hat) und ist schneller(auf meinem Spartan3 würde es
jetzt mit 170MHz laufen).

Viel Spaß!!



entity counter is
port(
    clk        : in std_logic;
    reset      : in std_logic;
    switches   : in std_logic_vector(3 downto 0);
   enable    : in std_logic;
    q          : out std_logic_vector(7 downto 0)
   );
end counter;

architecture Behavioral of counter is
signal count    : std_logic_vector(31 downto 0);

begin

process(clk)
begin
  if rising_edge(clk) then
    if reset = '1' then
      q <= (others => '0');
      count <= (others => '0');
    else
     if enable = '0' then
      --  if count = x"FFFFFFFF" then      --Counter manuell resetten...
        --    count <= (others => '0');
        --else
           count <= count +1;
         --end if;
    end if;

      case switches is
        when "0001" =>
          q <= count(7 downto 0);
        when "0010" =>
          q <= count(15 downto 8);
        when "0100" =>
          q <= count(23 downto 16);
        when "1000" =>
          q <= count(31 downto 24);
        when others =>
          q <= (others => 'Z');   --Schaltet den Ausgang auf Tristate
      end case;
    end if;
  end if;
end process;

end Behavioral;

von Daniel R. (daniel_r)


Lesenswert?

>Hallo, Tristate geht mit 'Z' -oder?
Richtig.

>Nach Möglichkeit sollte der Reset aber von Clock unabhängig sein.

Genau das vermeidet man.
Der Clock ist ja immer da(sonst würde ja nichts laufen).

Außerdem macht ein synchroner Reset das Design schneller und braucht
meistens weniger Resourcen.

Falls Du trotzdem einen asynchronen Reset wünschst, dann schrein
einfach "if reset = '1'" vor "if rising_edge(clk)"...und vergiss
das "end if" nicht.


Gruß Daniel

von Holger (Gast)


Lesenswert?

Hallo Daniel,

da war ich mit dem vorherigen Posting zu langsam ;-)

Kannst Du noch den Reset Clockunabhängig machen?



Gruß und schönes W'ende

Holger

von Holger (Gast)


Lesenswert?

Hallo,

ich muss noch mal neu anfangen. Alles hängt doch jetzt vom Clock-Signal
ab -oder?

Ich möchte meine Wunschkonfiguration noch mal darlegen und hoffe auf
Nachsicht:

1. wenn Enable-Signal anliegt, dann soll der Zähler die Ereignisse am
Clock-Eingang zählen (32-Bit)
2. Clock liegt nicht immer an, sondern wird extern dazugeschaltet
3. wenn kein Enable-Signal anliegt, dann
   -soll unabhängig ob ein Clock-Signal anliegt oder nicht ein Reset
möglich sein!
   -soll noch durch die vier Switch-Leitungen die jeweiligen Bytes
ausgegeben werden
   -sollen die Ausgänge hochohmig geschaltet werden, wenn keine
Switch-Leitung geschaltet wird

Also, ich brauche keinen Synchronzähler sondern einen Zähler der bei
Enable um sein Leben rennt. Für Reset und Auslesen ist genug Zeit
vorhanden!

Zählen und Reset/Ausgabe sind getrennt voneinander und während des
Zählens erfolgt kein Reset und kein Auslesen der Bytes!

So, nochmal viele Grüße
Holger

von Holger (Gast)


Lesenswert?

mein letzter Versuch fürs Wochenende ...


entity counter is
port(
    clk        : in std_logic;
    reset      : in std_logic;
    switches   : in std_logic_vector(3 downto 0);
    enable    : in std_logic;
    q          : out std_logic_vector(7 downto 0)
    );
end counter;

--------------------------------------------------

architecture Behavioral of counter is
signal count    : std_logic_vector(31 downto 0);

begin

process(clock)
begin
  if enable = '0' then           --aktive low

    if rising_edge(clk) then
       q <= (others => 'Z');
       count <= count +1;
    ebd if;

  else

  if reset = '1' then            --aktive high
     q <= (others => '0');
     count <= (others => '0');

  else

     case switches is            --aktive high
        when "0001" =>
          q <= count(7 downto 0);
        when "0010" =>
          q <= count(15 downto 8);
        when "0100" =>
          q <= count(23 downto 16);
        when "1000" =>
          q <= count(31 downto 24);
        when others =>
          q <= (others => 'Z');   --Tristate
      end case;

  end if;
  end if;
end process;

end Behavioral;

von Daniel R. (daniel_r)


Lesenswert?

Jetzt schaltest Du aber bei jeder Flanke des Clocks die Ausgänge auf
Tristate. Außerdem werden die Bytes nur ausgegeben, wenn kein enable
anliegt(also enable = '1'). Das entspricht nicht Deinen Vorgaben.

Wenn ich nacher noch Lust habe schreibe ich Dir das Zeug schnell...


Daniel

von Daniel R. (daniel_r)


Angehängte Dateien:

Lesenswert?

entity counter is
port(
    clk        : in std_logic;
    reset      : in std_logic;
    switches   : in std_logic_vector(3 downto 0);
   enable    : in std_logic;
    q          : out std_logic_vector(7 downto 0)
   );
end counter;

architecture Behavioral of counter is
signal count    : std_logic_vector(31 downto 0);

begin

process(clk,enable,reset,switches,count)
begin

  case switches is
        when "0001" =>
          q <= count(7 downto 0);
        when "0010" =>
          q <= count(15 downto 8);
        when "0100" =>
          q <= count(23 downto 16);
        when "1000" =>
          q <= count(31 downto 24);
        when others =>
          q <= (others => 'Z');     --Tristate
   end case;


  if reset = '1' then      --Asynchroner Reset
      q <= (others => '0');
      count <= (others => '0');
  elsif  rising_edge(clk) then
       if enable = '0' then    --Synchroner Zähler mit enable
        count <= count +1;
      end if;

  end if;
end process;

end Behavioral;


Daniel

von Holger (Gast)


Lesenswert?

Hallo,

danke für die Hilfe. Montag komm ich erst wieder an meinem PC ran.

Ich brauch unbedingt einen VHDL-Buch. Welches kann man mir empfehlen?
(amazon?)


Gruß
Holger

von high_speed (Gast)


Lesenswert?

VHDL-Synthese
Entwurf digitaler Schaltungen und Systeme
von Jürgen Reichardt, Bernd Schwarz

ISBN 3-486-27384-1

http://users.etech.haw-hamburg.de/users/Schwarz/En/Publications/VHDL_S...
http://users.etech.haw-hamburg.de/users/Reichardt/buch.html

Kapietel 8 (Synthesefähiger Entwurf eines Mikroprozessors)
http://users.etech.haw-hamburg.de/users/Schwarz/En/Publications/Sample...

VHDL-Quellcodes und Musterlösungen
http://users.etech.haw-hamburg.de/users/Reichardt/buch.html

MfG
Holger

von high_speed (Gast)


Lesenswert?


von Holger (Gast)


Lesenswert?

Hallo, es geht um obiges Beispiel:

  if reset = '1' then      --Asynchroner Reset
      q <= (others => '0');
      count <= (others => '0');
  elsif  rising_edge(clk) then
       if enable = '0' then    --Synchroner Zähler mit enable
        count <= count +1;
      end if;


Da wird doch bei einem Reset 0 an q ausgegeben -oder?


Gruß
Holger

von Daniel R. (daniel_r)


Lesenswert?

Ja, stimmt.

von Holger (Gast)


Lesenswert?

OK,

dann kann ich die Zeile ja löschen. Übrigens funzt der Zähler ansonsten
1a!


Gruß
Holger

von Holger (Gast)


Lesenswert?

Mahlzeit,

also mit einem 100MHz Quarzoszillator läuft das Teil auch noch! Laut
ISE sollte die Hälfte drin sein ;-)


Gruß
Holger

von Daniel R. (daniel_r)


Lesenswert?

Auf meinem FPGA liefe es laut ISE mit 200MHz ;)

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.