Hallo,
ich baue grade an einer Statemachine, die ein HD44780 Display ansteuert.
Da das jetzt funktioniert, bin ich dabei das ganze etwas zu optimieren.
Bisher warte ich nach jedem Befehl 40us, auch wenn der Befehl gar nicht
so lange braucht.
Deswegen wollte ich das Busyflag checken und so etwas Zeit sparen.
Es gibt allerdings keine einzelne Busy-Leitung, sondern man muss die
Read-Leitung auf High ziehen und dann das oberste Bit des Datenbusses
betrachten.
Ich hab also etwas gegooglet, wie man einen solchen Bidirektionalen Bus
behandelt.
Leider funktioniert es in der Simulation nicht wirklich. Anstatt das der
Augang komplett Low ist, ist der undefined.
Ich habe mal einen kleinen Test implementiert.
Als erstes geht oe auf High, schaltet damit den Bus auf Ausgang und lege
Daten an den Bus. Der Bus ist undefined. Wie? Watt?
Dann gehe ich in den Wartezustand, der nichts macht und plötzlich,
mittendrin, wird der Bus XXXXXXXX. Hä?
Das lesen geht dann anschließend wieder, wenn ich dann Daten extern
anlege und oe auf low ziehe.
Kann mir das jemand erklären?
Und dann noch was:
Kann man sich so auch Kürzschlüsse bauen und den FPGA kaputt machen?
Angenommen ich lege ne 0 an eine Leitung und zur selben Zeit legt die
andere Seite eine 1 auf die Leitung. Geht da was kaputt?
1 | library IEEE;
|
2 | use IEEE.STD_LOGIC_1164.ALL;
|
3 | use IEEE.STD_LOGIC_ARITH.ALL;
|
4 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
5 |
|
6 | entity bidir_bus is
|
7 | Port ( data : inout STD_LOGIC_VECTOR (7 downto 0);
|
8 | clk : in STD_LOGIC;
|
9 | reset : in STD_LOGIC;
|
10 | data_read : out STD_LOGIC_VECTOR (7 downto 0));
|
11 | end bidir_bus;
|
12 |
|
13 | architecture Behavioral of bidir_bus is
|
14 | signal data_in : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
|
15 | signal data_out : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
|
16 | signal oe : std_logic := '1';
|
17 |
|
18 | signal i : integer range 0 to 80000 := 0;
|
19 |
|
20 | type state_sequence is (
|
21 | start, write_data, wait1, read_data, done
|
22 | );
|
23 | signal state : state_sequence := start;
|
24 | begin
|
25 | data_in <= data;
|
26 | data <= data_out when oe = '1' else (others => 'Z');
|
27 |
|
28 | doStuff: process(clk, reset)
|
29 | begin
|
30 | if reset = '1' then
|
31 | oe <= '1';
|
32 | data_out <= (others => '0');
|
33 | state <= start;
|
34 | elsif rising_edge(clk) then
|
35 | case state is
|
36 | when start =>
|
37 | state <= write_data;
|
38 |
|
39 | when write_data =>
|
40 | oe <= '1';
|
41 | data_out <= x"55";
|
42 | state <= wait1;
|
43 |
|
44 | when wait1 =>
|
45 | if i = 80000 then
|
46 | i <= 0;
|
47 | oe <= '0'; --prepare for input
|
48 | state <= read_data;
|
49 | else
|
50 | i <= i + 1;
|
51 | state <= wait1;
|
52 | end if;
|
53 |
|
54 | when read_data =>
|
55 | data_read <= data;
|
56 | state <= done;
|
57 |
|
58 | when done =>
|
59 | state <= done;
|
60 | end case;
|
61 | end if;
|
62 | end process;
|
63 |
|
64 | end Behavioral;
|
edit:
OK. Bin ein Stück weiter.
Die Xe in ISim meinen wohl tatsächlich Kurzschluss. Denn immer genau die
Bits sind mit X markiert, bei denen auf der einen Seite eine 1 und auf
der anderen eine 0 steht. Ich hab das jetzt mal nicht unbedingt auf dem
FPGA selber testen wollen ;)
Alledings wirft das dann noch ne Frage auf.
Ich muss also unbedingt vorher, bevor die Gegenstelle meint senden zu
wollen unbedingt auf Z schalten, weil das sonst mächtig warm werden
könnte?
Ich bastel mal etwas weiter...