Hallo,
ich versuche gerade einen bidirektionalen I/O zu realisieren (es geht
letztlich um 1-wire), jedoch macht VHDL nicht so wie ich will ;)
Hier die Kurzfassung meines Codes:
1
entitiy onewirebit is
2
port(
3
CLK : in bit;
4
dq : inout std_logic;
5
invalue : out bit;
6
-- ...
7
);
8
end onewirebit;
9
10
architecture Behavioral of onewirebit is
11
signal dq_outvalue : bit;
12
signal dq_invalue : bit;
13
-- ...
14
begin
15
process(CLK)
16
begin
17
if CLK='1' and CLK'event then
18
-- ...
19
invalue <= dq_invalue;
20
-- ...
21
end if;
22
end process;
23
24
process(dq_outvalue, dq)
25
begin
26
if dq_outvalue = '1' then
27
dq <= 'Z';
28
else
29
dq <= '0';
30
end if;
31
if dq='0' then
32
dq_invalue <= '0';
33
else
34
dq_invalue <= '1';
35
end if;
36
end process;
37
end Behavioral;
So, hoffe das ist einigermaßen verständlich. Im synchronen Teil setze
ich mit dq_outvalue ob der Pin hochohmig oder Low sein soll, das
funktioniert auch soweit. Jetzt hätte ich gerne in dq_value den
aktuellen Wert des Busses, egal ob ich den nun nach Masse ziehe oder
nicht.
Zwei Probleme: Auf was steht dq jeweils? Und warum bekomme ich im Moment
diese Warnung?
1
WARNING:Xst:1710 - FF/Latch <invalue> (without init value) has a constant value of 0 in block <onewirebit>.
2
This FF/Latch will be trimmed during the optimization process.
3
WARNING:Xst:1348 - Unit onewirebit is merged (output interface has tristates)
Fabian S. schrieb:> CLK : in bit;> dq : inout std_logic;> invalue : out bit;
Wieso denn der Mischbetrieb?
Verwende doch einfach wie der Rest der Welt nur std_logic und dessen
Vektoren...
Nehmen wir mal deine Beschreibung
1
process(dq_outvalue,dq)
2
begin
3
ifdq_outvalue='1'then
4
dq<='Z';
5
else
6
dq<='0';
7
endif;
8
ifdq='0'then
9
dq_invalue<='0';
10
else
11
dq_invalue<='1';
12
endif;
13
endprocess;
und machen eine funktionsgleiche Umstellung
1
dq<='Z'whendq_outvalue='1'else'0';
2
dq_invalue<='0'whendq='0'else'1';
du hast da m.E. eine Macke in der Umschaltung...
Ein bidirektionaler Pin hat 3 Signale:
Eingangswert, Ausgangswert und Richtung.
Dir fehlt eines davon... :-o
Das wäre ein Tristate-Port:
1
:
2
dq:inoutstd_logic;
3
:
4
signaldq_outvalue:std_logic;
5
signaldq_invalue:std_logic;
6
signaldq_dir:std_logic;
7
:
8
dq<=dq_outvaluewhendq_dir='1'else'Z';
9
dq_invalue<=dq;
10
:
Und jetzt kannst du mit dq_outvalue und dq_invalue arbeiten...
Gegenfrage: Was für ein Mischbetrieb?
invalue hat jetzt damit direkt erstmal nichts zu tun, dass ist nur ein
"Rückgabewert" an die höher gestellte entity.
Und warum sollte ich nen vollen Tri-State Pin definieren wenn ich davon
nur die hälfte brauche? Der soll ja als Open-Drain arbeiten. Also
brauche ich Z, 0 und Eingang.
Und es bleibt die Frage: Wenn dq auf 'Z' steht und ich lese dq, was
kommt dann da raus? 1 und 0? H und L? Z? Oder was? Und was kommt da raus
wenn ich dq auf 0 stehen habe?
Edit: Wenn ich das verwende:
1
dq <= 'Z' when dq_outvalue='1' else '0';
Bekomme ich diesen Fehler:
1
Line 102. parse error, unexpected WHEN, expecting SEMICOLON
Fabian S. schrieb:> Gegenfrage: Was für ein Mischbetrieb?bit und std_logic
Wie ich schon im
Lothar Miller schrieb:>> Verwende doch einfach wie der Rest der Welt nur std_logic und dessen>> Vektoren...Fabian S. schrieb:> Und warum sollte ich nen vollen Tri-State Pin definieren wenn ich davon> nur die hälfte brauche? Der soll ja als Open-Drain arbeiten. Also> brauche ich Z, 0 und Eingang.
Also, das ist ja nicht schwierig, das hattest du tatsächlich schon...
Ich würde allerdings die dominante '0' vorrangig beschreiben:
1
:
2
dq:inoutstd_logic;
3
:
4
signaldq_outvalue:std_logic;
5
signaldq_invalue:std_logic;
6
:
7
dq<='0'whendq_outvalue='0'else'Z';
8
dq_invalue<=dq;
9
:
Damit ist es wie so oft:
Das Problem liegt offenbar nicht im geposteten Code...
Fabian S. schrieb:> Und es bleibt die Frage:> Wenn dq auf 'Z' steht und ich lese dq, was kommt dann da raus?
Das, was jemand anders von aussen auf das Signal treibt.
Wenn keiner was treibt, dann 'Z'.
EDIT:
Fabian S. schrieb:> Edit: Wenn ich das verwende:
Das ist ein Concurrent Statement.
Das geht nur ausserhalb eines Prozesses.
> Lothar Miller schrieb:>>> Verwende doch einfach wie der Rest der Welt nur std_logic und dessen>>> Vektoren...
Aso, ne das kann ich nicht machen, unserem Prof ist das sehr wichtig,
dass überall da wo es geht nur bit verwendet wird weil das seiner
Meinung nach schneller ist und weniger Fehler verursacht. Also da komme
ich nicht drum rum.
> Also, das ist ja nicht schwierig, das hattest du tatsächlich schon...
Das das nicht schwierig ist steht hier nicht zur Debatte, warum geht es
nicht anders?
> Damit ist es wie so oft:> Das Problem liegt offenbar nicht im geposteten Code...
Das habe ich eben auch festgestellt. Hier nochmal der aktuelle komplette
Code:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.all;
3
useIEEE.STD_LOGIC_ARITH.all;
4
useieee.numeric_std.all;
5
useIEEE.STD_LOGIC_UNSIGNED.ALL;
6
7
--
8
-- onewirebit
9
-- onewirebit is the implementation of the lowest protocol
10
-- layer, the bit layer. This entity is able to send bit to
11
-- the bus and receive bity from the bus.
12
--
13
14
entityonewirebitis
15
port(
16
CLK:inbit;-- system clock
17
dq:inoutstd_logic;-- route this to the physical pin connected to the onewire bus
18
reset:inbit;-- set this bit to '1' to send a reset condition, if a slave is present invalue will be set to '1', otherwise to '0'
19
writing:inbit;-- set this bit to '1' to start write process, one clock later clear this bit, after that for finished becoming '1'
20
outvalue:inbit;-- set this bit to the value to be written to the bus. Do not change this value while the entity is writing this value!
21
readbit:inbit;-- set this bit to '1' to read a bit from the bus
22
invalue:outbit;-- after finishing the readbit command, the readed value can be read here. Alternative it is used for the return value of reset.
23
finished:outbit-- after setting writing or readbit to '1' wait after one cycle for this bit to become '1' again
> Das, was jemand anders von aussen auf das Signal treibt.> Wenn keiner was treibt, dann 'Z'.
Ähhh aber der kann wohl kaum zwischen einem Pull-Up und einem High
Strong Drive unterscheiden? Also lese ich dort IMMER 0, 1 oder Z? Aber
woher soll er erkennen ob das Z ist? Irgend ein Pegel wird das Signal ja
immer haben...
Edit: Ups, vergessen... Es bestehen weiterhin folgende Warnungen:
1
WARNING:Xst:1710 - FF/Latch <invalue> (without init value) has a constant value of 0 in block <onewirebit>. This FF/Latch will be trimmed during the optimization process.
2
WARNING:Xst:1348 - Unit onewirebit is merged (output interface has tristates)
Fabian S. schrieb:> unserem Prof ist das sehr wichtig,
Und auf keinen Fall zuviele Kommentare, weil: die machen den Code so
langsam... :-/
> weil das seiner Meinung nach schneller ist
Lasst euch das mal beweisen...
> und weniger Fehler verursacht
Die Fehler passieren woanders!
> unserem Prof ist das sehr wichtig,> signal timer : std_logic_vector (31 downto 0) := (others=>'0');
DAS nenne ich mal konsequent!!!
Warum machst du dann nicht deinen Zähler wenigstens als unsigned
Vektor?
Oder als Integer?
Ach: zum Rechnen dürft ihr die alten Synopsys-Libs und
uneingeschränkte Vektoren verwenden... :-o
> Aber woher soll er erkennen ob das Z ist?> Irgend ein Pegel wird das Signal ja immer haben...
In der Hardware schon. Aber nicht im Simulator.
> use IEEE.STD_LOGIC_ARITH.all;> use IEEE.STD_LOGIC_UNSIGNED.ALL;> use ieee.numeric_std.all;Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete">>> WARNING:Xst:1710 - FF/Latch <invalue> has a constant value ...
Was macht denn deine Simulation?
Kommst du je in den Zustand state_reset1 ?
Lothar Miller schrieb:> Die Fehler passieren woanders!
Das brauchst du mir nicht zu sagen...
>> unserem Prof ist das sehr wichtig,>> signal timer : std_logic_vector (31 downto 0) := (others=>'0');> DAS nenne ich mal konsequent!!!> Warum machst du dann nicht deinen Zähler wenigstens als /unsigned/> Vektor?> Oder als Integer?> Ach: zum Rechnen dürft ihr die alten Synopsys-Libs und> uneingeschränkte Vektoren verwenden... :-o
Keine Ahnung, kenne das nur so und das hat bislang immer gut
funktioniert.
>> Aber woher soll er erkennen ob das Z ist?>> Irgend ein Pegel wird das Signal ja immer haben...> In der Hardware schon. Aber nicht im Simulator.
Das ist wohl eher umgekehrt, erklär mir mal bitte woher die Hardware
erkennen soll ob da am Ende nen Pull-Up oder nen Strong-Drive drin
ist...
>>> use IEEE.STD_LOGIC_ARITH.all;>> use IEEE.STD_LOGIC_UNSIGNED.ALL;>> use ieee.numeric_std.all;> Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"
Aha, werde ich mir mal reinziehen, soblad diese Probleme hier gelöst
sind...
>>>> WARNING:Xst:1710 - FF/Latch <invalue> has a constant value ...> Was macht denn deine Simulation?> Kommst du je in den Zustand state_reset1 ?
Keine Ahnung. Ich habe noch keinen Simulator zum laufen bekommen unter
Linux. Ich teste das hier alles auf echter Hardware...
Soooo, einen Fehler habe ich gefunden. Der Zustand state_reset1 wurde
tatsächlich nie erreicht, hätte jedoch nicht gedacht, dass das Teil so
intelligent ist, weil die Entscheidung das bit zu setzen oder nicht
fällt einige Ebenen weiter oben :D Wenn ich es da setze ist die Meldung
weg.
Bleibt nur noch die eine Warnung:
1
Unit onewirebit is merged (output interface has tristates)
Jemand eine Idee?
Ich habe IRGENDWO im Netz gelesen, dass das unwichtig ist und man es
igorieren kann, dann frage ich mich aber warum es dann ein Warning und
kein Note oder sowas ist :-/
Und es bleibt noch die Frage was ich aus dem dq auslese wenn ich es lese
je nachdem was für ein Zustand vorhanden ist.
Fabian S. schrieb:>>> Aber woher soll er erkennen ob das Z ist?>>> Irgend ein Pegel wird das Signal ja immer haben...>> In der Hardware schon. Aber nicht im Simulator.> Das ist wohl eher umgekehrt...
Die Hardware wird immer entweder '0' oder '1' erkennen. Der Simulator
kennt auch 'Z' (und die anderen Zustände von std_logic).
Wunderbar, ich denke dann sind auch alle Fragen geklärt bis auf das
1
Unit onewirebit is merged (output interface has tristates)
Aber das ignoriere ich nun erstmal getrost und werde kommenden Montag
meinen Prof dazu ausquetschen :D
Ich habe nun für die Zähler/Timer ein integer genommen, ist das besser?
:D
Fabian S. schrieb:> Ich habe nun für die Zähler/Timer ein integer genommen, ist das besser?
Ja, es ist schlüssiger. Wie gesagt: Mit Verktoren rechnet man nicht.
Wofür wurden sonst die anderen Datentypen erfunden. Also: nur die
numeric_std statt der std_logic_arith+std_logic_unsigned!
Und frag mal deinen Prof, wofür man denn die signed und unsigned
Vektoren brauchen kann, wenn es doch die integer gibt... ;-)