Archiv verlassen und diese Seite im Standarddesign anzeigen : [VHDL] Globale Variable/Signal?
redraven
15.12.2010, 16:24
Hi Community,
ich habe folgendes Problem:
Ich hab in VHDL 3 Prozesse. Der erste ist aktiv wenn der Reset-Taster gedrückt ist. In dem Prozess sollen alle Ausgänge bzw Signale auf '0' gesetzt werden. Soweit so gut.
Ein weiterer Prozess startet wenn der Start-Taster gedrückt wird. Da wird ein Signal auf '1' gesetzt.
Beim starten der Simulationssoftware (Multisim) bekomme ich folgenden Fehler: "Nonresolved signal 'VARIABLENNAME' has multiple sources."
Meine Frage jetzt: Wie kann ich solche Signale in mehreren Prozessen verwenden und verändern? "Shared Variable" geht für die Simulation aber soll sich nicht Synthetisieren lassen.
Grüße
poste mal bitte den quellcode....
redraven
15.12.2010, 19:37
Fehler: Nonresolved signal 'z_alt' has multiple sources.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY auswahl IS
PORT(
rst : IN std_logic;
start : IN std_logic;
zw_zeit : IN std_logic;
enable_zaehler : OUT std_logic;
in_w_en : OUT std_logic;
up_dn_zahler : OUT std_logic
);
-- Declarations
END auswahl ;
--
ARCHITECTURE verh_auswahl OF auswahl IS
signal zw_z: std_logic := '0';
signal z_alt: integer := 1;
BEGIN
--Taster Reset Prozess
reset_proc: process(rst)
begin
if rising_edge (rst) then
enable_zaehler <= '0';
in_w_en <= '0';
up_dn_zahler <= '1';
zw_z <= '0';
z_alt <= 1;
end if;
end process;
--Taster Zwischenzeit Prozess
zw_zeit_proc: process(zw_zeit)
begin
if rising_edge (zw_zeit) then
if zw_z = '0' then
zw_z <= '1';
in_w_en <= '1';
else
in_w_en <= '0';
end if;
end if;
end process;
--Enable-Zähler-Signal Prozess
run_proc: process(start)
begin
if rising_edge(start) then
if zw_z = '0' then
if z_alt = 1 then
enable_zaehler <= '1';
up_dn_zahler <= '1';
z_alt <= 2;
elsif z_alt = 2 then
enable_zaehler <= '0';
z_alt <= 3;
elsif z_alt = 3 then
enable_zaehler <= '1';
up_dn_zahler <= '0';
z_alt <= 4;
else
enable_zaehler <= '0';
z_alt <= 1;
end if;
end if;
end if;
end process;
END ARCHITECTURE verh_auswahl;
Ich stelle mir das gerade in Hardware vor. Du willst in zwei unabhängigen Prozessen durch verschiedene Aktionen die gleichzeitig ablaufen können einen Ausgang schalten. Und das mit unterschiedlichen Werten. Wer soll denn da gewinnen?
Du solltest da vielleicht mit zwei unabhängigen Variablen arbeiten und diese anschließend durch eine Logik zusammenbringen. Z.B ein Prozess setzt ein Signal und der andere setzt es zurück.
Oder du verwendest eine Art Mutex um die Variablenzuweisungen.
Im Prinzip sollte es reichen, wenn du vor dem Ändern der Variable im reset-Prozess eine Flagvariable setzt und anschließend wieder rücksetzt und im start-Prozess nur eine Änderung zuläßt, wenn das Flag nicht gesetzt ist.
Allerdings hab ich von den Möglichkeiten der VHDL Programmierung keine Ahnung. Möglicherweise gibts da ja schon fertige Konstrukte für Mutex, Semaphore und Konsorten. Sieh's also nur als Gedankenstütze.
sast
Du kannst auch alle drei Prozesse in einen verpacken. Dabei prüfst Du, ob Reset auf '1' steht (nicht auf rising_edge). Wenn ja, dann wird alles auf '0' gesetzt, ansonsten auf die anderen Eingaben reagiert. Also etwa so
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY auswahl IS
PORT(
rst : IN std_logic;
start : IN std_logic;
zw_zeit : IN std_logic;
enable_zaehler : OUT std_logic;
in_w_en : OUT std_logic;
up_dn_zahler : OUT std_logic
);
-- Declarations
END auswahl ;
--
ARCHITECTURE verh_auswahl OF auswahl IS
signal zw_z: std_logic := '0';
signal z_alt: integer := 1;
BEGIN
--Taster Reset Prozess
reset_proc: process(rst, zw_zeit, start)
begin
if rst = '1' then -- bei Reset auf nichts anderes reagieren
enable_zaehler <= '0';
in_w_en <= '0';
up_dn_zahler <= '1';
zw_z <= '0';
z_alt <= 1;
else -- Kein Reset
--Taster Zwischenzeit Prozess
if rising_edge (zw_zeit) then
if zw_z = '0' then
zw_z <= '1';
in_w_en <= '1';
else
in_w_en <= '0';
end if;
end if;
--Enable-Zähler-Signal Prozess
if rising_edge(start) then
if zw_z = '0' then
if z_alt = 1 then
enable_zaehler <= '1';
up_dn_zahler <= '1';
z_alt <= 2;
elsif z_alt = 2 then
enable_zaehler <= '0';
z_alt <= 3;
elsif z_alt = 3 then
enable_zaehler <= '1';
up_dn_zahler <= '0';
z_alt <= 4;
else
enable_zaehler <= '0';
z_alt <= 1;
end if;
end if;
end if;
end if;
end process;
END ARCHITECTURE verh_auswahl;
Dann hat jedes Signal genau eine Quelle.
MfG Mark
Edit: 'then' nach dem ersten if eingefügt.
redraven
16.12.2010, 10:25
Hi Mark,
geht das denn? Denn es ist ja kein Schalter sondern ein Taster der den Reset kurz auf 1 setzt und dann soll der Prozess reagieren.
redraven
16.12.2010, 10:27
Ich stelle mir das gerade in Hardware vor. Du willst in zwei unabhängigen Prozessen durch verschiedene Aktionen die gleichzeitig ablaufen können einen Ausgang schalten. Und das mit unterschiedlichen Werten. Wer soll denn da gewinnen?
Du solltest da vielleicht mit zwei unabhängigen Variablen arbeiten und diese anschließend durch eine Logik zusammenbringen. Z.B ein Prozess setzt ein Signal und der andere setzt es zurück.
Oder du verwendest eine Art Mutex um die Variablenzuweisungen.
Im Prinzip sollte es reichen, wenn du vor dem Ändern der Variable im reset-Prozess eine Flagvariable setzt und anschließend wieder rücksetzt und im start-Prozess nur eine Änderung zuläßt, wenn das Flag nicht gesetzt ist.
Allerdings hab ich von den Möglichkeiten der VHDL Programmierung keine Ahnung. Möglicherweise gibts da ja schon fertige Konstrukte für Mutex, Semaphore und Konsorten. Sieh's also nur als Gedankenstütze.
sast
Ja ich hab auch von den Möglichkeiten nicht so die Ahnung. Bin halt ziemlich C-Verwöhnt ;)
was sagt er denn, wenn du reset:
reset_flag<=1;
z_alt<=1;
reset_flag<=0;
und start:
if (not reset_flag) then ... endif
verwendest?
sast
Hi Mark,
geht das denn? Denn es ist ja kein Schalter sondern ein Taster der den Reset kurz auf 1 setzt und dann soll der Prozess reagieren.
Ja, wieso sollte es nicht gehen. Solange reset auf 1 ist, soll sich die Schaltung im Reset-Zustand befinden, ansonsten auf die anderen Flanken reagieren.
Probiers doch einfach mal aus.
MfG Mark
Edit:
@sast
Soetwas wie
reset_flag<=1;
z_alt<=1;
reset_flag<=0;
geht in VHDL nicht. Alle <= - Zuweisungen werden gleichzeitig ausgeführt. D.h. reset_flag würde sowohl auf 1 als auch auf 0 gesetzt werden.
MfG Mark
Deshalb wars ja auch als Frage formuliert.
Klingt einleuchtend.
Wie macht man denn dann zeitlich aufeinanderfolgende Schaltungen, mit FF zum Beispiel?
sast
Sequentielle Schaltungen realisiert man meistens mit einer FSM. Sprich man hat ein Register (Signal in VHDL), welches den aktuellen Zustand speichert, und bei jeder steigenden Taktflanke wird anhand des Registerwerts (also des Zustands) und der Eingaben ein neuer Zustand berechnet und im Register gespeichert. Parallel dazu (also außerhalb des Prozesses) wird der Ausgabewert mithilfe des aktuellen Zustandes ermittelt, ggf. auch mithilfe der aktuellen Eingabe beim Mealy-Automat. Der Synthesiser wird dann schon selbst ermitteln, an welcher Stelle Flipflops nötig sind.
Die von redraven beschriebene Schaltung macht im Prinzip auch nichts anderes.
Siehe dazu auch die Artikel über Moore- und Mealy Automaten bei Wikipedia.
MfG Mark
PS: Wenn Du dich für soetwas interessierst, kann ich Dir das Buch "Digital Design and Computer Architecture" von David und Sarah Harris nur empfehlen. Das fängt quasi bei Null an und geht bis zum Entwurf eines einfachen MIPS-ähnlichen Prozessors sowie Caches und MMU. Alles ist sehr gut erklärt und zu jeder Schaltung gibt es Beispiel-Code in VHDL und Verilog.
Danke für die ausführliche Erklärung und den Tipp
sast
redraven
20.12.2010, 15:39
Du kannst auch alle drei Prozesse in einen verpacken. Dabei prüfst Du, ob Reset auf '1' steht (nicht auf rising_edge). Wenn ja, dann wird alles auf '0' gesetzt, ansonsten auf die anderen Eingaben reagiert. Also etwa so
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY auswahl IS
PORT(
rst : IN std_logic;
start : IN std_logic;
zw_zeit : IN std_logic;
enable_zaehler : OUT std_logic;
in_w_en : OUT std_logic;
up_dn_zahler : OUT std_logic
);
-- Declarations
END auswahl ;
--
ARCHITECTURE verh_auswahl OF auswahl IS
signal zw_z: std_logic := '0';
signal z_alt: integer := 1;
BEGIN
--Taster Reset Prozess
reset_proc: process(rst, zw_zeit, start)
begin
if rst = '1' then -- bei Reset auf nichts anderes reagieren
enable_zaehler <= '0';
in_w_en <= '0';
up_dn_zahler <= '1';
zw_z <= '0';
z_alt <= 1;
else -- Kein Reset
--Taster Zwischenzeit Prozess
if rising_edge (zw_zeit) then
if zw_z = '0' then
zw_z <= '1';
in_w_en <= '1';
else
in_w_en <= '0';
end if;
end if;
--Enable-Zähler-Signal Prozess
if rising_edge(start) then
if zw_z = '0' then
if z_alt = 1 then
enable_zaehler <= '1';
up_dn_zahler <= '1';
z_alt <= 2;
elsif z_alt = 2 then
enable_zaehler <= '0';
z_alt <= 3;
elsif z_alt = 3 then
enable_zaehler <= '1';
up_dn_zahler <= '0';
z_alt <= 4;
else
enable_zaehler <= '0';
z_alt <= 1;
end if;
end if;
end if;
end if;
end process;
END ARCHITECTURE verh_auswahl;
Dann hat jedes Signal genau eine Quelle.
MfG Mark
Edit: 'then' nach dem ersten if eingefügt.
Danke =) Hat funktioniert! =)
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.