mikrocontroller.net

Forum: FPGA, VHDL & Co. Frequenzteiler


Autor: M. N. (marco2228)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich benötige für ein Projekt einen Frequenzteiler und habe schon einige 
Zeit hier im Forum gelesen, unten ist das Ergebnis. Leider sieht man 
weder an den LED, noch in dem Xilinx ISE Simulator irgendeine Reaktion 
(die '1' für die LED 7 natürlich ausgenommen). Liegt es daran, dass ich 
immer nur für einen Takt eine 1 ausgebe? Das müsste aber ja im Simulator 
zu sehen sein, oder?
Muss ich es eigentlich wirklich auf so viele Zähler aufteilen?


Besten Dank

Marco
______________________________________________________________________ 
_
entity frequenz is
    Port ( takt, reset : in  STD_LOGIC;
           led1 : out  STD_LOGIC;
           led2 : out  STD_LOGIC;
           led3 : out  STD_LOGIC;
           led4 : out  STD_LOGIC;
           led5 : out  STD_LOGIC;
           led6 : out  STD_LOGIC;
           led7 : out  STD_LOGIC);
end frequenz;

architecture Behavioral of frequenz is

signal f10m, f1m, f100k, f10k, f1k, f100, f10, f1: std_logic_vector(3 
downto 0);
signal ci10m, ci1m, ci100k, ci10k, ci1k, ci100, ci10, ci1: std_logic;

begin


teiler10m: process (reset, takt, f10m)
begin
if reset ='1' then
    f10m <= "0000";
  else
    if rising_edge(takt) then
      if f10m = 4 then
        f10m <="0000";
      else
        f10m <= f10m + 1;
      end if;
    else
      f10m <= f10m;
    end if;
  end if;
end process teiler10m;

ci10m<='1' when f10m = 4 else '0';

teiler1m: process (reset, takt, f1m, ci10m)

begin
if reset ='1' then
    f1m <= "0000";
  else
    if rising_edge(takt) and ci10m = '1' then
      if f1m = 9 then
        f1m <="0000";
      else
        f1m <= f1m + 1;
      end if;
    else
      f1m <= f1m;
    end if;
  end if;
end process teiler1m;

ci1m<='1' when (f1m = 9 and ci10m='1') else '0';


teiler100k: process (reset, takt, f100k, ci1m)

begin
if reset ='1' then
    f100k <= "0000";
  else
    if rising_edge(takt) and ci1m = '1' then
      if f100k = 9 then
        f100k <="0000";
      else
        f100k <= f100k + 1;
      end if;
    else
      f100k <= f100k;
    end if;
  end if;
end process teiler100k;

ci100k<='1' when (f100k = 9 and ci1m='1') else '0';

teiler10k: process (reset, takt, f10k, ci100k)
begin
if reset ='1' then
    f10k <= "0000";
  else
    if rising_edge(takt) and ci100k ='1' then
      if f10k = 9 then
        f10k <="0000";
      else
        f10k <= f10k + 1;
      end if;
    else
      f10k <= f10k;
    end if;
  end if;
end process teiler10k;

ci10k <='1' when (ci100k='1' and f10k = 9) else '0';

teiler1k: process (reset, takt, f1k, ci10k)
begin
if reset ='1' then
    f1k <= "0000";
  else
    if rising_edge(takt) and ci10k = '1' then
      if f1k = 9 then
        f1k <="0000";
      else
        f1k <= f1k + 1;
      end if;
    else
      f1k <= f1k;
    end if;
  end if;
end process teiler1k;

ci1k<='1' when (f1k = 9 and ci10k='1') else '0';

teiler100: process (reset, takt, f100, ci1k)
begin
if reset ='1' then
    f100 <= "0000";
  else
    if rising_edge(takt) and ci1k='1' then
      if f100 = 9 then
        f100 <="0000";
      else
        f100 <= f100 + 1;
      end if;
    else
      f100 <= f100;
    end if;
  end if;
end process teiler100;

ci100<='1' when (f100 = 9 and ci1k='1') else '0';

teiler10: process (reset, takt, f10, ci100)
begin
if reset ='1' then
    f10 <= "0000";
  else
    if rising_edge(takt) and ci100='1' then
      if f10 = 9 then
        f10 <="0000";
      else
        f10 <= f10 + 1;
      end if;
    else
      f10 <= f10;
    end if;
  end if;
end process teiler10;

ci10<='1' when (f10 = 9 and ci100='1') else '0';

teiler1: process (reset, takt, f1, ci10)
begin
if reset ='1' then
    f1 <= "0011";
  else
    if rising_edge(takt) and ci10='1' then
      if f1 = "1100" then
        f1 <="0011";
      else
        f1 <= f1 + 1;
      end if;
    else
      f1 <= f1;
    end if;
  end if;
end process teiler1;

ci1<='1' when (ci10='1' and f1 = 9) else '0';

led1 <= ci1;
led2 <= ci10;
led3 <= ci100;
led4 <= ci1k;
led5 <= ci10k;
led6 <= ci100k;
led7 <= '1';

end Behavioral;
______________________________________________________________________ 
_

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In welchem Buch hast du solche Konstrukte schon mal gesehen?
  if reset ='1' then
    f10m <= "0000";
  else
    if rising_edge(takt) then
      if f10m = 4 then
        f10m <="0000";
      else
        f10m <= f10m + 1;
      end if;
    else        -- !!!! Was soll denn das? Wenn keine steigende Taktflanke?
      f10m <= f10m;
    end if;
  end if;


Auch das ist eher selten zu sehen:
    if rising_edge(takt) and ci10='1' then
Du hast trotzdem Glück gehabt: die Synthese kann das heutzutage...


Warum machst du nicht erst mal nur einen einzigen Teiler?
Und wenn der läuft machst du die weiteren?

Ich würde das übrigens so angehen:
  use ieee.numeric_std.all;
  :
  :
  signal c1, c10, c100 : integer range 0 to 9 := 0;
  :
  -- Einer
  process begin
     wait until rising_edge(clk);
     led1 <= '0';
     if (c1 < 9) then 
        c1 <= c1 + 1;
     else             
        c1 <= 0;
        led1 <= '1';
     end if;
  end process;
  
  -- Zehner
  process begin
     wait until rising_edge(clk);
     led2 <= '0';
     if (c1=9) then
        if (c10 < 9) then 
           c10 <= c10 + 1;
        else
           c10 <= 0; 
           led2 <= '1';
        end if;
     end if;
  end process;
  :

BTW: warum fänst du bei den LEDs mit 1 an?
Mach das besser gleich von vornm weg mit 0..7 statt mit 1..8!!

Autor: M. N. (marco2228)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank schonmal für die Hilfe...

Die Reduzierung des Taktes bis auf 1 Hertz funktioniert jetzt. Nun habe 
ich versucht nach dem Frequenzteiler auf 10 Hz einen 2Hz-Takt wie folgt 
zu generieren:
 process begin
  wait until rising_edge(clk);
  clk_2 <= '0';  
  if (c10>4) then 
    clk_2 <= '1';
  else
    clk_2 <= '0';
  end if;
end process;

dabei soll das High Signal für die gleiche Zeit anliegen wie das Low 
Signal.

leider funktioniert es aber nicht so wie es soll...
Für mich sieht es so aus, als ob die LED durchgehend leuchtet.

Autor: Sym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, was machst du da? Du musst das Signal der LED zuweisen und zudem 
machst du damit ein 40%, 60% Teilerverhältnis.

Wenn du den Takt herunterteilen willst, so solltest du darauf achten 
eine Gated Clock zu vermeiden. D.h. mit einem Zähler runterteilen und 
ein enable-Pulsemuster generieren und alles mit EINER Clock takten. Denn 
jeder Taktübergang ist eine potentielle Fehlerquelle.

Autor: M. N. (marco2228)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das Signal weise ich später der LED zu, das ist ja erstmal nicht so 
wichtig. Daher hatte ich es auch nicht gepostet.
Ist es wirklich ein 40/60 Verhältnis? So wie ich es verstehe habe ich 
für 0-4 ein LOW Signal und für 5-9 ein High Signal.
Was meinst du mit enable Pulsmuster?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. N. schrieb:
> leider funktioniert es aber nicht so wie es soll...
> Für mich sieht es so aus, als ob die LED durchgehend leuchtet.
Und was sagt die Simulation?

Autor: Sym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, ergibt doch 50:50 Teilung. Du teilst also von 10 Hz auf 5 Hz 
runter.

Wenn du einfach nur einen Takt runterteilen willst, aber Probleme mit 
Gated Clock vermeiden willst, so verwende das von mir unten 
vorgeschlagene Konstrukt. Natürlich lassen sich auch mehrere Divider 
kaskadieren.
constant c_div : integer := 1000;

signal div : integer range 0 to c_div-1;
signal enable : std_logic;

-- process to divide clock
p_mydivider : process (clk, rst)
begin
  if rst = '0' then
    div <= 0;
    enable <= '0';
  elsif clk'event and clk = '1' then
    enable <= '0';
    if div /= 0 then
      div <= div - 1;
    else
      div <= c_div - 1;
      enable <= '1';
    end if;
  end if;
end process p_mydivider;


--process with virtually divided clock
p_slow: process (clk, rst)
begin
  if rst = '0' then 
  elsif clk'event and clk = '1' then
    if enable = '1' then
      -- your code here
    end if;
  end if;
end process p_slow;

Autor: M. N. (marco2228)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Lothar
über einen solch langen Zeitraum kann ich doch garnicht simulieren oder? 
also ich benutze das Xilinx ISE Webpack 10.1. Oder ist es möglich direkt 
nur die letzten beiden Frequenzteiler zu simulieren, ohne die restlichen 
Vorgeschalteten und den 50MHZ clk als Quelle?
Muss ich es vielleicht mit einem anderen Programm simulieren?

@Sym
stimmt, das ist falsch, aber das wären so wie ich es oben geschrieben 
habe dann 1Hz und nicht 5. Dann werde ich ja mit meinem 10 Hz Takt nicht 
glücklich oder? Ich kann ja nicht bis 2,5 zählen lassen.

Autor: Steffen H. (avrsteffen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man dann das "enable" für weitere Counter im Design und auch als 
2.Clock in anderen Components benutzen?

Also wenn ich in einer anderen Component einen Zähler habe der mit einem 
anderen Takt als der sys-Takt zählen soll? Natürlich hat dieser Zähler 
im Component 2 Taktanschlüsse. sys_CLK und div_CLK.

Sollte das gehen?

Noch eine Frage an die Experten:
Wie kann man da sicher sein, dass dann diesen div_CLK im Design auch als 
eine solcher speziellen Clock-Net geroutet wird??

Grüße Steffen

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen H. schrieb:
> Natürlich hat dieser Zähler im Component 2 Taktanschlüsse.
> sys_CLK und div_CLK.
Was ist div_CLK? Ein Ausgang?

> Noch eine Frage an die Experten:
> Wie kann man da sicher sein, dass dann diesen div_CLK im Design auch als
> eine solcher speziellen Clock-Net geroutet wird??
Indem du für abgeleitete Takte einen DCM (Taktmanager) nimmst.

> Sollte das gehen?
Zeig doch mal ein Beispiel, wie du das meinst...

Autor: Steffen H. (avrsteffen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was ist div_CLK? Ein Ausgang?
Ja, der div_CLK ist ein Ausgang und gleichzusetzen dem "enable" aus 
obrigem Beispielcode.


> Wie kann man da sicher sein, dass dann diesen div_CLK im Design auch als
> eine solcher speziellen Clock-Net geroutet wird??
>Antwort: Indem du für abgeleitete Takte einen DCM (Taktmanager) nimmst.
Ich weiß nicht ob Lattice sowas hat. Ich arbeite mit einem Lattice XP 
FPGA. Das hat 2 PLL-Module und vier (glaub ich) Clock-Select Module wo 
man 2 Takt-Signale einspeist und die dann Umschalten kann ohne 
irgendwelche Glitches zu bekommen.


>Zeig doch mal ein Beispiel, wie du das meinst...
Ein Beispiel hab ich noch nicht. Ich plane erst noch mein Design auf 
Papier. Und da bin ich jetzt bei dem zu verwenden variabelen Takt 
angekommen den ich in den Meisten Teilen meines Designs nutzen will um 
bestimmte Aktionen auszuführen.

Heut abend oder morgen hab ich dann vielleicht auch schon mal ein wenig 
Code.


Grüße Steffen

Autor: Steffen H. (avrsteffen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hab das Gefühl, dass sobald man was von Lattice schreibt hier nix mehr 
zurück kommt..

> Wie kann man da sicher sein, dass dann diesen div_CLK im Design auch als
> eine solcher speziellen Clock-Net geroutet wird??
>Antwort: Indem du für abgeleitete Takte einen DCM (Taktmanager) nimmst.
Bei Lattice XP heißen das übrigens DCS. Sind im XP 8 Stück vorhanden. 
Man hat mehrere Modi zum einstellen. Also entweder zwischen 2 
verschiedene Takten mit "SEL" umschalten, Takt abschalten, oder einfach 
nur als Buffer. (siehe Bilder)

Im Beitrag Titel Beitrag "Mehrere Takte aus Referenztakt teilen (PLL)" hab 
ich es dann noch folgendermaßen gesehen:
-- evtl. nötig, wenn die Synthese den neuen Takt nicht selber erkennt
-- attribute buffer_type: string; 
-- attribute buffer_type of cdiv: signal is "bufg"; 

Autor: mac4ever (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube es hat weniger mit Lattice zu tun, als mit fehlenden 
Zusatzinformationen, wie Beispielcode oder eine ausführliche 
Beschreibung. Einfach mit den Signalnamen eines eigenen Designs um sich 
werfen bringt einen nicht wirklich weiter ;)

Prinzipiell empfehle hier als ersten ein gutes Buch zum Thema VHDL und 
etwaigen Design Guidelines vom entsprechenden FPGA-Hersteller. Hier 
scheint es dem ein oder anderen am Verständnis der Beschreibungssprache 
und der resultierenden Hardwarestruktur zu mangeln ... was ich 
prinzipiell nicht verurteile. Jeder fängt mal an. Allerdings 
disqualifiziert man sich selbst, wenn noch nicht einmal die Grundlagen 
vorhanden sind!

@Steffen H.
Was die Sache mit einem enable für 2 Clock-Domains angeht. Hier solltest 
du dir sicher sein, das beide Domains aufeinander einsychronisiert sind. 
So etwas macht man für gewöhnlich über mehrere Sync-Stages. 
Metastabilität ist ein weiteres Stichwort.

Autor: Steffen H. (avrsteffen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich glaube es hat weniger mit Lattice zu tun, als mit fehlenden
>Zusatzinformationen, wie Beispielcode oder eine ausführliche
>Beschreibung. Einfach mit den Signalnamen eines eigenen Designs um sich
>werfen bringt einen nicht wirklich weiter ;)
Ich hab noch keinen Code getippt, da ich erstmal alles auf papier male 
und mir sozusagen schon vorher Gedanken drüber mache, ob es so überhaupt 
geht oder wie ich es überhaupt realisieren möchte/kann. Ich häng mal 
meine Skizze mit an.

>Prinzipiell empfehle hier als ersten ein gutes Buch zum Thema VHDL
Hehe, das bekomm ich erst zu Weihnachten ;)

>Was die Sache mit einem enable für 2 Clock-Domains angeht. Hier solltest
>du dir sicher sein, das beide Domains aufeinander einsychronisiert sind.
>So etwas macht man für gewöhnlich über mehrere Sync-Stages.
>Metastabilität ist ein weiteres Stichwort.
Ich glaube, da haben wir uns falsch verstanden. Das "enable" ist gleich 
dem "ce" aus hier schon oft angegebenen anderen Designs wo es um 
Taktteilung ging die syncron laufen sollen. Nach dem Motto:

Component Taktteiler:
entity Taktteiler is
   Port(
       CLK    : in std_logic;
       enable : out std_logic);
end Taktteiler;

architecture Verhalten of Taktteiler is

constant cnt_div : integer:=16;                   -- Teilerverhältnis
signal   cnt     : integer range 0 to cnt_div -1; -- Zähler für Teiler
signal   ce      : std_logic;

begin 

  process(clk) -- Clock Enable Generator 
  begin
    if rising_edge(clk) then
      if cnt = cnt_div -1 then
        enable  <= '1';
        cnt <= 0;
      else
        enable  <= '0';
        cnt <= cnt +1 ;
      end if;
    end if;
  end process;
enable <= ce;

end Verhalten;

Das "enable" kommt vom Taktteiler, einer anderen Component. Und hier 
z.B. in wieder einer anderen Component wird er genutzt.
entity IRGENDWAS is
   Port(
       CLK    : in std_logic;
       enable : in std_logic);
end IRGENDWAS;

architecture Verhalten of IRGENDWAS is
begin

process(clk)
begin
  if rising_edge(clk) then
    if enable='1' then
 
    -- Aktionen hier einfügen, welche mit langsamen Takt laufen
    -- ***1
 
    end if;
  end if;
end process;

end Verhalten;
Sollte das so gehen?

Grüße Steffen

Autor: Steffen H. (avrsteffen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein anderer Ansatz.
Component "ClockManager" Ich weiß nur noch nicht so Recht wie ich das 
umsetzen soll.

Die PLL ist kein Problem. Da gibt es ja den CoreGen.

Clock_Div:
Dies soll ein variabeler Counter werden der mit dem Prescaler 
eingestellt wird. Der Prescaler soll mal von einer anderen Component 
"Serial_Interface" zur Verfühgung gestellt werden. "update" kommt 
ebenfalls daher. Es ist für genau einen "sys_CLK" auf '1' wenn ein neuer 
"Prescaler" durch das ser.Interface zur Verfühgung steht. Damit will ich 
sicherstellen, dass ein neuer Divider-Wert erst übernommen wird, wenn 
der resultierende "div_CLK" von 1->0 geht. Der "RESET" Eingang ist mit 
dem LOOK der PLL verbunden um sicherzustellen, dass erst nach hochfahren 
der PLL der Counter anfängt zu laufen und auch durch LOOK resetet wird.

DCS:
DCS sollte wieder über den CoreGen zu bewerkstelligen sein. Hoffe ich 
jedenfalls mal. Der Enable Anschluss "en_CLK" ist zum Abschalten der 
"var_CLK" gedacht, da ich bestimmte Teilprozesse nicht ständig am laufen 
haben will die mit dem "var_CLK" getaktet werden sollen. Der DSC routet 
mir vor allem den "var_CLK" auf ein CLOCK-NET. Zumindest hab ich das so 
aus dem Datasheet herausgelesen.

Was sagt ihr zu diesen Ansatz?

Grüße Steffen

Autor: Steffen H. (avrsteffen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, nicht wundern mit dem RST bei der PLL. Steht ebenfalls so im 
Datasheet.
The PLL reset occurs under two conditions. At power-up an internal 
power-up reset signal from the configuration block resets the PLL. The 
user controlled PLL reset signal RST is provided as part of the PLL 
module that can be driven by an internally generated reset function or a 
pin. This RST signal resets all internal PLL counters.

Note: For LatticeECP/EC, RST must be asserted to re-start the locking 
process after losing lock. Refer to the LatticeECP/EC Family Data Sheet 
for the RST pulse width requirement. For LatticeXP, RST may be tied to 
GND.

Autor: mac4ever (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab das Datenblatt nur mal schnell überflogen. So wie es scheint ist 
ein DCS nichts anderes als ein Multiplexer für 2 Clocks. So wie es in 
deinem Design aussieht willst du ein selbst erzeugtes Signal (div_CLK) 
als Eingang für eine solche DCS nehmen. Ich habe große Zweifel ob das 
überhaupt funktioniert. Meines Wissens kann ein Clocknet nur über 
dedizierte Takteingänge gespeist werden. Ein beliebiges Signal an einer 
PLL bzw. als Taktquelle sollte der Compiler als Fehler quittieren. Aber 
ich kann mich auch irren. So tief ist mein Wissen dann wieder auch nicht 
:)
Wenn du wirklich einen variablen Takt in einem System brauchst, dann 
solltest du mal prüfen ob die PLLs auch während des Betriebs 
umkonfiguriert werden können. Bei Altera ist das z.B. möglich. Wenn ich 
das noch richtig im Kopf habe.

Frage: Wofür brauchst du diesen variablen Takt überhaupt? Sollen damit 
andere Teile des Designs betrieben werden oder geht der Takt nur auf 
einen Ausgangstreiber?

Autor: Steffen H. (avrsteffen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn du wirklich einen variablen Takt in einem System brauchst, dann
>solltest du mal prüfen ob die PLLs auch während des Betriebs
>umkonfiguriert werden können.
Die PLL kann man umkonfigurieren. Aber der ClockDivider hat da auch so 
seine Grenzen und ist deshalb nicht brauchbar für meinen gewollten 
variablen Takt. Der Teilt bloß in 2er Schritten und das bloß bis 30.
Siehe:
The CLKOP Divider values are 2, 4, 6, 8,..32 (2, 4, 6, 8..30 for 
LatticeXP devices) if CLKOS is not used. The CLKOP Divider values are 2,
4, 8, 16, 32 (2, 4, 8, 16 for LatticeXP devices) if CLKOS is used. Und 
den mit der PLL erzeugte System Takt "sys_CLK" von 100 Mhz brauch ich 
zusätzlich im System.

>Frage: Wofür brauchst du diesen variablen Takt überhaupt? Sollen damit
>andere Teile des Designs betrieben werden oder geht der Takt nur auf
>einen Ausgangstreiber?
Der soll nacher mal mein Sample- oder Recordingtakt werden. Das heißt, 
ein Trigger, das Data-pre-Register und der Adresszähler für das interne 
Dualport Blockram sollen sollen damit versorgt werden.

Ich werd nochmal überprüfen mit welchen Signalen ich den DCS versorgen 
kann.


Gruß
Steffen

Autor: Steffen H. (avrsteffen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>So wie es in deinem Design aussieht willst du ein selbst erzeugtes Signal 
>(div_CLK) als Eingang für eine solche DCS nehmen. Ich habe große Zweifel ob >das 
überhaupt funktioniert. Meines Wissens kann ein Clocknet nur über >dedizierte 
Takteingänge gespeist werden. Ein beliebiges Signal an einer
>PLL bzw. als Taktquelle sollte der Compiler als Fehler quittieren.

Ich glaube es geht. Wenn man sich mal das primäre Clock Net anschaut, 
kann man wie ich das sehe auch vom general Routing zu den DCS gelangen. 
Oder irre ich mich da?

Autor: mac4ever (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen H. schrieb:
> Der soll nacher mal mein Sample- oder Recordingtakt werden. Das heißt,
> ein Trigger, das Data-pre-Register und der Adresszähler für das interne
> Dualport Blockram sollen sollen damit versorgt werden.

Warum nimmst du nicht einfach einen festen Takt und regelst das über 
Enable-Signale?

Steffen H. schrieb:
> Ich glaube es geht. Wenn man sich mal das primäre Clock Net anschaut,
> kann man wie ich das sehe auch vom general Routing zu den DCS gelangen.
> Oder irre ich mich da?

Stimmt, sie tatsächlich danach aus. Versuch macht klug :)

Autor: Sym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verwende doch enable Signale anstatt den Takt wirklich runter zu teilen 
(wie in meinem Beispiel und dem von Steffen). Vorteil der Enable 
Signale: Alles arbeitet synchron mit einem Takt und du ersparst dir die 
Taktübergänge, die eine potentielle Fehlerquelle in der realen Hardware 
sind. Natürlich kann man chip enables auch problemlos beliebig oft 
kaskadieren, was bei Gated Clocks Probleme bringen kann.

Ob Lattice, Xilinx, Altera und was auch immer ist egal. Chip enables 
werden meist nativ von den Zellen unterstützt und sind somit meist die 
beste Lösung.

Autor: Steffen H. (avrsteffen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo und einen schönen 3.Advent

Ich hab mich mal an meinen CLOK_DIV herangewagt. Hab es jetzt 
Tatsächlich über Clock-enable gemacht. Laut Simulation scheint es zu 
funktionieren. Wäre schön, wenn nochmal jemand über den Code schauen 
könnte und eventuell Fehler entdeckt weil man das einfach so nicht macht 
wie ich es lösen will.
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 CLOCK_DIV is

port( 
  CLKIN    : in std_logic ; -- 100Mhz kommt von PLL
  UPDATE    : in std_logic ; -- Impuls 1 Taktzyklus lang
  RST    : in std_logic ; -- kommt von LOOK der PLL
  en_CLK    : in std_logic ; -- Enable CLKCE out
  PRESC    : in std_logic_vector ( 4 downto 0 ); -- Prescaler
  CLKCE    : out std_logic  ); -- Clock enable (chip enable)

end;

architecture Verhalten of CLOCK_DIV is


signal  cnt_div  : integer range 0 to 20000000-1;  -- Teilerverhältnis
signal  cnt  : integer range 0 to 20000000-1; -- Zähler für Teiler
signal  ce      : std_logic := '0';


begin



process(CLKIN,RST) -- Clock Enable Generator 
  begin
    if RST = '1' then  -- asynchroner Reset: = LOOK und kommt von PLL
       ce <= '0';
       cnt <= 0;
    else
      if rising_edge(CLKIN) then
         if UPDATE ='1' then
      cnt <= 0;
      ce <= '1';
      case PRESC is --                        PRESC|fSAMPLE | t/div
      when "00000" => cnt_div <=        0;   --  0 |  80Mhz | 250ns  
      when "00001" => cnt_div <=        2-1; --  1 |  40Mhz | 500ns
      when "00010" => cnt_div <=        4-1; --  2 |  20Mhz |   1µs
      when "00011" => cnt_div <=        8-1; --  3 |  10Mhz |   2µs
      when "00100" => cnt_div <=       20-1; --  4 |   4Mhz |   5µs
      when "00101" => cnt_div <=       40-1; --  5 |   2Mhz |  10µs
      when "00110" => cnt_div <=       80-1; --  6 |   1Mhz |  20µs
      when "00111" => cnt_div <=      200-1; --  7 | 400khz |  50µs
      when "01000" => cnt_div <=      400-1; --  8 | 200khz | 100µs
      when "01001" => cnt_div <=      800-1; --  9 | 100khz | 200µs
      when "01010" => cnt_div <=     2000-1; -- 10 |  40khz | 500µs
      when "01011" => cnt_div <=     4000-1; -- 11 |  20khz |   1ms
      when "01100" => cnt_div <=     8000-1; -- 12 |  10khz |   2ms
      when "01101" => cnt_div <=    20000-1; -- 13 |   4khz |   5ms
      when "01110" => cnt_div <=    40000-1; -- 14 |   2khz |  10ms
      when "01111" => cnt_div <=    80000-1; -- 15 |   1khz |  20ms
      when "10000" => cnt_div <=   200000-1; -- 16 | 400 hz |  50ms
      when "10001" => cnt_div <=   400000-1; -- 17 | 200 hz | 100ms
      when "10010" => cnt_div <=   800000-1; -- 18 | 100 hz | 200ms
      when "10011" => cnt_div <=  2000000-1; -- 19 |  40 hz | 500ms
      when "10100" => cnt_div <=  4000000-1; -- 20 |  20 hz |   1 s
      when "10101" => cnt_div <=  8000000-1; -- 21 |  10 hz |   2 s
      when "10110" => cnt_div <= 20000000-1; -- 22 |   4 hz |   5 s
      when others =>
      end case;
   else
           if cnt = cnt_div then  -- Wenn cnt = Teilerwert
              cnt <= 0;
        ce <= '1';
          else
              cnt <= cnt +1 ;
        ce <='0';
          end if;
  end if;
      end if;
    end if;
  end process;


process(CLKIN) -- Enable CLKCE out
  begin
  if rising_edge(CLKIN) then
    if en_CLK = '1' then
    CLKCE <= ce;
    else
    CLKCE <= '0';
    end if;
  end if;
  end process;

end Verhalten;
Zur Beschreibung:
Die Taktteilung soll über CLKCE im weiteren System erfolgen. Es kommen 
also für genau einen Haupttakt (CLKIN) CLKCE Impulse die abhängig vom 
gewählten Prescaler PRESC ein bestimmtes Pausenverhältnis haben. CLKCE 
wird wenn en_CLK = 1 ist ausgegeben.
Über UPDATE wird ein neuer Prescaler übernommen.

Was sagt ihr zu dieser Lösung?

Grüße
Steffen

Autor: mac4ever (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieht soweit ganz fernünftig aus. Den zweiten Prozess könntest du dir 
eigentlich sparen und durch ein Concurrent Statement erreichen.
CLKCE <= ce when en_CLK = '1' else '0';

Einfach innerhalb des architecture body schreiben. Also außerhalb des 
Pozesses. Muss man nicht so machen, erspart aber die zusätzliche 
Pufferung und somit die Verzögerung am Ausgang.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.