Forum: FPGA, VHDL & Co. Bei steigender und fallender Flanke unterschiedlich Schaltzeiten


von Jonas B. (holocron)


Lesenswert?

Hallo,
für eine Aufgabe sollen wir einen Inverter realisieren, der bei einer 
steigenden Flanke am Eingang mit einer Verzögerung von 7 ns schaltet und 
bei einer fallenden mit einer Verzögerung von 5 ns. Wir dürfen nur 
rising_edge verwenden (also nicht falling_edge). Zusätzlich soll ein 12 
Bit-Zähler implementiert sein. Den Zähler hab ich einfach in einem 
zweiten Prozess gepackt, nur bei den unterschiedlichen Flanken bin ich 
mir unsicher, ob das so stimmen kann:
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
4
entity myinverter is 
5
  port(inp: std_logic;
6
       outp: out std_logic;
7
       cnt: out std_logic_vector(11 downto 0);
8
end myinverter;
9
10
architecture behavior of myinverter is 
11
  signal value: std_logic_vector(11 downto 0);
12
  signal outp2: std_logic; 
13
begin
14
  inveter: process(inp) 
15
  begin
16
    if not rising_edge(inp) and inp = '0' then  -- falling edge
17
        outp2 <= not inp after 5 ns;
18
    elsif rising_edge(inp) then 
19
        outp2 <= not inp after 7 ns;
20
    end if;
21
22
  counter: process(inp)
23
  begin
24
    if value = "111111111111" then  -- overflow
25
          value = "000000000000";
26
    else 
27
          value <= std_logic_vector(unsigned(vaule) + 1);
28
    end if;
29
  end process;
30
end behavior
Gibt es für das Werte zuweisen einen geschickteren Weg als einfach die 
vielen 1en/0en zu tippen? Das wird doch sicher mit range gehen ?
Danke im Voraus.

Liebe Grüße

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

Jonas B. schrieb:
> für eine Aufgabe sollen wir einen Inverter realisieren, der bei einer
> steigenden Flanke am Eingang mit einer Verzögerung von 7 ns schaltet und
> bei einer fallenden mit einer Verzögerung von 5 ns.

Soll das synthetisiert werden? Dann wird es schwierig. Oder ist es nur 
für die Simu gedacht? Dann geht das mit den verzögerten Anweisungen.

Jonas B. schrieb:
> Wir dürfen nur
> rising_edge verwenden (also nicht falling_edge).

Toll. Eine Aufgabe des Stils: wenn ich dir die naheliegende und 
angemessene Lösung verbiete, auf welche Wurstelei kommst du dann?

Meine Lösung wäre wahrscheinlich:

if inp'event then
   if inp='0' then ....
   elsif inp='1' then ...
   end if;
end if;

(event war ja nicht explizit verboten, oder?)

Jonas B. schrieb:
> Gibt es für das Werte zuweisen einen geschickteren Weg als einfach die
> vielen 1en/0en zu tippen?

Da gibt es viele Wege. Da es gerade 12 Bit sind würde ich die Konstante 
in Hex angeben: x"FFF" bzw. x"000"
Auch mit (others => '1') oder (others => '0') dürfte was gehen.

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


Lesenswert?

Jonas B. schrieb:
> ob das so stimmen kann:
Was sagt deine Simulation?

> if not rising_edge(inp)
Das dürfte fast ständig "true" sein. Denn "keine" steigende Flanke gibts 
quasi dauernd. Sogar nie, wenn man davon ausgeht, dass eine Flanke die 
Zeit 0 hat. Wenn schon, dann würde ich für eine fallende Flanke das 
Signal invertieren und dann auf die steigende Flanke abfragen:
1
if rising_edge(not inp)

Aber die Verwendung der passenden Attribute ist sicher der bessere 
Weg:
https://www.csee.umbc.edu/portal/help/VHDL/attribute.html

> Gibt es für das Werte zuweisen einen geschickteren Weg als einfach die
> vielen 1en/0en zu tippen?
Nimm einen integer und du kannst simple leserliche Dezimalzahlen 
verwenden.

> Gibt es für das Werte zuweisen einen geschickteren Weg als einfach die
> vielen 1en/0en zu tippen?
Dein Zähler könnte den Überlauf auch ganz von allein. Du musst ihn nicht 
manuell zurücksetzen. Und warum nimmst du nicht wenigstens einen 
unsigned Vektor als Zähler?

> für eine Aufgabe sollen wir einen Inverter realisieren, der bei einer
> steigenden Flanke am Eingang mit einer Verzögerung von 7 ns schaltet und
> bei einer fallenden mit einer Verzögerung von 5 ns.
Es ist im Prinzip eine schlechte Idee, symbolische Verzögerungen in 
einem Code zu verwenden, der hinterher synthetisiert werden soll. Tu das 
am Besten nach dieser erzwungenen Übung nie wieder!
Siehe den Beitrag "Re: Einfaches Schieberegister in VHDL?"

: Bearbeitet durch Moderator
von Achim S. (Gast)


Lesenswert?

Ach ja, noch eine Ergänzung: da das mit den verzögerten Zuweisungen im 
Inverterprozess ja ohnehin nur in der Simu klappt, kann man 
wahrscheinlich auch ganz auf die Abfrage des events verzichten. In der 
Sensitivity-Liste steht nur inp, der Prozess wird also immer genau dann 
durchsimuliert, wenn bei inp ein event auftrat (also eine Signaländerung 
stattfand).

von Jonas B. (holocron)


Lesenswert?

Hi,
ja der Code ist für die Simulation, also nicht für eine Synthese 
gedacht.
Danke für die vielen Tipps!

Stimmt, finde die Aufgabe auch etwas dämlich ? Also explizit steht drin 
"Sie können hierfür die Funktion rising_edge() benutzen.". Dieses 
"können" klingt für mich fast wie eine Anweisung nur mit rising_edge() 
auszukommen.

Lothar M. schrieb:
> Was sagt deine Simulation?
Bei der hat sich nichts invertiert/das Signal blieb konstant. Allerdings 
hat edaplayground gestern ein wenig gestreikt.

Lothar M. schrieb:
> enn schon, dann würde ich für eine fallende Flanke das
> Signal invertieren und dann auf die steigende Flanke abfragen:if
> rising_edge(not inp)
Oh das ist aber eine geniale Idee! Ja ich denke das liegt dann genau im 
Sinne der Aufgabe, danke.
Wenn ich das aber implementiere (wie oben) kriege ich diese Meldung:
"COMP96 ERROR COMP96_0152: "Formal "s" of class signal must be 
associated with a signal." "design.vhd" 17 20"

von Achim S. (Gast)


Lesenswert?

Jonas B. schrieb:
> Wenn ich das aber implementiere (wie oben) kriege ich diese Meldung:
> "COMP96 ERROR COMP96_0152: "Formal "s" of class signal must be
> associated with a signal." "design.vhd" 17 20"

Na ja, der Code oben hat noch diverse Fehler (package numeric_std nicht 
eingebunden, falsche Zuweisungsoperatoren, vaule statt value, fehlendes 
end process...)

Aber dass du genau diese Fehlermeldung bekommst hätte ich bei dem Code 
nicht erwartet. Bist du sicher, dass du diese entity übersetzt hast? Wie 
sieht der tatsächliche Code denn inzwischen aus?

von Jonas B. (holocron)


Lesenswert?

Der Code sieht so aus:
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
5
entity myinverter is 
6
  port(inp: std_logic;
7
       outp: out std_logic;
8
       cnt: out std_logic_vector(11 downto 0));
9
end myinverter;
10
11
architecture behavior of myinverter is 
12
  signal value: std_logic_vector(11 downto 0) := "000000000000";
13
  signal outp2: std_logic := '0';
14
begin
15
  inveter: process(inp) 
16
  begin
17
    if rising_edge(not inp) then  -- falling edge
18
        outp2 <= not inp after 5 ns;
19
    elsif rising_edge(inp) then 
20
        outp2 <= not inp after 7 ns;
21
    end if;
22
  end process;
23
  outp <= outp2;
24
25
counter: process(inp)
26
  begin
27
    value <= std_logic_vector(unsigned(value) + 1);
28
  end process;
29
  cnt <= value;
30
end behavior;

von Achim S. (Gast)


Angehängte Dateien:

Lesenswert?

Tja: ich sehe nicht, wie die Fehlermeldung zu dieser entity passt. Ist 
diese Entity tatsächlich unter dem Namen design.vhd gespeichert? (denn 
der gemeldete Fehler liegt in design.vhd).

Zur eigentlichen Aufgabe: wie oben vermutet funktioniert es für die Simu 
ganz ohne Flankenabfrage (aufgrund der sensitivity-Liste) - siehe 
Anhänge...

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


Angehängte Dateien:

Lesenswert?

Jonas B. schrieb:
> if rising_edge(not inp) then  -- falling edge
rising_edge() kann mit der Funktion "not()" als Argument nichts 
anfangen. Du brauchst ein "Hilfssignal":
1
:
2
:
3
  signal notinp: std_logic;
4
begin
5
6
  notinp <= not inp;
7
8
  inveter: process(inp, notinp) 
9
  begin
10
    if rising_edge(notinp) then  -- falling edge
11
        outp <= not inp after 5 ns;
12
    end if;
13
    if rising_edge(inp) then 
14
        outp <= not inp after 7 ns;
15
    end if;
16
  end process;
17
:
18
:

Achim S. schrieb:
> Zur eigentlichen Aufgabe: wie oben vermutet funktioniert es für die Simu
> ganz ohne Flankenabfrage
Genau wie der Zähler nur in der Simulation tut...  ;-)
Im realen Leben ist die Sensitivliste des Zählers falsch. Oder es fehlt 
im Prozess eine Abfrage auf die Flanke. Deshalb zählt der auch mit jeder 
Taktflanke. Solche Flipflops gibts im realen Leben nicht...
Dazu das hier: 
http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife

: Bearbeitet durch Moderator
von Achim S. (Gast)


Lesenswert?

Lothar M. schrieb:
> Genau wie der Zähler nur in der Simulation tut...  ;-)

Genau das war ja die Aufgabenstellung:

Jonas B. schrieb:
> ja der Code ist für die Simulation, also nicht für eine Synthese
> gedacht.

von Jonas B. (holocron)


Lesenswert?

Hallo,
danke für die Hilfe. Nachdem ich das wie angegeben korrigiert hab passt 
alles.
Seltsamerweise komme ich mit genau diesem Code auf eine seltsame 
waveform (der Ausgang negiert einfach gar nicht). Wenn der Code im 
Programm aber funktioniert, liegt das vielleicht an der Webseite (das 
war die Webseite, die von der Vorlesung empfohlen wurde):

https://www.edaplayground.com/x/5eKJ

Lothar M. schrieb:
> Genau wie der Zähler nur in der Simulation tut...  ;-)
> Im realen Leben ist die Sensitivliste des Zählers falsch. Oder es fehlt
> im Prozess eine Abfrage auf die Flanke. Deshalb zählt der auch mit jeder
> Taktflanke. Solche Flipflops gibts im realen Leben nicht...
> Dazu das hier:
> http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife

Danke, ich schaus mir mal an.

Mit welchem Programm nehmt ihr denn eure Waveforms auf? Das scheint mir 
zuverlässiger als diese Seite zu sein.

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

Jonas B. schrieb:
> Mit welchem Programm nehmt ihr denn eure Waveforms auf? Das scheint mir
> zuverlässiger als diese Seite zu sein.

In meinem Fall: Xilinx ISE plus Multisim. Der Download und die 
Installation dauern zwar etwas, aber dafür kann man damit auch ernsthaft 
arbeiten.

In deiner Testbench fehlt imho die Komponentendeklaration. Füge die mal 
ein, vielleicht läuft es dann besser.

von Achim S. (Gast)


Lesenswert?

Ach ja: bei der Instantiierung von myinverter ist auch noch ein "entity" 
zu viel.

Und: bei verzögerten Anweisungen ist der Standard-Mode "inertial" (oder 
so ähnlich). Der Ausgangs schaltet dann nur, wenn der Eingang länger als 
die Verzögerungszeit stabil ist. Du muss umschalten auf transport oder 
dein simuliertes Eingangssignal länger als 7 ns stabil halten.

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


Lesenswert?

Jonas B. schrieb:
> Seltsamerweise komme ich mit genau diesem Code auf eine seltsame
> waveform (der Ausgang negiert einfach gar nicht).
Wenn du irgendwelche Signalflsnken um 5 oder 7ns verzögern willst, dann 
ist es sehr ungünstig, das Eingangssignal jede ns zu ändern.
Nimm mal den selben Takt wie Achim und ich...

: Bearbeitet durch Moderator
von S. R. (svenska)


Lesenswert?

Jonas B. schrieb:
> Also explizit steht drin "Sie können hierfür die Funktion
> rising_edge() benutzen.". Dieses "können" klingt für mich
> fast wie eine Anweisung nur mit rising_edge() auszukommen.

Ich lese das eher als eine Hilfestellung für die Klassendeppen, die 
keinen Ansatz haben. Sowas schreibt ein Lehrer meist hin, wenn er 
mehrfach leere Zettel bekommen hat. :D

Wäre es für die Synthese gewesen, dann wäre eine solche Anweisung ein 
Zaunpfahlwink gewesen, rising_edge mit einem Taktsignal zu benutzen, um 
das Timing zu garantieren. Aber hier ist ja alles asynchron.

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


Lesenswert?

S. R. schrieb:
> Jonas B. schrieb:
>> Also explizit steht drin "Sie können hierfür die Funktion
>> rising_edge() benutzen.". Dieses "können" klingt für mich
>> fast wie eine Anweisung nur mit rising_edge() auszukommen.
> Ich lese das eher als eine Hilfestellung für die Klassendeppen, die
> keinen Ansatz haben.
Man könnte das auch mal so lesen: "Sie können nachschauen, was die 
Funktion rising_edge() macht und darin eine Idee für die Lösung der 
Aufgabe finden."

Und dann wäre man mit 
https://www.csee.umbc.edu/portal/help/VHDL/packages/std_logic_1164.vhd 
schon mal gut bedient.

BTW: wenn man sich dort den Quelltext mal genauer anschaut, dann ist 
klar, warum das 's' in der zuvor geposteten Fehlermeldung auftaucht:
1
    -------------------------------------------------------------------    
2
    -- edge detection
3
    -------------------------------------------------------------------    
4
    --synopsys synthesis_off
5
    FUNCTION rising_edge  (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
6
    -- pragma subpgm_id 231
7
    BEGIN
8
        RETURN (s'EVENT AND (To_X01(s) = '1') AND 
9
                            (To_X01(s'LAST_VALUE) = '0'));
10
    END;
11
12
    FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
13
    -- pragma subpgm_id 232
14
    BEGIN
15
        RETURN (s'EVENT AND (To_X01(s) = '0') AND 
16
                            (To_X01(s'LAST_VALUE) = '1'));
17
    END;

: Bearbeitet durch Moderator
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.