Datum: 14.05.2008 11:37
Ich habe diesen Frequenzteiler in VHDL programmiert, er funktioniert jedoch nicht. Hat jemand eine Idee was da falsch sein könnte. Ich kann mir nicht erklären was da nicht hinhaut da es ein recht einfaches Programm ist. Danke im voraus. mfg Gerhard ##################################################################### -- clk_Teiler.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity Teiler is port( sysclk,enable: in std_logic; ds: in std_logic_vector(4 downto 0); clk: out std_logic); end Teiler; architecture strg of Teiler is signal clkDiv: std_logic_vector(5 downto 0):=(others=>'0'); signal clkTemp: std_logic:= '0'; signal LowOrHigh: std_logic:= '0'; begin Process (sysclk,enable,ds) begin if (enable='1') then clkDiv<= "111111"; elsif (sysclk='1' and sysclk'Event) then clkDiv<=clkDiv-'1'; end if; if (clkDiv="000000") then clkTemp<= LowOrHigh; clkDiv <= (others=>'1'); clkDiv(5)<=ds(4); clkDiv(4)<=ds(3); clkDiv(3)<=ds(2); clkDiv(2)<=ds(1); clkDiv(1)<=ds(0); if (LowOrHigh='0')then LowOrHigh<='1'; else LowOrHigh<='0'; end if; end if; end Process; clk<=clkTemp; end strg; ####################################################################
Datum: 14.05.2008 12:22
Hab mein Programm nun überarbeitet weil ich mir überlegt hab das vl die
anderen if`s alle synchron laufen müssen. Funktioniert aber immer noch
nicht.
###################################################################
-- clk_Teiler.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity Teiler is
port( sysclk,enable: in std_logic;
ds: in std_logic_vector(4 downto 0); -- Switches
clk: out std_logic);
end Teiler;
architecture strg of Teiler is
signal clkDiv: std_logic_vector(5 downto 0):=(others=>'0');
signal clkTemp: std_logic:= '0';
signal LowOrHigh: std_logic:= '0';
begin
Process (sysclk,enable,ds)
begin
if (sysclk='1' and sysclk'Event) then
clkDiv<=clkDiv-'1';
if (enable='1') then
clkDiv<= "000011";
clkTemp<='0';
LowOrHigh<='1';
elsif (clkDiv="000000") then
clkTemp<= LowOrHigh;
clkDiv <= (others=>'1');
clkDiv(5)<=ds(4);
clkDiv(4)<=ds(3);
clkDiv(3)<=ds(2);
clkDiv(2)<=ds(1);
clkDiv(1)<=ds(0);
if (LowOrHigh='0')then
LowOrHigh<='1';
else
LowOrHigh<='0';
end if;
end if;
end if;
end Process;
clk<=clkTemp;
end strg;
#######################################################################
Datum: 14.05.2008 12:35
Mit der ersten Variante baust du dir einen kombinatorischen schwanzbeisser. Dein enable ist in wirklichkeit ein reset! Was funktioniert denn nicht? Ich hoffe du benutzt das Konstrukt nicht um interne logik zu takten! Taktung FPGA/CPLD Du koenntest das ganze ein wenig ueberischtlicher schreiben:
process(sysclk) begin if rising_edge(sysclk) then if enable = '1' then clkDiv <= (others=>'1'); elseif clkDiv /= 0 then clkDiv <= clkDiv - 1; else clkTemp <= not clkTemp; clkDiv <= ds & "1"; end if; end if; end process; |
Cheers, Roger
Datum: 14.05.2008 12:37
Zunächst einmal: Man benutzt NICHT die std_logic_arith und std_logic_unsigned. Anstelle derer benutzt man die numeric_std. Das Zweite: was geht denn nicht? Was macht Dein Design? Das Dritte: in einem getakteten Prozess gehört nur der Takt und evtl. ein asynchroner Reset in die Sensitivitätsliste.
Datum: 14.05.2008 12:59
Dies "clkDiv <= (others=>'1');" widerspricht doch dem hier, oder nicht ? clkDiv(5)<=ds(4); clkDiv(4)<=ds(3); ... clkDiv(1)<=ds(0);
Datum: 14.05.2008 14:02
Also wenn ich die numeric_std anstelle der arith und der unsigned benutze funktionierts gar nicht mehr. Bei der 2 Variante lässt es sich durchsimulieren. Man sieht jedoch ein undefieniertes Signal für clk, ausser enable ist High. (Enable soll quasi auch ein reset sein) Was heißt interne logik zu takten???? Danke für eure antworten.
Datum: 14.05.2008 14:11
Man kann auch nicht einfach die Bibliotheken austauschen und denken das es dann geht. Du musst Dein Design auch entsprechend umstellen. "Interne Logik takten" bedeutet das Du das clk-signal an andere Module als Takt anschließt. Das macht man nämlich nicht bei FPGA-Designs, sondern verwendet einen ClockEnable. Zieh das clkTemp<= LowOrHigh; mal vor das if.
Datum: 14.05.2008 14:17
nein ich takte nur diesen einen Process damit, also hab ich da schon mal kein probolem. Aber wenn ich clkTemp<= LowOrHigh; vor das if ziehe ändert sich auch nichts. obwohl doch wenn man logisch überlegt das funk. müsste.
Datum: 14.05.2008 14:26
Noch ein Versuch: schreibe mal
LowOrHigh<='0'; if (LowOrHigh='0')then LowOrHigh<='1'; end if; |
Datum: 14.05.2008 14:29
was benutzt du zur Simulation, und wie sehen die Eingangsignale aus? Zeige doch mal dein Testbench.
LowOrHigh<='0'; if (LowOrHigh='0')then LowOrHigh<='1'; end if; |
ein simples not wird ja wohl reichen
Datum: 14.05.2008 14:37
Gerade getestet... Funzt mit dem ändern des if(LowOrHigh.. Teils.. @Roger: wenn er es korrekt initialisiert reicht ein not... ;)
Datum: 14.05.2008 14:43
welche library würde man für ein not benötigen. Bei mir funk. das not nämlich nicht.
Datum: 14.05.2008 14:44
Das not ist in der std_logic_1164 definiert.. Sollte also gehen... Was sagt Dir der Compiler?
Datum: 14.05.2008 14:49
Compiler sagt nichts--> funk einfach nicht
Datum: 14.05.2008 15:12
hab es jetzt über eine andere mögl. versucht die ich hier im forum gefunden habe. --> funktioniert aber auch nicht.
-- Teiler.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use IEEE.numeric_std.all; entity Teiler is port( sysclk,enable: in std_logic; ds: in std_logic_vector(4 downto 0); -- Switches clk: out std_logic); end Teiler; architecture strg of Teiler is signal clkDiv: std_logic_vector(31 downto 0) := (others=>'0'); begin Process (sysclk,enable,ds) begin if (enable='1') then clkDiv <= "00000000000000000000000000000000"; elsif(sysclk='1' and sysclk'event) then clkDiv <=clkDiv + '1'; end if; case ds is when "00000" => clk <= clkDiv(0); when "00001" => clk <= clkDiv(1); when "00010" => clk <= clkDiv(2); when "00011" => clk <= clkDiv(3); when "00100" => clk <= clkDiv(4); when "00101" => clk <= clkDiv(5); when "00110" => clk <= clkDiv(6); when "00111" => clk <= clkDiv(7); when "01000" => clk <= clkDiv(8); when "01001" => clk <= clkDiv(9); when "01010" => clk <= clkDiv(10); when "01011" => clk <= clkDiv(11); when "01100" => clk <= clkDiv(12); when "01101" => clk <= clkDiv(13); when "01110" => clk <= clkDiv(14); when "01111" => clk <= clkDiv(15); when "10000" => clk <= clkDiv(16); when "10001" => clk <= clkDiv(17); when "10010" => clk <= clkDiv(18); when "10011" => clk <= clkDiv(19); when "10100" => clk <= clkDiv(20); when "10101" => clk <= clkDiv(21); when "10110" => clk <= clkDiv(22); when "10111" => clk <= clkDiv(23); when "11000" => clk <= clkDiv(24); when "11001" => clk <= clkDiv(25); when "11010" => clk <= clkDiv(26); when "11011" => clk <= clkDiv(27); when "11100" => clk <= clkDiv(28); when "11101" => clk <= clkDiv(29); when "11110" => clk <= clkDiv(30); when "11111" => clk <= clkDiv(31); end case; end Process; end strg; |
Datum: 14.05.2008 16:19
die Variante teilt anders (in 2^n Schritten) als deine und scheint einem Schriftsteller entsprungen zu sein. Ich Staune immer wieder ueber die Ausdauer die manche Leute an den Tag legen. Diese wie auch deine zweite Variante sollte funktionieren, das Problem liegt bei dir. Du hast immer noch nicht erwaehnt welches Tool du zur Simulation einsetzt, es scheint ein Konfigurationsproblem zu sein. Cheers, Roger
Datum: 14.05.2008 16:37
ich verwende libero 8.0 da ich ein actel board habe.
Datum: 14.05.2008 21:32
@Gerhard: Wie stellst Du den fest, dass Dein Teiler nicht geht? Hast Du eine Testbench? Rick
Datum: 14.05.2008 22:21
ja hab ich. und für den clock wird immer nur 'x' angezeigt. ausser Enable = high dan funktsionirts.
Datum: 15.05.2008 18:00
Ok. Dann pack doch mal dein Modul und die Testbench in eine zip-Datei und stelle die hier ein. Rick
Datum: 15.05.2008 21:42
Dein VHDL Code ist nicht korrekt, weil Du 2 verschiedene Sachen in einen gemeinsamen Prozess steckst. Du mußt die Dinge trennen. Zuerst hast Du einen synchronen Teil, mit if (enable='1') then clkDiv <= "00000000000000000000000000000000"; elsif(sysclk='1' and sysclk'event) then clkDiv <=clkDiv + '1'; end if; Das ist ein synchroner Zähler, mit enable als Reset und sysclk als Takt. So ein Prozess benötigt nur enable und sysclk in der sensitivity list. Dann hast Du die case Anweisung, die außerhalb des elsif(sysclk='1' and sysclk'event) steht. Dies ergibt eine kombinatorische Logik für das clk Ausgangssignal, etwas das schon vom Prinzip her sehr, sehr ungünstig ist. Wenn man schon so ein Taktsignal erzeugt, dann sollte man es wenigstens vom schnellen Takt abtakten lassen. Der kombinatorische Teil hängt von den Signalen ds und clkDiv ab. Deshalb gehört das case in einen separaten Prozess mit diesen Signalen in der sensitivity list. Besser wäre es, das case in den elsif(sysclk='1' and sysclk'event) then .... end if; Zweig hineinzunehmen. Dann arbeitet der Frequenzteiler komplett synchron und es gehören nur enable und sysclk in die sensitivity list
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
- Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [vhdl]VHDL-Code[/vhdl]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel