Forum: FPGA, VHDL & Co. Umschalten zwischen rising und falling edge


von Andi P. (jamaram90)


Lesenswert?

Hallo,

folgenden Code habe ich mir überlegt:
1
process(Rx_buffer, Stop, reset)
2
3
variable s : std_logic_vector(n-1 downto 0);
4
5
begin
6
7
if reset = '1' then
8
9
 s := (others=> '0');
10
 
11
 elsif Rx_buffer(1) = '1' then
12
 
13
  if rising_edge(Stop) then
14
  
15
    s := q;
16
    signal_out_stop <= s;
17
    
18
  end if;
19
  
20
elsif Rx_buffer(1) = '0' then
21
22
  if falling_edge(Stop) then
23
  
24
    s := q;
25
    signal_out_stop <= s;
26
  end if;
27
  
28
end if;
29
30
end process;

Ich möchte quasi das es entscheidet, je nachdem was in Rx_buffer an der 
1. Bitstelle steht, ob 1 oder 0, es auf fallende oder steigende Flanke 
triggert.

Wenn ich den Code synthetisiere bekomme ich die Warnung:

Xst:3002 - This design contains one or more registers/latches that are 
directly incompatible with the Spartan6 architecture. The two primary 
causes of this is either a register or latch described with both an 
asynchronous set and asynchronous reset, or a register or latch 
described with an asynchronous set or reset which however has an 
initialization value of the opposite polarity (i.e. asynchronous reset 
with an initialization value of 1).


Kann mir jemand sagen wie ich das besser lösen kann damit es klappt. Ich 
hänge da jetzt schon eine Weile dran und verzweifle langsam. :-/

von Alexander F. (alexf91)


Lesenswert?

Lösung: Löschen und neu anfangen.

Latches sind hier dein kleinstes Problem.
Nur mal als Beispiel: signal_out_stop ist ein Flipflop, das abwechselnd 
auf die fallende oder steigende Flanke des Taktes reagieren soll.

Ich gehe davon aus, dass Stop nicht wirklich ein Takt ist, sondern ein 
normales Signal, das du irgendwo erzeugst (oder gar ein Taster...).
So ein Signal verwendet man nicht als Takt, aber das ist genau das, was 
rising_edge() macht.
Was du mit der Variable vorhast, verstehe ich auch nicht, die erfüllt 
hier keinen Zweck, da der im Reset gesetzte Wert nie verwendet wird. 
Wenn du was speichern musst, dann verwende Signale.

Der bessere Weg ist, Stop mit einem richtigen Takt, der bestimmt auf 
deinem Board vorhanden ist, zu sampeln und je nachdem, welchen Wert 
Rx_Buffer(0) hat, eine Aktion bei einer steigenden oder fallenden Flanke 
auszulösen (nicht mit rising/falling_edge überprüfen).

Falls du kein VHDL Buch hast, dann kauf dir eins und arbeite das durch, 
hier fehlen Grundlagen.
VDHL-Synthese von Reichardt/Schwarz wird dir weiterhelfen.

: Bearbeitet durch User
von Andi P. (jamaram90)


Lesenswert?

Die Variable s speichert den Wert eines Zählers zu dem das Signal Stop 
auftritt. Daher eben die Entscheidung ob steigende oder fallende Flanke.

von Alexander F. (alexf91)


Lesenswert?

Alex P. schrieb:
> Die Variable s speichert den Wert eines Zählers zu dem das Signal Stop
> auftritt.

Das ist mir schon klar. Du verwendest diesen gespeicherten Wert aber 
immer nur direkt nach der Zuweisung.
1
signal_out_stop <= q;
reicht da auch.

Poste mal den gesamten Code, da liegt wohl noch einiges im Argen.

von Andi P. (jamaram90)


Lesenswert?

Hier mal der gesamte Code. Es sollte dann noch ein weiterer Prozess 
hinzukommen der auf ein zweites Signal achtet und im Prinzip da auch 
wieder nach Einstellung über Rx_buffer(0) dann ob auf steigende oder 
fallende Flanke getriggert werden soll.
1
entity test is 
2
    
3
generic(n : integer := 16);       
4
  
5
 Port ( 
6
        
7
  clk     : in  STD_LOGIC;
8
  reset     : in std_logic;
9
  ce_i     : in   std_logic;
10
  Rx_buffer          : in std_logic_vector(1 downto 0);    
11
  Stop     : in std_logic;
12
         
13
14
         signal_out_stop : out std_logic_vector(n-1 downto 0); 
15
  ce_o  : out std_logic;
16
         Cout   : out std_logic_vector(n-1 downto 0)
17
        
18
       );
19
    
20
end test;
21
22
23
architecture Behavioral of test is
24
25
signal q : std_logic_vector(n-1 downto 0);
26
27
28
begin
29
30
P1: process(clk, ce_i, reset)
31
32
variable x : std_logic;
33
34
begin
35
36
if reset = '1' then
37
38
  q <= (others => '0');
39
  x := '0';
40
  
41
  
42
elsif ( clk'event and clk = '1' and ce_i = '1') then
43
44
  q <=  q + 1;
45
  x := '1';
46
  
47
end if;
48
49
ce_o <= x;
50
51
end process;
52
53
Cout <= q;
54
55
56
P2: process(Rx_buffer, Stop, reset)
57
58
variable s : std_logic_vector(n-1 downto 0);
59
60
begin
61
62
if reset = '1' then
63
64
 s := (others=> '0');
65
 
66
 elsif Rx_buffer(1) = '1' then
67
 
68
  if rising_edge(Stop) then
69
  
70
    s := q;
71
    signal_out_stop <= s;
72
    
73
  end if;
74
  
75
elsif Rx_buffer(1) = '0' then
76
77
  if falling_edge(Stop) then
78
  
79
    s := q;
80
    signal_out_stop <= s;
81
  end if;
82
  
83
end if;
84
85
end process;
86
87
end Behavioral;

von Forscher (Gast)


Lesenswert?

für die Erkennung eines '0' zu '1' wechsel nimmt man kein rising_edge(),

rising_edge und falling_edge sind nur für die Beschreibung von 
flankengesteuerten (engl. edge triggered) FlipFlops zulässig.


Was du suchst ist keine Flanken Erkennung (edge-trigger) sondern eine 
Zustandswechselerkennung oder Übergangserkennung ("state-change" 
"Transition-detection").


Um einen '0'  auf '1'Signalwechsel zu erkennen schickst du das Signal 
durch ein D-FF

und vergleichst ob das Signal am D-Eingang '1' ist während das Signal am 
Q-Ausgang '0' ist.

Gruß

von Alexander F. (alexf91)


Lesenswert?

Eliminiere alle Variablen, die benötigst du nicht.
Außerdem solltest du ieee.numeric_std.all verwenden und nicht die 
Synopsys Bibliotheken (du hast q als std_logic_vector deklariert).
1
p1: process(clk, reset)
2
begin
3
    if reset = '1' then
4
        q <= (others => '0');
5
        ce_o <= '0';
6
    elsif rising_edge(clk) then
7
        if ce_i = '1' then
8
            q <= q + 1;
9
            ce_o <= '1';
10
        end if;
11
    end if;
12
end process;

Im 2. Prozess kannst du das genau so machen.

Zur Flankenerkennung im 2. Prozess:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung

Wieder die Frage: Hast du ein Buch oder sonstige Unterlagen?

: Bearbeitet durch User
von Forscher (Gast)


Lesenswert?

Auch wenn in den Büchern asynchroner Resete gelehrt wird, sollte man ihn 
tunlichst vermeiden:
1
p1: process(clk)
2
begin
3
    if rising_edge(clk) then
4
      if reset = '1' then
5
        q <= (others => '0');
6
        ce_o <= '0';
7
       else
8
         if ce_i = '1' then
9
         --Überlaufbehandlung fehlt
10
            q    <= q + 1;
11
            ce_o <= '1';
12
         end if;
13
        end if;
14
     end if;
15
end process pl;

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


Lesenswert?

Forscher schrieb:
> Auch wenn in den Büchern asynchroner Resete gelehrt wird, sollte man ihn
> tunlichst vermeiden
Bei Lattice und Altera darf man durchaus einen asynchronen Reset 
beschreiben. Allerdings darf da dann nicht einfach ein asynchroner 
Resettaster drauf gelegt werden, sondern der Resettaster muss wie jedes 
andere asynchrone Signal auch einsynchronisiert werden. Denn sonst kann 
gleich der Start des Design schiefgehen, weil nicht alle Flipflops 
gleichzeitig aus dem Reset kommen. Und dann sind wir wieder da:
http://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html


Alex P. schrieb:
> Hier mal der gesamte Code.
Meine VHDL Beschreibungen fangen mit den verwendeten Packages an...

: Bearbeitet durch Moderator
von Andi P. (jamaram90)


Lesenswert?

Alexander F. schrieb:
> Wieder die Frage: Hast du ein Buch oder sonstige Unterlagen?

Ja ich besitze zahlreiche Vorlesungsunterlagen und auch das von dir 
schon angesprochene Buch. Ich werde mich da noch etwas weiter belesen.

Trotzdem vielen Dank für die Auskünfte und Antworten. Hilft mir schon 
sehr weiter.

Gruß

Alex

von Christoph Z. (christophz)


Lesenswert?

Alex P. schrieb:
> Es sollte dann noch ein weiterer Prozess
> hinzukommen der auf ein zweites Signal achtet und im Prinzip da auch
> wieder nach Einstellung über Rx_buffer(0) dann ob auf steigende oder
> fallende Flanke getriggert werden soll.

Dann lohnt es sich jetzt schon, die Funktionalität für das eine Signal 
in einen separaten Funktionsblock zu packen (Sobald es läuft und 
getestet ist).

Dann kannst du danach in deinem Top Modul einfach für jedes zu 
überwachende Signal einfach einen Funktionsblock instantieren. Ohne den 
selben Code zweimal zu schreiben.

Ist auch eine gute Übung, das mal an etwas kleinerem auszuprobieren. Im 
erwähnten Buch kannst du das auch nachlesen unter "Struktureller VHDL 
Entwurf".

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.