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
>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;
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
So werden alle LEDs immer an sein...Du brauchst noch einen Clockvorteiler(außer Du taktest den CPLD direkt mit 10Hz oder so ;)).
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
>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.
mmm, sieht ja einfacher aus als erwartet. Wie MHz kann denn so ein CPLD bei diesem Zähler verarbeiten? Gruß Holger
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
>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.
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;
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.
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;
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
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
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
@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
Hallo, Tristate geht mit 'Z' -oder? Nach Möglichkeit sollte der Reset aber von Clock unabhängig sein. Gruß Holger
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;
>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
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
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
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;
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
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
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
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
Hier noch mal die vollständigen Links. http://users.etech.haw-hamburg.de/users/Schwarz/En/Publications/VHDL_Synthesis.html http://users.etech.haw-hamburg.de/users/Schwarz/En/Publications/Sample/Chap8.pdf MfG Holger
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
OK, dann kann ich die Zeile ja löschen. Übrigens funzt der Zähler ansonsten 1a! Gruß Holger
Mahlzeit, also mit einem 100MHz Quarzoszillator läuft das Teil auch noch! Laut ISE sollte die Hälfte drin sein ;-) Gruß Holger
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.