Forum: FPGA, VHDL & Co. Flankengesteuertes RS-FF in VHDL


von Benedikt (Gast)


Lesenswert?

Ich versuche schon seit ein paar Stunden flankengesteuert ein FF zu
setzen und zurückzusetzen:
Kommt eine High-Low Flanke von Signal A, soll dass FF gesetzt werden,
kommt eine Low-High Flanke von Signal B, soll es zurückgesetzt werden.

Aber leider komme ich mit der Triggerung auf die beiden Flanken nicht
weiter...

von Kest (Gast)


Lesenswert?

if a'event and a='1' then
  q <='1';
elsif b'event and b='0' then
  q <='0';
end if;

? Ist das das, was Du suchst?

Kest

von Benedikt (Gast)


Lesenswert?

Ja, so habe ich es auch:

 if ale='0' and ale'event then
  ras <= '1';
 elsif En='1'  and En'event then
  ras <= '0';
 end if;

Allerdings kommt dann ein Fehler:

Signal ras cannot be synthesized, bad synchronous description.

von Kest (Gast)


Lesenswert?

Ich vermute mal, dass da noch ein ELSE-Zeweig fehlt

 if ale='0' and ale'event then
  ras <= '1';
 elsif En='1'  and En'event then
  ras <= '0';
 else
  ras <= 'Z'; -- oder so?
 end if;

Kest

von Benedikt (Gast)


Lesenswert?

Auch nicht:
Signal ras cannot be synthesized, bad synchronous description.

von Kest (Gast)


Lesenswert?

Womit synthetisierst Du?

Vielleicht doch 'event umschreiben? So wie:

if ale_old='1' and ale='0' then
 ale_old='0';
 ras <='1';

und so weiter?

Sonst weis ich auch nicht. Eigentlich sollte daraus etwas Kombinatorik
entstehen, aber damit kommt doch heutzutage jede Software klar, oder
etwa doch nicht? :-o

Kest

von Benedikt (Gast)


Lesenswert?

Ich verwende Xilinx ISE 6.3i und versuche das ganze in einen XC9536 zu
packen.

von Kest (Gast)


Lesenswert?

Okay, etwas wird mir klar, Benedikt. Ist zwar nur eine Vermutung, aber
ich denke, ich bin da schon ziemlich nahe an der Lösung:
und zwar guck Dir die Struktur der Macrozellen an. Meistens haben sie
nur einen CLOCK Eingang. Man kann also nur ein Mal 'event nehmen...
keine Ahnung, ob ich mich jetzt verständlich ausdrücke. Versuch' mal
ohne Else, sondern einfach mit if's zu schreiben


 if ale='0' and ale'event then
  ras <= '1';
 end if;

 if En='1'  and En'event then
  ras <= '0';
 end if;


vielleicht klappt es so?

Kest

von Benedikt (Gast)


Lesenswert?

Nein, so geht es auch nicht.

Alle Ideen die ich hatte, verstoßen gegen irgendeine VHDL Regel.

- 2 Events in einer if Schelife funktionieren nicht, da die Latches nur
1 Clock Eingang haben.
- 2 getrennte ifs gehen nicht, da man nicht einem Signal an zwei
getrennten Stellen einen Wert zuweisen kann. Die Software weiß nämlich
nicht, ob nicht beide ifs gleichzeitig wahr sein können.
- Das mit dem Hilfssignal läuft auf eine der beiden zuvor genannten
Verstöße zu, denn ale_old muss irgendwie auch wieder auf 1 gesetzt
werden.
Wenn ich solch eine Schaltung per Hand aufbauen würde, würde ich ein
RS-FF nehmen, und die beiden Signale differenzieren, um kurze Peaks zu
erzeugen mit denen das FF gesetzt bzw. zurückgesetzt wird. Aber leider
geht das hier nicht so einfach, und ein digitales Monoflop das mit
Hilfe einem Takt einen Peak erzeugt wäre etwas aufwenig...

von T.M. (Gast)


Lesenswert?

In einem Prozess darf nur 1 Clock signal mit 'Event abgefragt
werden.Alles andere führt zu obiger Fehlermeldung.

von T.M. (Gast)


Lesenswert?

1
process(B)
2
begin
3
  if B'event and B ='0' then
4
    B_intern <= '1'
5
  end if;
6
end process;
7
8
process(A, B_intern)
9
begin
10
  if B_intern = '1' then
11
    ras <= '0';
12
  elsif A'event and A = '1' then
13
    ras <= '1';
14
  end if;
15
end process;

probier es mal so

von FPGA-User (Gast)


Lesenswert?

@Benedikt

FFs die auf 2 Taktflanken arbeiten, gibts nur im CoolRunner II.

Versuch doch mal stattdessen die Funktion so zu beschreiben,
dass Du mit 1 Flanke und einem asynchronen Set- oder Reset-Signal
auskommst - geht das ?
Ansonsten wird nichts übrigbleiben, als die Signale einzutakten
und die übliche Flankenerkennung mit 2 FFs zu machen.

von Henrik K. (henrik)


Angehängte Dateien:

Lesenswert?

Man kann das nicht synthetisieren, weil man sich für die steigende oder
fallende Flanke entscheiden muß! Ein (einzelnes) FF das auf beide
Flanken reagiert gibt es auch nicht zu kaufen. Da musst man sich schon
eine etwas komplexere Logik einfallen lassen.
Im Anhang findest du die Schematik eines Vorschlags von mir. Aber
ACHTUNG: Diese Schaltung könnte sehr STÖRANFÄLLIG sein, da sie gezielt
Laufzeiten von Gattern ausnutzt! Ich empfehle dir Einschränkungen bei
deinen Anforderungen zu machen und etwas "stabileres" zu
programmieren!
Ich würde die Schltung NICHT einsetzen.

[VHDL]
entity SFF is
    Port ( A : in std_logic;
           B : in std_logic;
           Q : out std_logic
        );
end SFF;

architecture Behavioral of SFF is
Signal va      :std_logic;
Signal vb      :std_logic;
Signal res_vab  :std_logic;
begin

Main: Process (A,B, va, vb, res_vab)
begin

if (res_vab='0') then
  if  (A='0' and A'event) then
    va<='1' ;
  end if;
else
 va<='0';
end if;

if (res_vab='0') then
  if (B='1' and B'event) then
    vb<='1';
  end if;
else
 vb<='0';
end if;

res_vab<=vb;

Q<=va;

end Process Main;


end Behavioral;
[\VHDL]

Gruss Henrik

von Henrik K. (henrik)


Lesenswert?

Mal wieder 2 schneller...

von T.M. (Gast)


Lesenswert?

Mein Quelltext oben ist natürlich Quark. B_intern wird ja nie mehr
zurückgesetzt. Zu so später Stunde sollte ich wohl mein Gehirn nicht
mehr quälen ;-) Aber ich schliesse mich dem Vorschlag vom FPGA-User an,
dein Design so umzustellen, dass ein normales D-FF mit asynchr. Reset
eingesetzt werden kann. Lässt sich am besten handeln.

Grüße
T.M.

von T.M. (Gast)


Lesenswert?

Ich hätte dann doch ne Frage: Ich dachte immer, in einem Prozess ist nur
1 clocksignal erlaubt? Hendriks Code lässt sich aber einwandfrei
synthetisieren mit ISE... Hab ich da nen Verständnisproblem?

Grüße
T.M.

von Benedikt (Gast)


Lesenswert?

>Ich dachte immer, in einem Prozess ist nur 1 clocksignal erlaubt?

Erlaubt sind meherere, man sollte aber nur eines verwenden, da es
offiziell nicht funktionieren muss, es kann aber.

von Benedikt (Gast)


Angehängte Dateien:

Lesenswert?

Icb bechreibe mal für was ich das ganze brauche, vielleicht fällt
jemandem eine Lösung ein:

Das ganze ist ein DRAM Controller für einen AVR:
ALE dient als RAS Signal, aber leider bleibt dieses bis zum nächsten
Lesevorgang auf Low (was aber nicht sein darf, wegen dem precharge
Timing).
Jedenfalls möchte ich den Cyclus mit der Low High Flanke von RD\ oder
WR\ (bei mir schon als Enable zusammengefasst) wieder beenden.

Ich hab es auch nochmal als Bild angehängt: Das schwarze habe ich, das
rote suche ich.

von FPGA-User (Gast)


Lesenswert?

@Benedikt
warum nimmst Du nicht eine Statemachine, in der alle
benötigten Signale synchron vom Takt abgeleitet
werden ?
Bei den asynchronen Tricksereien handelst Du Dir Ärger
ein, wenn nicht alles 100 Pro durchdacht ist
(Timing bei versch. Temp. ...)

von Benedikt (Gast)


Lesenswert?

@FPGA-User

Wenn ich alles synchron mache, geht mir Wertvolle Zeit verloren. Das
Timing ist schon kritisch genug. Daher würde ich den Takt gerne auf das
ALE Signal beziehen, denn das gibt die Startbedingung vor und sollte so
schnell wie möglich verarbeitet werden.

Da ALE aus dem Takt abgeleitet wird, ist es leicht verzögert. Wenn ich
das jetzt wiederum mit dem takt synchronisiere habe ich zumindest eine
halbe Taktperiode veroren, (wodurch mir dann 25ns fehlen würden).

von Henrik K. (henrik)


Lesenswert?

@T.M. : Das in einem Prozess nur ein clock-Signal erleubt ist, kenne ich
nur indem Zusammenhang, dass es bei der Simulation Probleme geben kann,
nicht aber bei der Hardware.
Vielleicht ist das für eine Simulation besser geeignet:
1
entity SFF is
2
    Port ( A : in std_logic;
3
           B : in std_logic;
4
           Q : out std_logic
5
        );
6
end SFF;
7
8
architecture Behavioral of SFF is
9
begin
10
11
Main: Process (A,B)
12
variable res_vab  : std_logic;
13
variable va     : std_logic;
14
variable vb     : std_logic;
15
begin
16
17
if (res_vab='0') then
18
  if  (A='0' and A'event) then
19
    va:='1' ;
20
  end if;
21
else
22
 va:='0';
23
end if;
24
25
if (res_vab='0') then
26
  if (B='1' and B'event) then
27
    vb:='1';
28
  end if;
29
else
30
 vb:='0';
31
end if;
32
33
res_vab:=vb;
34
35
Q<=va;
36
37
end Process Main;
38
39
40
end Behavioral;

(wird auf das Gleiche synthetisiert wie oben)
Wie schon gesagt: Weil die Funktion durch die Laufzeiten von Gattern
funktioniert, würde ich diesen Code NICHT verwenden.

Gruss Henrik

von FPGA-User (Gast)


Lesenswert?

@Henrik

würde ich auch nicht einsetzen, res_vab ist ein Spike,
bei dem nicht sicher ist ob er ausreicht, um va wirklich
rückzusetzen.

Folgende Idee :
Das Reset-Signal für vb wird nicht aus dem eigenen Ausgang
Q sondern von va abgeleitet !
d.h.:

- der Ausgang von vb geht auf den Clear-Eingang von va
- der Ausgang von va geht auf den Clear-Eingang von vb
  (jetzt aber Lo-Aktiv)

Ziel ist, dass vb selbst erst asynchron zurückgesetzt
wird, wenn va ebenfalls zurückgesetzt wurde .

von Benedikt (Gast)


Lesenswert?

Ich habe jetzt noch etwas rumprobiert, und kam zu diesem Code, der
zumindest in der Simulation das macht, was ich möchte:

if ale='1' then
  state<='0';
elsif iclk='1' and iclk'event then
  state <= '1';
 end if;

if (state='1') then
  transfer <= '1';
 elsif ale='0' and ale'event then
  transfer <= '0';
 end if;

Dabei sind iclk und ale die Eingangssignale und transfer der Ausgang.

von FPGA-User (Gast)


Lesenswert?

hm, könnte gehen, sieht erstmal gut aus.

von Benedikt (Gast)


Lesenswert?

In der Praxis funktioniert es auch, aber leider hat das Ausgangssignal
etwa 20ns Verzögerung gegenüber einem anderen (das ebenfalls mit ale
geschaltet wird).

Kann man irgendwie im CPLD diese 20ns verschwenden ?

von TobiFlex (Gast)


Lesenswert?

Ich würde es so probieren:

if iclk='0' and iclk'event then
  ras_a <= NOT ale;
end if;

if iclk='1' and iclk'event then
  ras_b <= ras_a;
end if;

ras <= ras_a AND ras_b;

Kann sein, daß ich die VHDL-Syntax nicht richtig getroffen habe weil
ich meistens in AHDL arbeite.
Spikes dürften nicht auftreten, denn L in ras_a und ras_b überlappen
immerhin einen halben Takt.

von TobiFlex (Gast)


Lesenswert?

oder besser so:
Ich würde es so probieren:

if iclk='1' and iclk'event then
  ras_a <= NOT ale;
  ras_b <= ras_a AND NOT ale;
end if;


ras <= ale AND ras_b;

von TobiFlex (Gast)


Lesenswert?

if iclk='1' and iclk'event then
  ras_a <= NOT ale;
  ras_b <= ras_a AND NOT ale;
end if;


ras <= ale OR ras_b;
           ^^

Noch ein Fehler: hier muß OR statt AND stehen!

von Benedikt (Gast)


Lesenswert?

Ich versuche gerade irgendwie 10-20ns an Verzögerung in das 11bit breite
Adressensignal zu bekommen.
Dem FAQ von Xilinx nach geht das, aber bei mir irgendwie nicht...

http://www.xilinx.com/xlnx/xil_ans_display.jsp?iLanguageID=1&getPagePath=7595&BV_SessionID=@@@@0135735048.1125336611@@@@&BV_EngineID=ccchaddfidjdffgcefeceihdffhdfjf.0


Hier mein Code:

attribute KEEP : string;
attribute KEEP of adress0, adress1, adress2 : signal is "TRUE";
  --keep buffer from being optimized out

process (adress0) begin    --Adress Mux Delay
adress1 <=adress0;
adress2 <=adress1;
adress <=adress2;
end process;

Was mache ich falsch ?
Was hat das :string bei dem ersten attribute zu bedeuten ?

von FPGA-User (Gast)


Lesenswert?

@Benedikt

schreib erstmal alle Signale in die Sensitivity-List Deines Prozesses:
process(adress0, adress1, adress2)

oder vergiss besser die asynchrone Variante, erst war die synchrone
20 ns zu langsam, jetzt willst Du wieder 20 ns Verzögerung
reinbringen.
Glaub mir, das sind genau die Designs, die irgendwann funktionieren,
und wenn mal die Temperatur steigt oder ein SDRAM andere Parameter
hat dann gibts bei 3 von hundert Zugriffen Bitfehler - wie willst
Du das in den Griff bekommen ?

von Benedikt (Gast)


Lesenswert?

Wenn ich ein SDRAM ansteuern würde, wäre das ganze einfach, aber leider
steure ich ein normales DRAM an, und das ist leider asynchron...

Wenn ich es schaffe, alle Adressignale um mindestens 10ns zu verzögern,
dann liege ich mit dem Timing laut Datenblatt im grünen Bereich.
Abgesehen vom Beginn des RAS Signals (und der entsprechenden Adressen)
ist der Rest eigentlich unkritisch.

Mittlerweile habe ich es irgendwie geschafft die Buffer einzubauen.
Seltsamerweise hat ein Signal (Adress6) eine andere Verzögerung als der
Rest, obwohl es bei der Belegung (Makrozelle usw.) keine Besonderheiten
hat. Ohne Buffer hat jedes Signal 25ns.

Destination Pad ale Clock (edge) to Pad
adress<0> 42.000
adress<10> 42.000
adress<1> 42.000
adress<2> 42.000
adress<3> 42.000
adress<4> 42.000
adress<5> 42.000
adress<7> 42.000
adress<8> 42.000
adress<9> 42.000
adress<6> 34.500
ras 25.000

Für jedes Signal habe ich einen Buffer eingebaut:

my_buf : buf
port map (
i => adress0(0),
o => adress(0));

von high_speed (Gast)


Lesenswert?

Mit einem Design, das auf Laufzeiten aufbaut, wirst du unweigerlich
scheitern.
Erhöhe deinen Grundtakt und leite davon deine nötigen Takte ab.

MfG
Holger

von Benedikt (Gast)


Lesenswert?

Ich muss jediglich ein Signal etwas verzögern, um die CPLD Laufzeiten zu
kompensieren und die erforderlichen 10ns Hold Zeit erreichen.
Der Rest vom Timing ist fest vorgegeben.

Mit einer Handvoll TTL ICs (Adressmultiplexer, Refreshzähler usw.) und
einer Delayline wurde sowas früher oft aufgebaut.

von FPGA-User (Gast)


Lesenswert?

@Benedikt

Nix für ungut, aber Holger hat recht, das Ding geht in die Hose
wenn Du Dich auf irgendwelche Delays verlässt.

Ich habe schone einige Memory-Interfaces gemacht, u.a. für NAND-
Flash, asyncrone RAMs, DDR-RAM, MMC/SD-Cards usw.,
aber immer die Adressen, Daten und Strobes synchron von einem
Takt abgeleitet, das hat sich super bewährt.
Du kannst das Timing genau nachvollziehen und der Timing-Analyzer
in der FPGA-Software liefert die richtigen Werte.
Außerdem ist dann garantiert, dass die Geschichte im ges.
Temp-Bereich und Betriebsspannungsbereich funktioniert.

von Benedikt (Gast)


Lesenswert?

OK, ich habe jetzt einen größeren CPLD genommen, bin daher mit den Pins
etwas flexibler (beim kleinen hatte ich keine freien Pins mehr, weshalb
ein externer Takt unmöglich war).
Damit versuche icht jetzt noch ein letzes mal die asynchrone Version,
wenn das nix wird stelle ich auf synchron um.

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.