LED-Zähler mit Xilinx CPLD

Gast #389479
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
Gast #389480
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;
Gast #389484
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
Gast #389485
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.
Gast #389489
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;
#389490
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.
#389491
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;
Angehängte Dateien:
Gast #389492
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
Gast #389494
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
#389495
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
#389497
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;
Angehängte Dateien:
#389498
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
Gast #389500
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
Gast #389501
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;
#389502
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
#389503
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
Angehängte Dateien:
Gast #389505
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
Gast #389507
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren