Forum: FPGA, VHDL & Co. Counterwert speichern bevor Reset


von Fellap (Gast)


Lesenswert?

Hallo,

ich habe einen Counter und Eingangssignal. Wenn das Eingangssignal high 
ist, soll der Counterwert zu diesem Zeitpunkt gespeichert werden und der 
Counter auf null zurückgesetzt werden.

Weiß aber nicht so recht genau, wie ich das bewerkstelligen kann.

Hier mein Versuch:
1
  
2
  process (clk, reset_internal,flanke,cntMSEC)
3
  variable save_cntMSEC: integer := 0;
4
  begin  -- process
5
    if clk'event and clk = '1' then  -- rising clock edge
6
    if prescaler<49 then
7
       prescaler <= prescaler + 1;
8
      else
9
         prescaler <= 0;
10
       if cntMSEC = 50 then
11
         cntMSEC <= 0;
12
       else 
13
          cntMSEC <= cntMSEC + 1;          --1 us
14
        end if;
15
      end if;
16
    end if;
17
    if reset_internal = '1' then
18
    prescaler <= 0;
19
    cntMSEC <= 0;
20
    end if;
21
    if flanke = '1' then
22
     save_cntMSEC := cntMSEC;
23
    save_cnt2 <= save_cntMSEC;
24
    prescaler <= 0;
25
    cntMSEC <= 0;
26
    end if;
27
  end process;

Die Idee war, den wert vor dem Reset in eine Variable zu speichern, da 
Variablen ja den Wert sofort annehmen. Um global auf diesen Wert 
zugreifen zu koennen, habe ich die Variable in ein Signal gespeichert 
und dann erst das ganze resetet...

Synthetisieren laesst es sich... aber die Simulation zeigt, es 
funktioniert nicht... schaetze aufgrund der Fehlermeldungen:
1
WARNING:Xst:2677 - Node <save_cnt2_0> of sequential type is unconnected in block <timer>.
2
WARNING:Xst:2677 - Node <save_cnt2_1> of sequential type is unconnected in block <timer>.
3
WARNING:Xst:2677 - Node <save_cnt2_2> of sequential type is unconnected in block <timer>.
4
WARNING:Xst:2677 - Node <save_cnt2_3> of sequential type is unconnected in block <timer>.
5
WARNING:Xst:2677 - Node <save_cnt2_4> of sequential type is unconnected in block <timer>.
6
WARNING:Xst:2677 - Node <save_cnt2_5> of sequential type is unconnected in block <timer>.

Wieso erhalte ich diese Fehlermeldungen?
Und wenn das mit der Variablen keine gute Idee ist, da man sie als 
Anfaenger meiden soll... Bin ich gerne offen fuer andere Ideen..

Vielen Dank im voraus..

von dden (Gast)


Lesenswert?

Hallo,
zuerst solltest du mit save_cnt2 auch noch was machen.
Möchtest du wirklich einen asynchronen kombinatorischen reset?
Wenn überhaupt mach deinen reset_internal asynchron und deine 
Flanke(welche höchstwahrscheinlich synchron kommt) synchron.
Und eigentlich sollte auch "save_cnt2 <= cntMSEC;" im synchronen Reset 
langen.
Wie sieht den deine simulation aus?

von Fellap (Gast)


Lesenswert?

dden schrieb:
> Hallo,
> zuerst solltest du mit save_cnt2 auch noch was machen.


Was meinst du, ich sollte mit save_cnt2 auch noch etwas machen?
Also ich habe spaeter save_cnt2 verwendet um davon einen konstanten wert 
abzziehen. Dieser konstante wert 't' ist groesser als der wert in 
save_cnt2 - somit wird der Wert negativ. Dann moechte ich diesen 
negativen Wert mit einer anderen konstanten multiplizieren...

dden schrieb:
> Möchtest du wirklich einen asynchronen kombinatorischen reset?
> Wenn überhaupt mach deinen reset_internal asynchron und deine
> Flanke(welche höchstwahrscheinlich synchron kommt) synchron.
Ist das nun so besser? (siehe code)
1
  -- Frequenzteiler 1msec
2
  process (clk, reset_internal,flanke,cntMSEC)
3
  variable save_cntMSEC: integer := 0;
4
  begin  -- process
5
    if clk'event and clk = '1' then  -- rising clock edge
6
    if prescaler<49 then
7
       prescaler <= prescaler + 1;
8
      else
9
         prescaler <= 0;
10
       if cntMSEC = 50 then
11
         cntMSEC <= 0;
12
       else 
13
          cntMSEC <= cntMSEC + 1;          --1 us
14
        end if;
15
      end if;
16
    if flanke = '1' then
17
     save_cntMSEC := cntMSEC;
18
    save_cnt2 <= save_cntMSEC;
19
    prescaler <= 0;
20
    cntMSEC <= 0;
21
    end if;  
22
    end if;
23
    if reset_internal = '1' then
24
    prescaler <= 0;
25
    cntMSEC <= 0;
26
    end if;
27
28
  end process;
29
30
31
32
  process (inp,clk) --Lothar Miller
33
  begin
34
   if rising_edge(clk) then
35
      -- Schieberegister
36
      sr <= sr(6 downto 0) & inp;
37
      -- Flankenerkennung, 1 Sync-FF, dann sofort reagieren
38
      flanke <= '0';
39
      if (sr="11111110") then flanke <= '1'; end if; -- fallend
40
      if (sr="00000001") then flanke <= '1'; end if; -- steigend
41
      -- Entprellen
42
      if (sr="11111111") then pegel <= '1'; end if; -- high
43
      if (sr="00000000") then pegel <= '0'; end if; -- low
44
    if (flanke = '1') then 
45
        
46
        calc_d <= save_cnt2 - t; --t = constanter wert
47
        d <= d + calc_d;     
48
    end if;    
49
   end if;
50
  end process;

dden schrieb:
> Wie sieht den deine simulation aus?

Simulation sieht wie Hardware aus... Die ganze Zeit save_cnt2 = 0

von pks (Gast)


Lesenswert?

Irgendwie krieg ich ne Gänsehaut, wenn ich Deinen code betrachte :-)
Mach einfach einen rein getakteten Prozess(nur clk in der SL), definier 
save_cntMSEC als Signal und wenn dein Rücksetzt-Signal kommt, setzt Du 
halt den Zählerzurück und weist den aktuellen Wert save_cntMSEC zu. Wozu 
brauchst Du da eine Variable?

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


Lesenswert?

Fellap schrieb:
> process (clk, reset_internal,flanke,cntMSEC)
Wo lernst mann den diese seltsame zusammengepackte Kombination von 
getaktetem und kombinatorischem Prozess? Und vor allem: der Code ist so 
eigenartig formatiert, dass man dieses Gebastel erst beim zweiten Blick 
erkennt.
> Ist das nun so besser? (siehe code)
Nein. In einen getakteten Prozess kommt vor oder hinter dem Takt keine 
kombinatorische Beschreibung! Niemals!

> process (inp,clk) --Lothar Miller
Nein, das stimmt nicht. Ich hätte in die Sensitivliste nicht das 
unnötige Signal inp aufgenommen...

Fellap schrieb:
> ich habe einen Counter und Eingangssignal. Wenn das Eingangssignal high
> ist, soll der Counterwert zu diesem Zeitpunkt gespeichert werden und der
> Counter auf null zurückgesetzt werden.
Dann wird in deinem gespeicherten Counterwert immer 0 stehen.
Warum: weil im ersten Augenblick der Counter gespeichert wird, dann wird 
der Counter zurückgesetzt und dann gleich der zurückgesetzte Wert wieder 
gespeichert...

> ich habe einen Counter und Eingangssignal. Wenn das Eingangssignal high
> ist, soll der Counterwert zu diesem Zeitpunkt gespeichert werden und der
> Counter auf null zurückgesetzt werden.
Ich würde das so machen:
1
process begin
2
   wait until rising_edge(clk);
3
   if ms_presc < 49 then       -- us erzeugen aus 50MHz
4
      ms_presc <= ms_presc+1;
5
   else
6
      ms_presc <= 0;
7
      cnt <= cnt+1;            -- us zählen
8
   end if;
9
10
   sr <= sr(1 downto 0) & inp; -- Einsynchronisieren mit Schieberegister
11
12
   if (sr="001") then          -- steigende Flanke
13
      save_cnt <= cnt;         -- Wert speichern
14
      cnt      <= 0;           -- und Zähler zurücksetzen
15
   end if;    
16
end process;

: Bearbeitet durch Moderator
von Fellap (Gast)


Lesenswert?

Lothar Miller schrieb:
1
if (sr="001") then          -- steigende Flanke
2
       save_cnt <= cnt;         -- Wert speichern
3
       cnt      <= 0;           -- und Zähler zurücksetzen
4
    end if;
 end process;

Ah achso.. also wird hier nun nur zu dem Zeitpunkt wenn sr = "001" ist 
gespeichert? und im naechsten takt, trifft die Bedingung aufgrund sr = 
"010" nicht mehr zu und wird deswegen nicht mehr ueberschrieben?!

Ich habe da noch meine Probleme mit der sensitive-Liste... Was kommt 
denn nun alles in die sensitvelist? - dachte immer, alles, auf das der 
Process reagieren soll... quasi "angestupst" werden soll..?!

Wenn ich nun noch Berechnungen durchfuehren moechte... kann ich dass 
dann auch noch in den selben Process mitreinschreiben? Oder lieber einen 
neuen Process? bzw Wann einen neuen Process anfangen? Ihr und ich merkt 
schon... Hier fehlt es vorne und hinten an Grundlagen :-/

Ein anderes Problem hat sich eben auch noch ergeben...
Wenn ich nun eine Berechnung durchfuehren moechte (siehe Code)...
1
process begin
2
   wait until rising_edge(clk);
3
   if ms_presc < 49 then       -- us erzeugen aus 50MHz
4
      ms_presc <= ms_presc+1;
5
   else
6
      ms_presc <= 0;
7
      cnt <= cnt+1;            -- us zählen
8
   end if;
9
10
   sr <= sr(1 downto 0) & inp; -- Einsynchronisieren mit Schieberegister
11
12
   if (sr="001") then          -- steigende Flanke
13
      save_cnt <= cnt;         -- Wert speichern
14
      cnt      <= 0;           -- und Zähler zurücksetzen
15
      calc_d <= save_cnt - t; --t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
16
      d <= d + (calc_distance * a); --a = 500
17
   end if;    
18
end process;

d wird hier in Mikrometer berechnet.. aber d wird bis in den 
Meterbereich reichen... So wird d riesen gross. Angezeigt werden soll 
aber nur Meter und Zentimeter auf 7Segementanzeigen mittels Lothars 
Millers Vector -> BCD Converter

Nun war mein erster Gedanke, einfach durch 10000000 teilen..

Jedoch laesst sich das nicht synthetisieren... und von divisionen 
generell wird bei VHDL sowieso meistens abgeraten...

Jemand eine Idee?

von Uwe (Gast)


Lesenswert?

> BCD Converter
Dann halt nur die oberen 4x4=16 Bits des Wertes mit dem BCD zu 
7-Segmentkonverter verbinden.

von Uwe (Gast)


Lesenswert?

Aber ich glaube du hast noch nicht verstanden, daß du in VHDL nicht 
programmierst sondern Bauteile "erschaffst" und sie danach mit signalen 
miteinander verdrahtest. Dort passiert immer alles gleichzeitig (wie in 
einer Elektronischen Schaltung halt). Dinge die nacheinander passieren 
sollen werden mit verschalteten RS-FlipFlops gemacht (Counter und 
Schieberegister zusammen mit kombinatorischer logik -> Statemachines).

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


Lesenswert?

Fellap schrieb:
> Ich habe da noch meine Probleme mit der sensitive-Liste... Was kommt
> denn nun alles in die sensitvelist? -
Alles, was zur Neuberechnung eines Prozesses für die Simulation 
wichtig ist. Die Synthese schert sich einen feuchten Kehrricht um die 
Sensitivliste...

> Angezeigt werden soll aber nur Meter und Zentimeter auf
> 7Segementanzeigen mittels Lothars Millers Vector -> BCD Converter
Ja, ist doch kein Problem: wandle alle Stellen des Vektors und gib nur 
die interessanten aus..

> und von divisionen generell wird bei VHDL sowieso meistens abgeraten...
Warum wohl? Wie ist ein Hardware-Divider aufgebaut?

> d wird hier in Mikrometer berechnet..
Warum? Ist doch unnötig, und zudem ist der kleinste Schritt 500um. Warum 
rechnest du dann nicht in mm oder in halben mm?

> Ah achso.. also wird hier nun nur zu dem Zeitpunkt wenn sr = "001" ist
> gespeichert? und im naechsten takt, trifft die Bedingung aufgrund sr =
> "010" nicht mehr zu und wird deswegen nicht mehr ueberschrieben?!
Oder auch wegen "011", das kommt darauf an, wie lange der inp high ist. 
Sieh dir einfach mal die Simulation an...

von Fellap (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Angezeigt werden soll aber nur Meter und Zentimeter auf
>> 7Segementanzeigen mittels Lothars Millers Vector -> BCD Converter
> Ja, ist doch kein Problem: wandle alle Stellen des Vektors und gib nur
> die interessanten aus..

Ja aber dein Vector2BCD hat "nur" einen Input von 16 Bit, jedoch ist d 
20 Bit lang. So kann ich doch nicht alle verarbeiten lassen!???

Lothar Miller schrieb:
>> d wird hier in Mikrometer berechnet..
> Warum? Ist doch unnötig, und zudem ist der kleinste Schritt 500um. Warum
> rechnest du dann nicht in mm oder in halben mm?

Weil ich nicht weiss wie.. am liebsten wuerde ich ja nur in cm rechnen 
aber ich habe irgendwie voll die Blockade :-/

Lothar Miller schrieb:
>> und von divisionen generell wird bei VHDL sowieso meistens abgeraten...
> Warum wohl? Wie ist ein Hardware-Divider aufgebaut?

Ohja.. okay jetzt sehe ich es auch....

von Fellap (Gast)


Lesenswert?

Lothar Miller schrieb:
>> d wird hier in Mikrometer berechnet..
> Warum? Ist doch unnötig, und zudem ist der kleinste Schritt 500um. Warum
> rechnest du dann nicht in mm oder in halben mm?

richtig... der kleinste Schritt ist 500um... Stimmt auch mit der 
Simulation ueberein...

Aber ich steh so auf dem Schlauch... Ich habe 4 7 Segmentanzeigen... Wie 
kann ich denn nun designen, dass der Vector2BCD mir 10er und 1er Meter 
und 10er und 1er cm ausgibt... Also klar ist, dass der Vektor2BCD 5 
Digits bereit stellt... und ich die oberen 4 anzeigen lassen muss.. aber 
wenn ich momentan den vektor d dem Vector2BCD uebergebe (siehe Code) 
kommen natuerlich nur im Mikrometerbereich die zahlen raus....
1
vector_sig(15 downto 0) <= conv_std_logic_vector(d,16); --Uebergabe von d an Vector2BCD (d: integer)



Fellap schrieb:
> Lothar Miller schrieb:
>>> Angezeigt werden soll aber nur Meter und Zentimeter auf
>>> 7Segementanzeigen mittels Lothars Millers Vector -> BCD Converter
>> Ja, ist doch kein Problem: wandle alle Stellen des Vektors und gib nur
>> die interessanten aus..
>
> Ja aber dein Vector2BCD hat "nur" einen Input von 16 Bit, jedoch ist d
> 20 Bit lang. So kann ich doch nicht alle verarbeiten lassen!???

Sorry das war Schmarn was ich schrieb.. mein d vektor wird noch viel 
laenger... ist ja auch klar.. wenn die Entfernung steigt, benoetigt der 
Vektor mehr Bits... und wenn es bis in den Meterbereich hineinragt und 
der Vektor in Mikrometer dargestellt wird, ist ja klar, das der d-vektor 
so ultra lang wird... Aber wie kann ich das verhindern? - Wenn ich nicht 
Dividieren kann / soll???

Aber soweit erstmal vielen vielen Dank fuer eure Muehe! :)

von Fellap (Gast)


Lesenswert?

Fellap schrieb:
> Sorry das war Schmarn was ich schrieb.. mein d vektor wird noch viel
> laenger... ist ja auch klar.. wenn die Entfernung steigt, benoetigt der
> Vektor mehr Bits... und wenn es bis in den Meterbereich hineinragt und
> der Vektor in Mikrometer dargestellt wird, ist ja klar, das der d-vektor
> so ultra lang wird... Aber wie kann ich das verhindern? - Wenn ich nicht
> Dividieren kann / soll???

Sorry... war wohl noch zu verschlafen... Habe es nun...

1
signal vector_sig: std_logic_vector (15 downto 0) := (others => '0');
2
signal digit1: std_logic_vector (3 downto 0) := (others => '0');
3
signal digit2: std_logic_vector (3 downto 0) := (others => '0');
4
signal digit3: std_logic_vector (3 downto 0) := (others => '0');
5
signal digit4: std_logic_vector (3 downto 0) := (others => '0');
6
signal sig_bcd: std_logic_vector (19 downto 0);
7
8
--Vector 2 BCD
9
      
10
vector_sig(15 downto 0) <= conv_std_logic_vector(d,16); 
11
12
digit1 <= sig_bcd(7 downto 4);    --1. Zahl anzeigen lassen
13
digit2 <= sig_bcd(11 downto 8);    --2. Zahl anzeigen lassen
14
digit3 <= sig_bcd(15 downto 12);  --3. Zahl anzeigen lassen
15
digit4 <= sig_bcd(19 downto 16);  --4. Zahl anzeigen lassen

Bloss haben sich noch ein paar Probleme herausgestellt.... und zwar 
zaehlt der counter nur bis 62375380, als waere er nur 25 Bit breit.. 
Aber integer hat doch 32 Bit oder?
Sowohl in der Simulation, als auch auf der Hardware besteht dieser 
Fehler...

Hat jemand eine Idee?

von Fellap (Gast)


Lesenswert?

Oh.. signal d noch vergessen...
1
 signal d: integer := 0;

von Fellap (Gast)


Lesenswert?

mensch... so hier nochmal der code.. diesmal richtig...
1
signal d: integer := 0;
2
signal vector_sig: std_logic_vector (15 downto 0) := (others => '0');
3
signal digit1: std_logic_vector (3 downto 0) := (others => '0');
4
signal digit2: std_logic_vector (3 downto 0) := (others => '0');
5
signal digit3: std_logic_vector (3 downto 0) := (others => '0');
6
signal digit4: std_logic_vector (3 downto 0) := (others => '0');
7
signal sig_bcd: std_logic_vector (19 downto 0);
8
signal logicVectorD: std_logic_vector (31 downto 0) := (others => '0');
9
10
--Vector 2 BCD
11
logicVectorD <= conv_std_logic_vector(d,32);
12
vector_sig(15 downto 0) <= logicVectorD(31 downto 16);  
13
14
digit1 <= sig_bcd(7 downto 4);    --1. Zahl anzeigen lassen
15
digit2 <= sig_bcd(11 downto 8);    --2. Zahl anzeigen lassen
16
digit3 <= sig_bcd(15 downto 12);  --3. Zahl anzeigen lassen
17
digit4 <= sig_bcd(19 downto 16);  --4. Zahl anzeigen lassen




Was mir auch noch aufgefallen ist... wenn die zeit save_cnt kleiner ist, 
als t.. muesste ja d eigentlich kleiner werden... wird es aber nicht.. 
es steigt einfach weiter an...
1
signal ms_presc: integer range 0 to 49 := 0; --Counter for get 1 usec
2
signal cnt:  integer range 0 to 50 := 0; --Counter for 1 msec
3
signal sr     : std_logic_vector(2 downto 0);
4
signal save_cnt: integer := 0;
5
signal calc_d: integer := 0;
6
signal d: integer := 0;
7
signal t : integer range 19 to 20 := 20; --minimal d = 20 mikrometer
8
9
process begin
10
   wait until rising_edge(clk);
11
   if ms_presc < 49 then       -- us erzeugen aus 50MHz
12
      ms_presc <= ms_presc+1;
13
   else
14
      ms_presc <= 0;
15
      cnt <= cnt+1;            -- us zählen
16
   end if;
17
18
   sr <= sr(1 downto 0) & inp; -- Einsynchronisieren mit Schieberegister
19
20
   if (sr="001") then          -- steigende Flanke
21
      save_cnt <= cnt;         -- Wert speichern
22
      cnt      <= 0;           -- und Zähler zurücksetzen
23
      calc_d <= save_cnt - t; --t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
24
      d <= d + (calc_distance * a); --a = 500
25
   end if;    
26
end process;

Also Problem:
d zaehlt nicht bis 32 bit hoch...
d wird in der hardware nicht runtergezaehlt, wenn t groesser als 
save_cnt ist

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


Lesenswert?

Fellap schrieb:
> signal d: integer := 0;
> d zaehlt nicht bis 32 bit hoch...
Sondern wie weit?
Wie war das nochmal mit dem Vorzeichen bei einem integer?

> d wird in der hardware nicht runtergezaehlt, wenn t groesser als
> save_cnt ist
1
      calc_d <= save_cnt - t; --t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
2
      d <= d + (calc_distance * a); --a = 500
Ja, warum denn auch? Das eine hat mit dem Anderen ja nichts zu tun...

> d wird in der hardware nicht runtergezaehlt
Wie sieht es in der Simulation aus?

Nochmal: du brauchst auch gar keine 32 Bit, wenn du den Faktor 500 
endlich mal weglässt! Dadurch machst du dir 9 Bits "kaputt" und dem 
Optimizer unnötig Arbeit. Denk einfach mal da drüber nach, und dann 
reicht dir ein Integer auf einmal locker und luftig ganz ohne das 32. 
Bit und Überlauf und Vorzeichen undsonstwasauchimmernoch....

von Fellap (Gast)


Lesenswert?

Lothar Miller schrieb:
> Fellap schrieb:
>> signal d: integer := 0;
>> d zaehlt nicht bis 32 bit hoch...
> Sondern wie weit?
> Wie war das nochmal mit dem Vorzeichen bei einem integer?

In der Simulation zaehlt es nur bis integer 62375380 (bzw. 26 Bit) 
hoch...
In der Hardware zaehlt es bis integer 6553xxxx (bzw. 26 Bit) hoch. 
(xxxx, da ich in der Hardware nicht die letzten Stellen sehen kann 
aufgrund nur der 4x 7Segementanzeigen)...
Also waere ja massig Bits uebrig fuer das Vorzeichenbit...


Lothar Miller schrieb:
>> d wird in der hardware nicht runtergezaehlt, wenn t groesser als
>> save_cnt ist      calc_d <= save_cnt - t; --t = constanter wert (fast gleich
> gross wie save_cnt --> ergebnis kleine zahl)
>       d <= d + (calc_distance * a); --a = 500
> Ja, warum denn auch? Das eine hat mit dem Anderen ja nichts zu tun...

Sorry.. sehe gerade, habe mich hier, vertippt.. aber in meinem Code 
stimmts... muss heißen:
1
calc_d <= save_cnt - t; --t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
2
d <= d + (calc_d * a); --a = 500


Lothar Miller schrieb:
>> d wird in der hardware nicht runtergezaehlt
> Wie sieht es in der Simulation aus?

In der Simulation funktioniert das einwandfrei. - wenn t groeßer als 
save_cnt, wird "d" kleiner... Bloß in der Hardware funktioniert das 
nicht... Komme da kein stueck voran...

Lothar Miller schrieb:
> Nochmal: du brauchst auch gar keine 32 Bit, wenn du den Faktor 500
> endlich mal weglässt! Dadurch machst du dir 9 Bits "kaputt" und dem
> Optimizer unnötig Arbeit.

Du meinst, das ich den Faktor 100 weglasse und einfach nur mit 5 
multipliziere oder? Dann spare ich mir so immerhin 6 Bit... Oder 
verstehe ich da gerade etwas falsch?

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.