Forum: FPGA, VHDL & Co. Werden hier Latches erzeugt?


von Pat R. (patrik)


Lesenswert?

Hallo Leute,
ich habe ein Problem mit meinen Signalen, vermutlich wegen Latches.
Also ich habe drei Module, MemoryOrganizer, Linearizer und 
ControlCenter.
Linearizer holt sich Werte vom Memoryorganizer und gibt diese an 
ControlCenter weiter. ControlCenter verbindet diese zwei Module und gibt 
die Werte vom Linearizer auf Leds aus.
Hier die Code-Ausschnitte:

MemoryOrganizer:
  value <= value_int;

  process(mem_clock, reset)
  begin
    if reset = '1' then
      value_int <= "0000000000";
    elsif mem_clock'event and mem_clock = '1' then
      if address = "000111111100010011100000" then
        value_int <= "0000000" & count_int;
      else
        value_int <= "1111111" & count_int;
      end if;

    end if;
  end process;

  process(reset, clk)
  begin
    if reset = '1' then
      mem_clk_fsm <= clk_wait_for_start;
      ready <= '1';
      DONE <= '0';
      mem_clock_last <= '0';
    elsif clk'event and clk = '1' then
      case mem_clk_fsm is
        when clk_wait_for_start =>
          int_clk <= "000";
          done <= '0';

          if start = '1' then
            count_int <= count;
            ready <= '0';
            mem_clk_fsm <= clk_processing;
          else
            ready <= '1';
          end if;
        when clk_processing =>
          int_clk <= int_clk + 1;

          mem_clock_last <= mem_clock;

          if mem_clock = '1' and mem_clock_last = '0' then
            count_int <= count_int - '1';
            done <= '1';
          else
            done <= '0';
          end if;

          if count_int = "000" then
            mem_clk_fsm <= clk_wait_for_start;
          end if;
      end case;
    end if;
  end process;


----------------------------------------------------------------------

Linearizer:


  MEM_VALUE_1A <= mem_value_a_int;


  process(clk, reet)
  begin
  if reset = '1' then
  .
  .
  elsif clk'event and clk = '1' then
    .
    .
    when wait_for_mem1 =>
      if mem_done = '1' then
        main_fsm <= wait_for_mem2;
        -- hier testweise an mem_value_a_int zugewiesen
        if address = "000111111100010011100000" then
          mem_value_a_int <= MEM_VALUE;
        end if;
      end if;
    .
    .
    when wait_for_mem4 =>
      if mem_done = '1' then
        if address = "000111111100010011100000" then
          MEM_VALUE_1B <= MEM_VALUE;
        end if;
        main_fsm <= wait_for_mem5;
      end if;
    .
    .
    when wait_for_mem7 =>
      if mem_done = '1' then
        if address = "000111111100010011100000" then
          MEM_VALUE_1C <= MEM_VALUE;
        end if;
        main_fsm <= wait_for_mem8;
      end if;
    .
    .
    when wait_for_mem10 =>
      if mem_done = '1' then
        main_fsm <= wait_for_mem11;
        if address = "000111111100010011100000" then
          MEM_VALUE_1D <= MEM_VALUE;
        end if;
        IS_ZERO <= '0';
        IS_POSITIVE <= '1';
      end if;
    .
    .
  end if
  end process;

------------------------------------------------------------------------

ControlCenter:
leds <=  MEM_VALUE_1A(7 downto 0);

------------------------------------------------------------------------

Gewünscht ist, dass MEM_VALUE_1A(7 downto 0) den Wert "00000110" hat. 
Tatsächlich, wenn mem_value_a_int <= MEM_VALUE; im Linearizer aufgerufen 
wird, hat MEM_VALUE den korrekten Wert "0000000110"(habe ich am Osci 
gemessen). Allerdings behält mem_value_a_int und damit auch MEM_VALUE_1A 
diesen Wert nicht, sonder ändert sich sobald MEM_VALUE an MEM_VALUE_1B, 
MEM_VALUE_1C oder MEM_VALUE_1D zugewiesen wird. Und am Ende haben alle 
Signale den Wert von MEM_VALUE_1D. Es sieht für mich nach Latches, hier 
die Meldungen von der Synthese:

INFO:Xst:2261 - The FF/Latch <value_int_3> in Unit <MemoryOrganiser> is 
equivalent to the following 6 FFs/Latches, which will be removed : 
<value_int_4> <value_int_5> <value_int_6> <value_int_7> <value_int_8> 
<value_int_9>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_0> in Unit <Linearizer> is 
equivalent to the following 4 FFs/Latches, which will be removed : 
<MEM_VALUE_1B_0> <MEM_VALUE_1D_0> <leds_0> <mem_value_a_int_0>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_1> in Unit <Linearizer> is 
equivalent to the following 4 FFs/Latches, which will be removed 
:<MEM_VALUE_1B_1> <MEM_VALUE_1D_1> <leds_1> <mem_value_a_int_1>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_2> in Unit <Linearizer>
is equivalent to the following 4 FFs/Latches, which will be removed :
<MEM_VALUE_1B_2> <MEM_VALUE_1D_2> <leds_2> <mem_value_a_int_2>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_3> in Unit <Linearizer>
is equivalent to the following 4 FFs/Latches, which will be removed :
<MEM_VALUE_1B_3> <MEM_VALUE_1D_3> <leds_3> <mem_value_a_int_3>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_4> in Unit <Linearizer>
is equivalent to the following 4 FFs/Latches, which will be removed :
<MEM_VALUE_1B_4> <MEM_VALUE_1D_4> <leds_4> <mem_value_a_int_4>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_5> in Unit <Linearizer>
is equivalent to the following 4 FFs/Latches, which will be removed :
<MEM_VALUE_1B_5> <MEM_VALUE_1D_5> <mem_value_a_int_5> <leds_5>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_6> in Unit <Linearizer>
is equivalent to the following 4 FFs/Latches, which will be removed :
<MEM_VALUE_1B_6> <MEM_VALUE_1D_6> <mem_value_a_int_6> <leds_6>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_7> in Unit <Linearizer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_1B_7> <MEM_VALUE_1D_7> <mem_value_a_int_7>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_8> in Unit <Linearizer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_1B_8> <MEM_VALUE_1D_8> <mem_value_a_int_8>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_1C_9> in Unit <Linearizer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_1B_9> <MEM_VALUE_1D_9> <mem_value_a_int_9>

Und jetzt meine Fragen, sind es Latches, wenn ja warum und wie kann ich 
sie beseitigen?

Danke
Patrik

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


Lesenswert?

Zur Beruhigung:
Das sind keine Latches.
Irgendwas in der Beschreibung verleitet den Synthesizer dazu, 
anzunehmen, dass MEM_VALUE_1C = MEM_VALUE_1B = MEM_VALUE_1D = leds = 
mem_value_a_int. Wie sieht denn die Adressdecodierung komplett aus?


Zu Beunruhigung:
Du überquerst Taktdomänen asynchron. Viel Erfolg dabei.
1
    elsif mem_clock'event and mem_clock = '1' then  --### Domäne 1
2
      if address = "000111111100010011100000" then
3
        value_int <= "0000000" & count_int;  ---------
4
  :
5
  :
6
  process(reset, clk)
7
  begin
8
     :
9
    elsif clk'event and clk = '1' then --## Domäne 2
10
     :
11
            count_int <= count;     ------------------
Oder ist der mem_clock synchron zum clk?
Falls ja: warum arbeitest du dann nicht mit Clock-Enables?

von Pat R. (patrik)


Lesenswert?

Was meinst du mit 'Adressdecodierung'? Falls du das Signal address 
meinst, das wird aus mehreren anderen Signalen berechnet.

mem_clock ist das dritte Bit von int_clk: std_logic_vector(2 downto 0). 
Und int_clk wird Taktsynchron hochgezählt. In diesem Fall ist also 
mem_clock 4 Takte High und 4 Takte Low.
Ich will einfach nur, dass der Linearizer ein paar Taktzycklen warten 
muss, bis er den Wert vom MemoryOrganizer bekommt. Denn MemoryOrganizer 
simuliert nur eine Schnittstelle zum Speicher, wird aber später ersetzt 
und dann wird es ein bissl dauern bis die Werte aus dem Speicher 
eingelesen werden.

von Pat R. (patrik)


Lesenswert?

Lothar Miller wrote:
> Zur Beruhigung:
> Das sind keine Latches.
> Irgendwas in der Beschreibung verleitet den Synthesizer dazu,
> anzunehmen, dass MEM_VALUE_1C = MEM_VALUE_1B = MEM_VALUE_1D = leds =
> mem_value_a_int. Wie sieht denn die Adressdecodierung komplett aus?
>

Und nicht nur dass, sondern
MEM_VALUE_1C = MEM_VALUE_1B = MEM_VALUE_1D = leds = mem_value_a_int = 
MEM_VALUE

denn wann immer sich MEM_VALUE ändert, ändern sich auch alle diese vier 
Signale.

von Pat R. (patrik)


Lesenswert?

Wenn ich an mem_value_a_int einen konstanten Wert zuweise, behält dieses 
Signal diesen Wert. Sobald ich diesem Signal MEM_VALUE zuweise...

von Pat R. (patrik)


Lesenswert?

Noch vollständigkeitshalber, MEM_VALUE ist mit value_int verbunden.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Schau dir doch einfach mal den erzeugten Schaltplan an, da kannst du 
schnell erkennen ob etwas unerwünschtes synthetisiert wurde oder etwas 
wichtiges fehlt.

von Pat R. (patrik)


Lesenswert?

Also ich habe den Linearizer so weit wie möglich reduziert und das Modul 
sieht wie folgt aus:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Linearizer is
  PORT(
      CLK : IN STD_LOGIC;
      RESET : IN STD_LOGIC;
      MEM_DONE : in STD_LOGIC;
      MEM_VALUE : in STD_LOGIC_VECTOR(4 downto 0);
      MEM_START : out STD_LOGIC;
      RESULT : OUT STD_LOGIC_VECTOR(7 downto 0)
  );

end Linearizer ;

architecture Behavioral of Linearizer is


signal MEM_VALUE_A, MEM_VALUE_B, MEM_VALUE_C, MEM_VALUE_D :
STD_LOGIC_VECTOR(4 downto 0);

type main_fsm_type is (wait_for_start, start_mem_read1, mem_start1,
wait_for_mem1, wait_for_mem2, wait_for_mem3, wait_for_mem4,
wait_for_mem5);
signal main_fsm : main_fsm_type;

begin


  process(clk, reset)
  begin
    if reset = '1' then
      mem_start <= '0';
      main_fsm <= wait_for_start;
      result <= "00000000";
    elsif clk'event and clk = '1' then
      case main_fsm is
        when wait_for_start =>
          main_fsm <= start_mem_read1;
        when start_mem_read1  =>
          main_fsm <= mem_start1;
          MEM_START <= '1';
        when mem_start1 =>
          MEM_START <= '0';
          main_fsm <= wait_for_mem1;
        when wait_for_mem1 =>
          if mem_done = '1' then
            MEM_VALUE_A <= MEM_VALUE;
            main_fsm <= wait_for_mem2;
          end if;
        when wait_for_mem2 =>
          if mem_done = '1' then
            MEM_VALUE_B <= MEM_VALUE;
            main_fsm <= wait_for_mem3;
          end if;
        when wait_for_mem3 =>
          if mem_done = '1' then
            MEM_VALUE_C <= MEM_VALUE;
            main_fsm <= wait_for_mem4;
          end if;
        when wait_for_mem4 =>
          if mem_done = '1' then
            main_fsm <= wait_for_mem5;
            MEM_VALUE_D <= MEM_VALUE;
          end if;
        when wait_for_mem5 =>
RESULT(4 downto 0) <=MEM_VALUE_A + MEM_VALUE_B + MEM_VALUE_C + 
MEM_VALUE_D;

          main_fsm <= wait_for_start;
      end case;
    end if;
  end process;

end Behavioral;


Was sagt die Synthese?
INFO:Xst:2261 - The FF/Latch <MEM_VALUE_D_0> in Unit <PercentualRetimer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_A_0> <MEM_VALUE_B_0> <MEM_VALUE_C_0>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_D_1> in Unit <PercentualRetimer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_A_1> <MEM_VALUE_B_1> <MEM_VALUE_C_1>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_D_2> in Unit <PercentualRetimer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_A_2> <MEM_VALUE_B_2> <MEM_VALUE_C_2>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_D_3> in Unit <PercentualRetimer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_A_3> <MEM_VALUE_B_3> <MEM_VALUE_C_3>

INFO:Xst:2261 - The FF/Latch <MEM_VALUE_D_4> in Unit <PercentualRetimer>
is equivalent to the following 3 FFs/Latches, which will be removed :
<MEM_VALUE_A_4> <MEM_VALUE_B_4> <MEM_VALUE_C_4>

Und wenn ich einen Testmodul dazu schreibe und es auf dem Spartan3E 
StarterKit Board laufen lasse und mir das Ergebnis 'Result' anschaue, 
dann wird tatsächlich alles durch MEM_VALUE_D ersetzt und als Result 
steht MEM_VALUE_D + MEM_VALUE_D + MEM_VALUE_D + MEM_VALUE_D.

Die Simualtion zeigt das korrektes Ergebnis => VERZWEIFLUNG!

Kann mir jemand erklären was ich falsch mache?

Patrik

von Pat R. (patrik)


Lesenswert?

Andreas Schwarz wrote:
> Schau dir doch einfach mal den erzeugten Schaltplan an, da kannst du
> schnell erkennen ob etwas unerwünschtes synthetisiert wurde oder etwas
> wichtiges fehlt.

Ich habe es soeben versucht und soweit ich es verstehen konnte, sind 
MEM_VALUE_A, MEM_VALUE_B und MEM_VALUE_C futsch :-(

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


Angehängte Dateien:

Lesenswert?

Der Synthesizer ist schlauer, als du denkst:
der sieht, dass diese MEM_VALUE_(A..D) nirgends verwendet werden und 
optimiert sie raus. Verwende die Signale, oder führe sie nach aussen 
(Anhang), dann klappts auch mit der Nachbarin ;-)

EDIT:
Verwenden heißt: nicht nur in einem Zustand (wait_for_mem5) verwenden.

von Pat R. (patrik)


Angehängte Dateien:

Lesenswert?

also ich mache wohl etwas ganz falsch! Ich habe es mit deinem code 
versucht, funct aber nicht :(
Die Synthese bringt immer noch die Meldungen die ich hier schon gepostet 
habe.
Schaue dir  bitte das Bild im Anhang, das ist imho Müll pur!
Das ist doch result <= (((mem_value + mem_value)+ mem_value)+mem_value);

Das sehe ich nämlich auch auf den leds.

Ich benutze ISE 10.1. Kann man da nicht irgendwie einstellen, dass er 
das nicht 'wegoptimiert'?

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


Angehängte Dateien:

Lesenswert?

Was du da bekommst ist Käse :-(
Sowas habe ich mit deiner ursprünglichen Beschreibung erhalten.

Meine Zielarchitektur: Spartan 3
Die Synthese-Einstellungen: Alles auf Default
Meine SW-Version: 8.2.03i
Mein Ergebnis: Anhang

von Pat R. (patrik)


Lesenswert?

aha, da haben es die Entwickler von ISE zu gut gemeint. Kann ich 
irgendwo die ältere ISE Version runterladen?

Aber, ich kann mir ehrlich gesagt nicht vorstellen, dass die 10.1 
Version nicht in der Lage wäre, den Code zu syntetisieren, so dass das 
richtige Ergebenis rauskommt.

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


Lesenswert?

Patrik Krizan wrote:
> Aber, ich kann mir ehrlich gesagt nicht vorstellen, dass die 10.1
> Version nicht in der Lage wäre, den Code zu syntetisieren, so dass
> das richtige Ergebenis rauskommt.
Ich eigentlich auch nicht...
Sieh doch mal die Synthese-Eigenschaften durch, ob du damit was ändern 
kannst.

von Pat R. (patrik)


Lesenswert?

folgendes funktioniert:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity Linearizer is
7
  PORT(
8
      CLK : IN STD_LOGIC;
9
      RESET : IN STD_LOGIC;
10
      MEM_DONE : in STD_LOGIC;
11
      MEM_VALUE : in STD_LOGIC_VECTOR(4 downto 0);
12
      MEM_START : out STD_LOGIC;
13
      RESULT : OUT STD_LOGIC_VECTOR(7 downto 0)
14
  );  
15
16
end Linearizer;
17
18
architecture Behavioral of Linearizer is
19
20
signal MEM_VALUE_A, MEM_VALUE_B : STD_LOGIC_VECTOR(4 downto 0);
21
22
signal is_mem_value_a, is_mem_value_b : std_logic;
23
24
type main_fsm_type is (wait_for_start, start_mem_read1, mem_start1, wait_for_mem1, wait_for_mem2, wait_for_mem3);
25
signal main_fsm : main_fsm_type;
26
27
begin
28
  
29
  process(clk, reset)
30
  begin
31
    if reset = '1' then
32
      mem_start <= '0';
33
      main_fsm <= wait_for_start;
34
      result <= "00000000";
35
      is_mem_value_a <= '0';
36
      is_mem_value_b <= '0';
37
    elsif clk'event and clk = '1' then
38
      
39
40
      case main_fsm is
41
        when wait_for_start =>
42
          is_mem_value_a <= '0';
43
          is_mem_value_b <= '0';
44
          main_fsm <= start_mem_read1;
45
        when start_mem_read1  =>
46
          main_fsm <= mem_start1;          
47
          MEM_START <= '1';
48
        when mem_start1 =>
49
          MEM_START <= '0';
50
          main_fsm <= wait_for_mem1;
51
          is_mem_value_a <= '1';
52
        when wait_for_mem1 =>
53
          if is_mem_value_a = '1' and mem_done = '1' then
54
            MEM_VALUE_A <= MEM_VALUE;
55
            main_fsm <= wait_for_mem2;
56
            is_mem_value_b <= '1';
57
          end if;
58
        when wait_for_mem2 =>
59
          is_mem_value_a <= '0';
60
          if is_mem_value_b = '1' and mem_done = '1' then
61
            main_fsm <= wait_for_mem3;
62
            MEM_VALUE_B <= MEM_VALUE;            
63
          end if;
64
        when wait_for_mem3 =>
65
          is_mem_value_b <= '0';
66
          RESULT(4 downto 0) <= MEM_VALUE_A + MEM_VALUE_B;
67
          main_fsm <= wait_for_start;
68
      end case;
69
    end if;
70
  end process;
71
  
72
73
end Behavioral;

gefällt mir aber nicht wirklich :-\

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.