Hallo,
ich versuche mich (wieder) in VHDL einzuarbeiten. Dazu versuche ich
einen einfachen Zähler aus dem Netz mit Modelsim zu simulieren:
1
LIBRARY IEEE;
2
USE IEEE.STD_LOGIC_1164.ALL;
3
USE IEEE.NUMERIC_STD.ALL;
4
5
ENTITY three_bit_counter IS
6
PORT (
7
clk : IN STD_LOGIC;
8
enable : IN STD_LOGIC;
9
count : OUT UNSIGNED (2 DOWNTO 0)
10
);
11
END ENTITY three_bit_counter;
12
13
ARCHITECTURE Behavioral OF three_bit_counter IS
14
15
SIGNAL internal_count : UNSIGNED (2 DOWNTO 0) := "000";
16
17
BEGIN
18
counter: PROCESS (clk, enable)
19
BEGIN
20
IF rising_edge(clk) AND enable ='1' THEN
21
internal_count <= internal_count + 1 AFTER 15 ns;
22
END IF;
23
END PROCESS counter;
24
25
count <= internal_count;
26
27
END Behavioral;
Die Entwicklungsumgebung ist Libero 12.1 / Modelsim 10.7C.
Ich nutze (vorerst) keine Testbench sondern setze die Signale in
Modelsim manuell (rechte Maustaste->Modifiy->force...)
Leider Zählt der Ausgang "count" nicht wie erwartet hoch, sondern bleibt
"X"
Kann mir das Jemand erklären?
Vielen Dank,
Markus
Markus schrieb:> internal_count <= internal_count + 1 AFTER 15 ns;
Ein Tipp: lass gleich zu Beginn diese symbolischen Pseudo-Verzögerungen
weg. Die sind eh' nicht synthetisierbar und du legst dir damit
irgendwann selbst ein Ei.
Siehe dazu den Beitrag "Re: Einfaches Schieberegister in VHDL?"Markus schrieb:> Zählt der Ausgang "count" nicht wie erwartet hoch, sondern bleibt "X"
Er "bleibt" nicht 'X', sondern er kommt von 'U' und wird dann 'X'. Das
kommt von 2 Treibern, die auf dieses Signal gehen und liegt offenbar an
dieser murksigen manuellen Forcerei, denn mit einer simplen Testbench
klappt das wunderbar wie erwartet.
Wobei dir hier schon diese symbolische Verzögerung von 15ns das Bild
nahezu undurchschaubar macht. Wenn ich das weglasse, dann passiert immer
nur genau bei oder besser wegen der steigenden Taktfklane was. Und so
ein Bild habe ich im Kopf. Es macht die Sache einfach und überschaubar.
Wenn ich die Simulation mit der Testbench versuche kommt eine
Fehlermeldung:
** Fatal: (vsim-3807) Types do not match between component and entity
for port "count".
# Time: 0 fs Iteration: 0 Instance: /tb_counter/uut
File:../synthesis/three_bit_counter.vhd Line: 12
Das sieht irgendwie so aus, als ob der "unsigned" nicht nach
"std_logic_vector" gecastet wird (oder umgekehrt).
Fehlt da vlt irgendwo ein "use" oder könnte irgendwo eine Einstellung
falsch sein?
Markus schrieb:> oder könnte irgendwo eine Einstellung falsch sein?
Was steht denn in der Zeile 12?
Und was kommt raus, wenn du mal alle Deklarationen von "count" genauer
anschaust?
Du selber hatttest das doch letzthin noch ganz anders deklariert,
denn Markus schrieb:> count : OUT UNSIGNED (2 DOWNTO 0)
Und jetzt:
> count : out std_logic_vector(2 downto 0)
Und die Testbench:
> count : OUT UNSIGNED(2 downto 0)
Merkst du was?
BTW: was ist denn das für ein unheimlich umständliches Herumgehampel mit
smartfusion-Primitiven, das du da angehängt hast? Wo hast du dieses
umständliche Gebastel gefunden?
Lothar M. schrieb:> BTW: was ist denn das für ein unheimlich umständliches Herumgehampel mit> smartfusion-Primitiven, das du da angehängt hast? Wo hast du dieses> umständliche Gebastel gefunden?
Das wird automatisch von Libero generiert, bevor dann Modelsim gestartet
wird, welches die o.g. Fehlermeldung im Log hat.
In den Quellfiles steht nach wie vor nur die Deklaration als unsigned
drin.
So wie ich dass verstehe, arbeitet die Bibliothek zum simulieren mit
std_logic_vektor und nicht mit unsigned. Daher meine Vermutung, dass
irgendwo noch eingestellt werden muss, dass und wie "unsigned" nach
"std_logic_vektor" konvertiert werden soll.
Markus schrieb:> dass irgendwo noch eingestellt werden muss, dass und wie "unsigned" nach> "std_logic_vektor" konvertiert werden soll.
Da gibts nichts "einzustellen". Typkonvertierungen müssen in VHDL
explizit gemacht werden, da geht nichts "automatisch" (*). Du musst also
in der Testbench auch eine Komponente mit std_logic_vector definieren
und die Komponente passend deklarieren.
(*) die "automatische" Addition des UNSIGNED zu einem Integer in
"internal_count + 1" geht z.B. nur, weil der der Operator '+' so
überladen ist, dass er diese Operation ausführen kann. Das findest du im
Sourcecode der numeric_std.
Ok,
ich habe jetzt die Deklaration des Ports von unsigned nach
std_logic_vector geändert. Ich kann jetzt wieder simulieren, mit dem
gleichen Ergebnis wie vom Eingangspost.
Allerdings bin ich jetzt auf eine Warnung gestossen:
User-specified initial value defined for instance internal_count[2:0] is
being ignored due to limitations in architecture.
Ein nicht initialisiertes Signal "internal_count" erklärt das
Simulationsergebnis.
Wenn jetzt bei enable='0' den internal_count auf 0 setze dann zählt der
Zähler auch wie erwartet hoch:
1
ARCHITECTURE Behavioral OF three_bit_counter IS
2
3
SIGNAL internal_count : UNSIGNED (2 DOWNTO 0) := "000";
4
5
BEGIN
6
counter: PROCESS (clk, enable)
7
BEGIN
8
IF rising_edge(clk) then
9
if enable='0' then
10
internal_count <= (others => '0');
11
else
12
internal_count <= internal_count + 1 ;
13
end if;
14
END IF;
15
END PROCESS counter;
16
count <= std_logic_vector(internal_count);
17
18
END Behavioral;
Was sind das für "limitations in architecture" bzw. wie kann ich diese
eleganter umgehen, so dass obiges ":= "000";" funktioniert ?
Markus schrieb:> Allerdings bin ich jetzt auf eine Warnung gestossen:> User-specified initial value defined for instance internal_count[2:0] is> being ignored due to limitations in architecture.
Das sagt aber mit ziemlicher Sicherheit der Sythesizer und nicht der
Simulator.
> Was sind das für "limitations in architecture"
Dein flash-basierter Baustein von Microsemi kann keine Initialwerte
verarbeiten. Nähere Informationen sind sicher im Datenblatt zu finden.
Du musst einen expliziten Reset vorsehen.
> bzw. wie kann ich diese> eleganter umgehen, so dass obiges ":= "000";" funktioniert ?
Du kannst sie nicht "umgehen", weil der Baustein sie nicht unterstützt.
Im "Actel HDL Coding Style Guide" findet sich der klare Satz
"In the absence of a reset, there is no way of predicting the initial
value of the state register flip-flops during the “power up” operation
of an Actel FPGA."
Lothar M. schrieb:> Das sagt aber mit ziemlicher Sicherheit der Sythesizer und nicht der> Simulator.
Ja, das ist richtig. Die Warnung kommt vom Synthesizer.
> Dein Baustein kann offenbar keine Initialwerte verarbeiten. Nähere> Informationen sind sicher im Datenblatt zu finden.
Auf die Schnelle konnte ich da jetzt nichts zu finden (ist ein IGLOO2).
Ich lasse das also erstmal so, auch wenn das "unschön" ist.
Danke für deine Unterstützung.
Markus
Markus schrieb:>> BTW: was ist denn das für ein unheimlich umständliches Herumgehampel mit>> smartfusion-Primitiven, das du da angehängt hast? Wo hast du dieses>> umständliche Gebastel gefunden?>> Das wird automatisch von Libero generiert, bevor dann Modelsim gestartet> wird, welches die o.g. Fehlermeldung im Log hat.>> In den Quellfiles steht nach wie vor nur die Deklaration als unsigned> drin.
Sieht danach aus, als ob hier der TO eine post-map bzw. gate-level
Simulation macht.
@Markus: Sieh mal in ein Libero Tutorial wie das mit der Simulation
eigentlich vorgesehen ist. Da muss es noch andere Knöpfe geben um eine
einfach VHDL Simulation zu machen ohne das vorher etwas Synthetisiert
wird.
Christophz schrieb:> Sieh mal in ein Libero Tutorial wie das mit der Simulation> eigentlich vorgesehen ist. Da muss es noch andere Knöpfe geben um eine> einfach VHDL Simulation zu machen ohne das vorher etwas Synthetisiert> wird.
Ja, Du hast Recht. Ganz oben unter "Verify Pre-Synthesized Design" gibts
das. Das hatte ich irgendwie übersehen/ignoriert. Aber spätestens, wenn
ich dann für den konkreten FPGA synthetisiere kommt ja das Problem mit
den "limitations in architecture". Das wäre mir dann auf die Füsse
gefallen.
Aber generell ist es wohl der richtige Weg, erstmal ohne synthetisieren
zu simulieren. Danke für den Hinweis.
BTW: Ich habe noch ein Problem mit dem Workflow. Zur Zeit läuft der
folgendermassen ab:
- VHDL schreiben/ändern
- in Libero im Designflow "simulieren" drücken
- es wird synthetisiert, anschliessend automatisch Modelsim aufgerufen
- in Modelsim ziehe ich mir die Signale, die mich interessieren in das
Wave Fenster (die Signale die nach aussen (Testbench) geführt sind, sind
schon drin)
- wenn das Ergebnis nicht so ist wie erwartet, beende ich Modelsim und
fange wieder oben an
Das "reinholen" der Signale habe ich schon über ein do-File
automatisiert, aber es kann doch nicht richtig sein, dass ich jedesmal
den Modelsim beenden und über Libero neu starten muss.
Ich konnte im Netz keine brauchbare Lösung zu diesem "Problem" finden.
In irgendeinem Tutorial stand, dass man über Modelsim synthetisieren
soll, aber das scheiterte bei mir schon an der Auswahl der
Quellfiles/Bibliotheken.
Markus
Markus schrieb:> Das "reinholen" der Signale habe ich schon über ein do-File> automatisiert, aber es kann doch nicht richtig sein, dass ich jedesmal> den Modelsim beenden und über Libero neu starten muss.
Nein, muß man auch nicht.
1. Das Synthetisieren in Libero sollte für eine Simulation nicht nötig
sein.
2. Modelsim muß alle geänderten (und davon abhängigen) Quelldateien neu
compilieren: vcom *.vhd oder vmake
3. im noch geöffneten Modelsim: 'restart -f' und 'run -all' eintippen
Duke
P.S.: Pro-Tipp im .do-File eine Funktion für Tippfaule einbinden:
Ah, ok.
Die Parameter für's compilieren kann ich mir aus dem File "run.do"
rauskopieren, welches von Libero beim Aufruf von Modlesim erzeugt wird.
Vielen Dank.
Markus