Forum: FPGA, VHDL & Co. latch bei synthese mit bedingter zuweisung


von mchii (Gast)


Lesenswert?

Hallo

folgenden code habe ich von lothar-miller ein binaer counter, nun wollte 
ich den code so verändern das ich den Takt clk in 2^x stufen dividieren 
kann.

Dazu habe ich ein Singal "takt" erzeugt das nach jedem durchlauf 
getoggelt wird (not) und mit max_tick auf dem output verbunden ist. Nun 
meldet Xilinx ISE 11.5 aber ein Latch:

WARNING:Xst:737 - Found 1-bit latch for signal <takt>. Latches may be 
generated from incomplete case or if statements. We do not recommend the 
use of latches in FPGA/CPLD designs, as they may lead to timing 
problems.

Frage wo liegt mein Problem bei diesem if?
  takt <= not takt when r_reg=(2**N-1) else takt;

wo liegt mein Denkfehler?
1
entity free_run_bin_counter is
2
  generic(N: integer := 8);
3
  port(
4
      clk, reset: in std_logic;
5
      max_tick: out std_logic;
6
      q: out std_logic_vector(N-1 downto 0)
7
      );
8
end free_run_bin_counter;
9
10
architecture arch of free_run_bin_counter is
11
  signal r_reg: unsigned(N-1 downto 0);
12
  signal r_next: unsigned(N-1 downto 0);
13
  signal takt: std_logic;
14
begin
15
  process(clk, reset)
16
  begin
17
    if( reset = '1') then
18
      r_reg <= (others => '0');
19
    elsif rising_edge(clk) then
20
      r_reg <= r_next;
21
    end if;
22
  end process;  
23
  r_next <= r_reg +1;
24
  q <= std_logic_vector(r_reg);
25
  takt <= not takt when r_reg=(2**N-1) else takt;
26
  max_tick <= takt;
27
end arch;

von mchii (Gast)


Lesenswert?

kurzer nachtrag Code ist NICHT von lothar miller... entschuldigung für 
die falsche angabe...

lg

von Jan M. (mueschel)


Lesenswert?

>Dazu habe ich ein Singal "takt" erzeugt das getoggelt wird
Ja.

>Dazu habe ich ein Singal "takt" erzeugt das nach jedem durchlauf getoggelt wird
Nein.

Das Signal toggelt solange mit der maximal möglichen Frequenz hin und 
her wie r_reg=(2**N-1) gilt. Du willst aus takt ein Flipflop machen, das 
seinen Zustand nur bei einer Taktflanke ändert.

von Duke Scarring (Gast)


Lesenswert?

mchii schrieb:
> wo liegt mein Denkfehler?
Da fehlt die Testbench dazu...

von mchii (Gast)


Lesenswert?

Stimmt testbench fehlt... (hab ich mich noch nicht damit befasst)

Habs jetzt so gemacht, frage mir kommt das umständlich vor hat jemand 
eine "sauberere Lösung"?
1
entity free_run_bin_counter is
2
  generic(N: integer := 8);
3
  port(
4
      clk, reset: in std_logic;
5
      max_tick: out std_logic;
6
      q: out std_logic_vector(N-1 downto 0)
7
      );
8
end free_run_bin_counter;
9
10
architecture arch of free_run_bin_counter is
11
  signal r_reg: unsigned(N-1 downto 0);
12
  signal r_next: unsigned(N-1 downto 0);
13
  signal flag: std_logic;
14
  signal takt: std_logic;
15
begin
16
  process(clk, reset)
17
  begin
18
    if( reset = '1') then
19
      r_reg <= (others => '0');
20
    elsif rising_edge(clk) then
21
      r_reg <= r_next;
22
    end if;
23
  end process;  
24
  
25
  process(flag)
26
  begin
27
    if rising_edge(flag) then
28
      takt <= not takt;
29
    end if;
30
  end process;
31
  
32
  r_next <= r_reg +1;
33
  q <= std_logic_vector(r_reg);
34
        -- flag erzeugen
35
  flag <= '1' when r_reg=(2**N-1) else '0';
36
37
  max_tick <= takt;
38
39
end arch;

lg Mchii

von Uwe (Gast)


Lesenswert?

Das Ausgangssignal (2^n) das du willst liegt einfach am entsprechenden 
q(n-1) an. Damit toggelst du ein JK-FlipFlop. Fetisch

von Uwe (Gast)


Lesenswert?

Achso JK-FF brauchst du noch nicht mal.

von Matthias G. (mgottke)


Lesenswert?

Hallo mchii

Du hast noch ein paar Probleme in dem Verständnis, was der unterschied 
zwischen Software und Hardwarebeschreibung ist. Versuche Dich von dem 
Gedanken zu lösen, dass du Hardware programmierst.

Um ein Signal stabil in einem Zustand zu halten bedarf es ein 
Speicherelement. Dies sollte im FPGA (oder CPLD) immer ein FlipFlop 
sein. Ein Latch ist immer zu vermeiden.

Um ein FF zu beschreiben bedarf es (für den Anfänger) immer ein Prozess 
mit einem Takt. Dein folgender Ansatz
1
  process(flag)
2
  begin
3
    if rising_edge(flag) then
4
      takt <= not takt;
5
    end if;
6
  end process;

ist daher nicht verkehrt. Das Signal Takt invertiert sich immer wenn das 
Singal flag eine steigende Flanke hat.

Allerdings stellt das Signal flag hier das Problem dar:
1
  flag <= '1' when r_reg=(2**N-1) else '0';

Warum: Was hier beschrieben ist ist eine sogenannte beiläufige 
Anweisung. Es entsteht hier eine Schaltungslogik die aus den 
Grundgattern (UND, ODER, NAND...) zusammengebaut ist. Wenn sich nun ein 
oder mehrere Signale am Eingang dieser Gatterkombination (also ein bit 
aus r_reg) ändert, dann hat das zur Folge dass sich ev. das Signal flag 
ändert. Wenn Du aber pech hast, dann ändert wegen der Laufzeiten auf den 
Leitungen (Signal) und den Durchlaufzeiten in den Gattern dein 
flag-Signal für einen kurzen Moment obwohl es sich aus Deiner Logik 
nicht ändern sollte. Dies nennt man Glitch.

Als Feste Regel sollte daher sein, dass ein Takt immer nur exakt eine 
Quelle haben sollte. Das flag-Signal von Dir wir ja als Takt verwendet.

Um das ganze trotzdem korrekt zu lösen, könntest Du folgendes tun:
1
  process(clk)
2
  begin
3
    if rising_edge(clk) then
4
      if r_reg=(2**N-1) then
5
        takt <= not takt;
6
      end if;
7
    end if;
8
  end process;

Was hier entsteht ist ein FF dessen Ausgang invertiert auf den Eingang 
zurück geführt wird. Die Verknüfung r_reg=(2**N-1) ergibt dann ein 
Signal das an den Enable Eingang des FF geführt wird.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

mchii schrieb:
> kurzer nachtrag Code ist NICHT von lothar miller...
Richtig. Ich mache (so gut wie keine) Latches...
> entschuldigung für die falsche angabe...
Du bist hiermit entschuldigt... ;-)

Matthias G. schrieb:
> Um das ganze trotzdem korrekt zu lösen...
Diese Lösung entspricht nicht ganz dem ursprünglichen Problem:
>>>   flag <= '1' when r_reg=(2**N-1) else '0';
Das ist eigentlich kein TAKT, sondern ein ENABLE, das alle 2**N 
Taktzyklen für genau 1 Taktzyklus aktiv ist. Takte (Mehrzahl) gibt es in 
einem Anfängerdesign nicht. Sondern es gibt nur 1 Takt. Fertig.

Die Lösung sieht also so aus:
1
  process(clk)
2
  begin
3
    if rising_edge(clk) then
4
      if r_reg=(2**N-1) then takt <= '1';
5
      else                   takt <= '0';
6
      end if;
7
    end if;
8
  end process;

von mchii (Gast)


Lesenswert?

Hallo

Danke für die Hilfe mgottke und ausführliche Erklärung, dadurch ergeben 
sich jedoch ein paar fragen.

1, meinst du damit das ich IMMER nur clk auf die empfindlichkeits liste 
setzen soll?

2.) die Lösung hier funktioniert, was ist jedoch wenn der Fall 
r_reg=(2**N-1) für 2 oder GÜLTIG wäre, dann bräuchte ich ja wieder eine 
Flanke... wie mach ich es da?


Dieses beispiel hier dürfte ja nicht "richtig" sein...
process(clk)
begin
if rising_edge(clk) then
  if rising_edge(flanke) then
    ....

@lothar
ebenfalls danke für die hilfe, dein Beispiel ist ein Enable, ich jedoch 
wollte dieses Enable als Flag nutzen um den Takt in entsprechende Stücke 
zu teilen....

lg mchii

von mchii (Gast)


Lesenswert?

korrektur von 2.)

2.) die Lösung hier funktioniert, was ist jedoch wenn der Fall
r_reg=(2**N-1) für 2 oder mehr takte GÜLTIG wäre, dann bräuchte ich ja 
wieder eine
Flanke... wie mach ich es da?

von mchii (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

hm der code erzeugt noch immer ein Latch, aber ohne Xilinx ise warning.

1
entity free_run_bin_counter is
2
  generic(N: integer := 30);
3
  port(
4
      clk, reset: in std_logic;
5
      max_tick: out std_logic
6
--      q: out std_logic_vector(N-1 downto 0)
7
      );
8
end free_run_bin_counter;
9
10
architecture arch of free_run_bin_counter is
11
  signal r_reg: unsigned(N-1 downto 0);
12
  signal r_next: unsigned(N-1 downto 0);
13
--  signal flag: std_logic;
14
  signal takt: std_logic;
15
begin
16
  process(clk, reset)
17
  begin
18
    if( reset = '1') then
19
      r_reg <= (others => '0');
20
    elsif rising_edge(clk) then
21
      r_reg <= r_next;
22
    end if;
23
  end process;  
24
  
25
  process(clk)
26
  begin
27
    if rising_edge(clk) then
28
      if r_reg=(2**N-1) then
29
        takt <= not takt;
30
      end if;
31
    end if;
32
  end process;
33
  
34
  r_next <= r_reg +1;
35
--  q <= std_logic_vector(r_reg);
36
  max_tick <= takt;
37
end arch;

von mchii (Gast)


Lesenswert?

Habe jetzt mal folgendes versucht jedoch OHNE erfolg... was führt zu 
diesem latch?
1
  process(clk)
2
  begin
3
    if rising_edge(clk) then
4
      if r_reg=(2**N-1) then
5
        takt <= not takt;
6
      else
7
        takt <= takt;
8
      end if;
9
    end if;
10
  end process;

von Matthias G. (mgottke)


Angehängte Dateien:

Lesenswert?

> hm der code erzeugt noch immer ein Latch, aber ohne Xilinx ise warning.

Bei mir gibt es da kein Latch. Für N=2 entsteht die Schaltung im Bild.

@ Lothar
> Diese Lösung entspricht nicht ganz dem ursprünglichen Problem:

Da hast Du schon recht. Ich hatte noch die gleichen Gedanken dazu. Hier 
liegt aber so ein bisschen ein Sonderfall zu. max_tick (spich takt) ist 
hier ein Ausgang. Sehr vermutlich wird aber der Block, und daher auch 
der Takt, im FPGA weiter verwendet. Das wäre ungünstig.

Ich wollte erst mal nur ein Problemchen beleuchten um das Verständnis 
dafür zu wecken.

Für Anfänger: Es gibt nur genau 1 Takt im Design. Alles andere läuft 
über Enable.
Für Fortgeschrittene und Profis: Es gibt auch nur 1 Takt. Ausnahmen 
bestätigen die Regel. Taktübergänge sind immer kritisch.

von michi m. (mchii)


Lesenswert?

Du hast recht da kommt kein latch, jedoch updatet das "View RTL 
schematic" nicht bei änderungen selbst wenn ich force klicke, irgend 
eine idee wie ich das im XilinxISE mache ohne neu zu starten?


bleiben noch meine Fragen zu vorhin:

2.) die Lösung hier funktioniert, was ist jedoch wenn der Fall
r_reg=(2**N-1) für 2 oder mehrere Takte GÜLTIG wäre, dann bräuchte ich 
ja wieder eine
Flanke... wie mach ich es da?


Dieses beispiel hier dürfte ja nicht "richtig" sein...
process(clk)
begin
if rising_edge(clk) then
  if rising_edge(flanke) then
    ....

lg Michi

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

michi m. schrieb:
> Dieses beispiel hier dürfte ja nicht "richtig" sein...
> process(clk)
> begin
> if rising_edge(clk) then
>   if rising_edge(flanke) then
>     ....
So ein Bauteil mit 2 Takteingängen gibt es nicht in einem FPGA. Für die 
Simulation darfst du das aber trotzdem so hinschreiben... ;-)

mchii schrieb:
> 1, meinst du damit das ich IMMER nur clk auf die empfindlichkeits liste
> setzen soll?
Auf die Sensitvliste (die ausschliesslich für den Simulator interessant 
ist!) gehören alle Signale, die eine Neuberechnung des Prozesses für die 
Simulation nötig machen.
KURZ: die Sensitivliste ist nur für die Simulation interessant.
ABER: wenn die Sensitivliste nicht korrekt ist, stimmt auch die 
Simulation nicht!

mchii schrieb:
> hm der code erzeugt noch immer ein Latch, aber ohne Xilinx ise warning.
Ich kann Matthias nur bestätigen: dieses Bild gehört nicht zu dem dazu 
geposteten Code.

von michi m. (mchii)


Lesenswert?

Lothar Miller schrieb:
> So ein Bauteil mit 2 Takteingängen gibt es nicht in einem FPGA. Für die
> Simulation darfst du das aber trotzdem so hinschreiben... ;-)
>
Ja das war mir bewusst, nur meinte Matthias ich solle nur eine 
"Taktquelle" verwenden im ganzen Design (wenn ich das richtig gelesen 
hab) nun war aber meine Frage wenn dieses Enable als Flag nutzen will, 
das Enable aber über 2 oder Mehr taktzyklen aktiv ist wie ich hier dann 
auf die Flanke Triggern soll, wenn im ganzen Design nur ein Takt 
existieren soll.


> mchii schrieb:
>> hm der code erzeugt noch immer ein Latch, aber ohne Xilinx ise warning.
Lothar Miller schrieb:
> Ich kann Matthias nur bestätigen: dieses Bild gehört nicht zu dem dazu
> geposteten Code.
Ja wie schon oben geschrieben hat mein Xilinx RTL Schematic den Plan 
nicht aktuallisiert.... (selbst bei expliziter aufforderung)

lg Michi

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

michi m. schrieb:
> das Enable aber über 2 oder Mehr taktzyklen aktiv ist wie ich hier dann
> auf die Flanke Triggern soll, wenn im ganzen Design nur ein Takt
> existieren soll.
Ich würde das so machen, wenn das Enable ein externes Signal wäre:
http://www.lothar-miller.de/s9y/categories/19-SpikePuls
Oder so:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung

> wenn dieses Enable als Flag nutzen will,
> das Enable aber über 2 oder Mehr taktzyklen aktiv ist
Ich verstehe das Problem nicht ganz: wenn du das Enable im FPGA 
erzeugst, dann ist es genauso lang, wie du es beschrieben hast.

von michi m. (mchii)


Lesenswert?

Danke für die Hilfe.


Ich verstehe deine Bedenken, nun ist halt eine Anfängerfrage da macht 
man sich um solche Dinge gedanken auch wenn das Signal von einem Selbst 
erzeugt wird.

Danke für die Links.


lg Michi

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.