PDA

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

dremler
15.12.2010, 17:59
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;

sast
16.12.2010, 09:11
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

p_mork
16.12.2010, 09:36
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 ;)

sast
16.12.2010, 11:18
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

p_mork
16.12.2010, 12:37
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

sast
16.12.2010, 13:16
Deshalb wars ja auch als Frage formuliert.
Klingt einleuchtend.
Wie macht man denn dann zeitlich aufeinanderfolgende Schaltungen, mit FF zum Beispiel?

sast

p_mork
16.12.2010, 18:50
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.

sast
17.12.2010, 08:24
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! =)