Jonny schrieb:> Kann mir jemand sagen, wieso in Diamond1.3 die gezeigte> VHDL-Beschreibung komplett wegoptimiert wird?
Weil nach drei Takten sowieso eine '1' am Ausgang ankommt. Ein halbwegs
schlaues Synthesewerkzeug macht daraus eine Schieberegisterkette und
fertig.
Altera Quartus II 11.0 SP1 nimmt obige Beschreibung und implementiert
drei Register.
Bedeutet dies, dass man bei Lattice keine Signal-Initialisierungen
verwenden darf und einen Reset benötigt?
Grüsse,
Jonny
Würde meinen ein default-assignment hilft:
elsif rising_edge(Clk) then
ena <= '0'; -- Default assignment
case fsm is
when ss_rst => fsm <=ss_ini;
when ss_ini => fsm <= ss_active;
when ss_active => ena <= '1';
end case;
end if;
Aus der Synplify Pro Hilfe von Diamond:
----------------------
Ignored VHDL Language Constructs
The synthesis tool ignores the following constructs in your design. If
found, the tool parses and ignores the construct (provided that no logic
is required to be synthesized) and continues with the synthesis run.
disconnect
assert and report
initial values on inout ports
------------------------------
Ich denke Punkt 3 trifft hier zu.
Hi Pek,
ja eine Default-Zuweisung hilft.
Aber finde ich ja höchst interessant, dass Xilinx und Altera die
Beschreibung schlucken, aber Lattice nicht. Man kann halt überhaupt gar
nichts verallgemeinern, das ist mal sicher! Gerade die Aussage: "Man
nehme überhaupt keinen Reset, und alles ist in Ordnung".
Grüsse,
Jonny
Jonny schrieb:> Aber finde ich ja höchst interessant, dass Xilinx und Altera die> Beschreibung schlucken, aber Lattice nicht.
Bis vor knapp 2 Jahren hat das noch keiner geschluckt. Nicht mal bei
internen Signalen.
Jonny schrieb:> Gerade die Aussage:> "Man nehme überhaupt keinen Reset, und alles ist in Ordnung".
Ich meinte, darauf verwiesen zu haben, dass es um das WP272 der Firma
Xilinx ging. Bei Lattice war bis zum Synthesizerwechsel vor 2 Jahren
überhaupt keine Signalinitialisierung in der freien Toolchain möglich.
> Man kann halt überhaupt gar nichts verallgemeinern, das ist mal sicher!
Man kann einiges verallgemeinern, aber man sollte sich immer wieder mal
anschauen, ob die Verallgemeinerung im Allgemeinen noch funktioniert...
;-)
Lothar Miller schrieb:>> Gerade die Aussage:>> "Man nehme überhaupt keinen Reset, und alles ist in Ordnung".> Ich meinte, darauf verwiesen zu haben, dass es um das WP272 der Firma> Xilinx ging.
Vieles was im WP272 über Resetprobleme steht ist allgemein gültig, z.B.
dass ein Resettaster böse ist.
Die Konsequenzen sind halt verschieden und hängen von der Architektur
ab. Die Flipflops im Lattice haben im Gegensatz zu Xilinx immer noch
einen Set/Reset Eingang.
Die Beschreibung eines Registers mit einem asynchronen Reset braucht bei
Lattice keine extra Reseourcen, während das bei Xilinx wohl die teuerste
Variante ist.
Man kann bei Lattice das Reset auf dem Toplevel an eine PUR Instanz
binden und braucht dann kein externes Resetsignal mit seinen extra
Problemen.
Schwierig ist halt allgemein portabler VHDL/Vferilog Code zu schreiben.
martin schrieb:> Die Verwendung von initial Werten ist keine gute Idee bei der Synthese.> Wie soll denn die Hardware so etwas nachbilden.
Hä?!? Ganz einfach, indem die initialen Werte beim Laden der
Konfiguration in die Register geladen werden? Das sowas bei einem ASIC
Design nicht geht ist klar, aber bei FPGAs gehts nunmal. Punkt.
Ich denke es kommt auf auf die Zielhardware an
ob init-Werte Sinn machen oder nicht.
Also ich beim ersten Code mal 1 und 0 bei "ena" vertauscht,
und den Code dann in den ISE9.2 geworfen:
Beim ersten Lauf ist das Ziel ein Spartan3:
Und siehe da
Es werden 3 FF erzeugt, und das erste hat den init
wert '1' bekommen => also started dieses Flipflop nach dem
FPGA download mit einer 1 (ganz ohne extra Reset Leitungen).
Beim zweiten Lauf ist der Zielbaustein ein CPLD:
Und: tja auch ISE optimiert hier alles weg,
der ena ist nur noch Konstant auf 1.
Nun ist die Frage: Welches Ziel hat Jonny bei
der Synthese mit Diamond1.3 von Lattice gewählt:
FPGA oder CPLD ?
Ich denke das bei RAM-basierte FPGAs die Init-Werte bei
Registern durchaus Sinn machen, denn die download logic
auf den FPGAs sorgt dafür das Initwerte bei den Flipflops
(und RAMs) ankommen.
Hingegen brauchen CPLDs, Proasics und richtige ASICs durchaus
immer Syncrone oder Asyncrone Resets, da hier jedes
Flipflop in einem Unbekannten Zustand started.
Zusatz:
Behauptung: jeder Chip enthält mindestens einen asyncronen Reset!
martin schrieb:> Und weils beim asic nicht geht sollte man sich so einen stil garnicht> erst angewoehnen
Weil 1% der VHDL-Anwender ASICs machen, sollen 99% die Vorteile der
FPGAs nicht nutzen?
Weil 1% der VHDL-Anwender ASICs machen, sollen 99% asynchrone Resets
verwenden?
Sollte man dann auch keine Taktmanager, IO-Zellen usw. verwenden?
Für mich gilt auf jeden Fall: wenn mir mein Chip eine tolle Funktion
bietet, dann verwende ich die auch.
bko schrieb:> Behauptung: jeder Chip enthält mindestens einen asyncronen Reset!
Logisch, das steht ja sogar in der Xilinx-Doku und ist im altbekannten
Beitrag "Re: Xilinx und die Resets" erwähnt.
Die Tools machens unterschiedlich, weil die "ena" für die ersten beiden
States schlicht nicht definiert ist. Der springende Punkt ist, dass Du
in Software denkst. VHDL ist aber keine Programmiersprache, sondern eine
Hardwarebeschreibungssprache (mindestens soweit das Elaborat
synthetisierbar sein soll). Deshalb ist es ein guter Ansatz, in
Registern und Übergangslogik zu denken (strikte Zweiprozesslösung ist
für mich die direkte Quintessenz daraus, in den sequentiellen Prozess
gehört überhaupt keine Logik, in den kombinatorischen gehört ein
Default-Assignment für JEDES Ausgangssignal).
In Hardware gedacht bedeutet folgende Sequenz:
if rising_edge(Clk) then
case fsm is
when ss_rst => fsm <=ss_ini;
when ss_ini => fsm <= ss_active;
when ss_active => ena <= '1';
end case;
end if;
nichts anderes als:
ss_rst : ena = don't care
ss_ini : ena = don't care
ss_active : ena = '1'
und der Synthesizer macht damit, was er will (ein guter wird die Logik
minimieren und eine fixe '1' zuweisen). Dass der Initialwert
ursprünglich '0' war spielt aus HW-Sicht keine Rolle. Es wäre
(akademischer Fall) sogar noch korrekt wenn das Tool bei ss_rst eine '1'
und bei ss_ini eine '0' zuweist. Darum: Wenn man ein Signal in jedem
Fall definiert, kriegt man auch, was man sich wünscht.
Gruss
Peter
das ist doch unfug, ena soll den Zustand behalten bis der State erreicht
ist.
Man muss keinesfalls für jeden State einer FSM auch jedem Signal eine
Zuweisung machen.
Es ist vielmehr so:
In Hardware gedacht bedeutet folgende Sequenz:
if rising_edge(Clk) then
case fsm is
when ss_rst => fsm <=ss_ini;
when ss_ini => fsm <= ss_active;
when ss_active => ena <= '1';
end case;
end if;
nichts anderes als:
ss_rst : ena <= ena
ss_ini : ena <= ena
ss_active : ena <= '1'
Warum bitte soll man das explizit hinschreiben?
pek schrieb:> Die Tools machens unterschiedlich, weil die "ena" für die ersten beiden> States schlicht nicht definiert ist.
Nein, es ist sehr wohl definiert. Aber weil ena in den ersten beiden
States nicht verändert/verwendet wird, MUSS es speichernd sein und den
zuletzt zugewiesenen Wert halten. Und das ist hier nun mal der
Initialisierungswert '0'. Der Simulator sieht das genauso, und deshalb
ist das hier falsch:
> und der Synthesizer macht damit, was er will (ein guter wird die Logik> minimieren und eine fixe '1' zuweisen).
Darf er nicht!
Ausgenommen: er kann es nicht und dieses (aus VHDL-Sicht fehlerhafte)
Verhalten ist dokumentiert.
> Dass der Initialwert ursprünglich '0' war spielt aus HW-Sicht keine Rolle.
Oh doch, durchaus....
Im Anhang die Screenshots der Simulation und der RTL-Pläne von Xilinx
ISE13 auf Spartan3...
abc schrieb:> ss_rst : ena <= ena> ss_ini : ena <= ena> ss_active : ena <= '1'
Du hast Recht, das ist mir die nicht sehr lesbare "alles in einem
Prozess"-Variante etwas durch die Lappen. Nichts desto trotz, erachte
ich folgende Schreibweise (obwohl sie etwas mehr Platz benötigt) als
viel lesbarer und robuster:
-- Combinational: Reset FSM
-----------------------------------------------------------------------
fsm : process (fsm_cur)
begin
-- Default assignments
---------------------------------------------------------------------
ena <= '0';
fsm_next <= fsm_cur;
-- FSM
---------------------------------------------------------------------
case fsm_cur is
when SS_RST =>
fsm_next <= SS_INI;
when SS_INI =>
fsm_next <= SS_ACTIVE;
when SS_ACTIVE =>
ena <= '1';
when others =>
fsm_next <= SS_RST;
end case;
end fsm;
-- Sequential: Common register block
----------------------------------------------------------------------
seq : process (HardResxRN, SysxC)
begin
if HardResxRN = RESET_ACTIVE then
fsm_cur <= SS_RST;
elsif (SysxC'event and SysxC = '1'
--synopsys translate_off
and SysxC'last_value = '0'
--synopsys translate_on
) then
fsm_cur <= fsm_next after PROP_DELAY;
end if;
end process seq;
pek schrieb:> erachte ich folgende Schreibweise als viel lesbarer und robuster:
Die beliebte Zwei-Prozess-Schreibweise, die Anfänger immer in
kombinatorische Schleifen führt... ;-)
Seis durm: der eine mag Blonde, der andere Schwarze, der eine Große, der
andere kleine... Aber Hauptsache: sie mögen sich und kommen miteinander
aus.
> fsm_cur <= fsm_next after PROP_DELAY;
Zum Thema "Zeiten in der funktionalen Simulation" das dort im
Beitrag "Re: Frage zu Pseudozufallsgenerator!?"> (SysxC'event and SysxC = '1'> --synopsys translate_off> and SysxC'last_value = '0'> --synopsys translate_on> )
Wieso 5 Zeilen, wenn rising_edge() (was ja EXAKT das selbe macht)
gereicht hätte?
Lothar Miller schrieb:>> fsm_cur <= fsm_next after PROP_DELAY;> Zum Thema "Zeiten in der funktionalen Simulation" das dort im> Beitrag "Re: Frage zu Pseudozufallsgenerator!?"
Zusammengefasst: Der Delay wird nicht synthetisiert. Ist vorbeugend für
die Simulation. Es gibt Simulatoren/Modelle, die können mit 0-Holdtime
schlecht umgehen. Wichtig PROP_DELAY muss kürzer als ein clock-cycle
sein.
>> (SysxC'event and SysxC = '1'>> --synopsys translate_off>> and SysxC'last_value = '0'>> --synopsys translate_on>> )>> Wieso 5 Zeilen, wenn rising_edge() (was ja EXAKT das selbe macht)> gereicht hätte?
Naja, Einwand stimmt zu 100% für FPGA-Only. Benutze immer denselben
sequentiellen Prozess, der halt auch für den Einsatz in ASIC's und
Simulation mit "Würfel"-FF und "Don't care at start"-FF benutzt wurde.
Bei einer späteren ASIC-Integration wäre dann alles schon da.
pek schrieb:> Zusammengefasst: Der Delay wird nicht synthetisiert....
...und er kann zu Pseudotakten führen.
pek schrieb:> Es gibt Simulatoren/Modelle, die können mit 0-Holdtime schlecht umgehen.
Welchen Simulator betrifft das?
Drei weiß ich, die es nicht betrifft: Aldec, Modelsim und ISIM.
Lothar Miller schrieb:>> Zusammengefasst: Der Delay wird nicht synthetisiert....> ...und er kann zu Pseudotakten führen.
...vermutlich nur wenn noch Übergangslogik im Prozess ist, hatte noch
nie Probleme damit (wir haben damit 3 Multimedia-Prozessoren simuliert
und synthetisiert).
> pek schrieb:>>> Es gibt Simulatoren/Modelle, die können mit 0-Holdtime schlecht umgehen.> Welchen Simulator betrifft das?> Drei weiß ich, die es nicht betrifft: Aldec, Modelsim und ISIM.
ncsim, vcs, und ja, auch mit modelsim gabs schon probleme, vorwiegend
mit IP-Simulationsmodellen (das sind dann Simulations-Fälle die
vermutlich in eine ähnliche Kategorie gehören, wie diejenigien wo noch
ein "wait for 0 ns" eingefügt werden muss, damit der Tick eins weiter
geht...)
pek schrieb:>>> Zusammengefasst: Der Delay wird nicht synthetisiert....>> ...und er kann zu Pseudotakten führen.> ...vermutlich nur wenn noch Übergangslogik im Prozess ist
Richtig:
Ein Propagation-Delay tritt im kombinatorischen Prozess auf.
Die Zeit vom Takt bis zum stabilen Durchreichen an den FF-Ausgang heißt
tco (Clock-to-Output).
>Man kann bei Lattice das Reset auf dem Toplevel an eine PUR Instanz>binden und braucht dann kein externes Resetsignal mit seinen extra>Problemen.
OK, und wie sehen dann die Reset-Werte der einzelnen Register aus? Wie
wir ja festgestellt haben, werden "signal initial values" ignoriert.
Also was für einen Sinn macht es dann eine PUR-Instanz zu verwenden,
zumal diese ja nur einen Eingang hat?
Grüsse, Jonny
>Aus der Synplify Pro Hilfe von Diamond:>>---------------------->Ignored VHDL Language Constructs>>initial values on inout ports>-----------------------------
Aus der Synplify Pro Hilfe von Diamond, ab Version 1.2
Nun ist es endlich mal offiziell!
VG, SuperWilly
Jonny schrieb:> Was hilft dir eine PUR-Instanz, wenn die Module keinen Reset-Eingang> haben?
Ich habe mich getäuscht, PUR/GSR Instanzen dienen dazu um in einer
Testbench das Startupverhalten besser abbilden zu können.
Nach einigen probieren bin ich zum folgenden Schluss gekommen:
Synplify erkennt in deiner orginalen Version ein synchrones R/S Flipflop
für ena, und ignoriert dann den initial value.
1
W BN288 Register ena with set has an initial value of 0. Ignoring initial value. test5.vhd (27) Test5.srr (38) 17:26:57 Wed Sep 28 premapping
wenn man in der FSM irgendwo noch eine '0' an ena zuweist, klappt es mit
dem D-Fliplop und auch mit initial value.
>Aus der Synplify Pro Hilfe von Diamond:>>---------------------->Ignored VHDL Language Constructs>>initial values on inout ports>-----------------------------
Aber bedeutet dies nicht, dass Signale (Register) initialisiert werden
dürfen? Es werden ja nur Ports genannt.
Grüsse, Jonny
OK, also wenn wir nochmal zum Ausgangspunkt der Diskussion zurück gehen
-
wieso wird der als erstes gezeigte Code wegoptimiert?
Weil Lattice (bzw. SynplifyPro für Lattice) keine
Signalinitialisierungen unterstützt oder warum?
Jonny schrieb:> Weil Lattice (bzw. SynplifyPro für Lattice) keine> Signalinitialisierungen unterstützt oder warum?
Hast du meine letze Post weiter oben gelesen und versucht zu verstehen?
Es wird nicht das korrekte FF inferreriert, da in der FSM nur einmal
eine '1' an ena zugewiesen wird.
Da geht:
1
libraryieee;
2
useieee.std_logic_1164.all;
3
4
5
entitye_testis
6
port(
7
Clk:instd_logic;
8
EnaOut:outstd_logic
9
);
10
ende_test;
11
12
13
14
architecturetestofe_testis
15
16
17
typet_fsmis(ss_rst,ss_ini,ss_active);
18
signalfsm:t_fsm:=ss_rst;
19
signalena:std_logic:='0';
20
21
begin
22
23
EnaOut<=ena;
24
25
FSM:process(Clk)
26
begin
27
ifrising_edge(Clk)then
28
casefsmis
29
whenss_rst=>fsm<=ss_ini;
30
whenss_ini=>fsm<=ss_active;ena<='0';
31
whenss_active=>ena<='1';
32
endcase;
33
endif;
34
endprocess;
35
36
endtest;
Und wenn ich den initial Wert ändere
1
signalena:std_logic:='1';
sehe ich das auch im Ergebnis (Physical View von Diamond).
Siehe in den beiden angängten Bildern, der Reset/Set am FF unterscheidet
sich.