In meiner Schaltung benutze ich einen RAM-Baustein, der von einem
Schreiber gefüllt und von einem Leser ausgelesen wird. Während des
Füllens darf der Leser nicht zugreifen, sonst gibt es Murks.
+---------+ +-----------+
| | | |
| RAM +---+---+ Leser |
| | | | |
+---------+ | +-----------+
| SO NICHT!
| +-----------+
| | |
+---+ Schreiber |
| |
+-----------+
Also benutze ich einen XC9572XL, der als Vermittler für den RAM-Baustein
dienen soll. (Natürlich macht der 9572 noch viel mehr.)
+---------+ +---------+ +-----------+
| | | | | |
| RAM +-------+ PROXY +-------+ Leser |
| | | (9572) | | |
+---------+ +----+----+ +-----------+
|
| +-----------+
| | |
+------------+ Schreiber |
| |
+-----------+
Das Problem ist nun, wenn ich meine Schaltung laufen lasse (also NICHT
in der Simulation), funktioniert zunächst alles wunderbar, aber jeweils
nach durchschnittlich 5-10 Minuten erhalte ich einen Lesefehler.
Hier ist die Implementierung von Lesen und Schreiben (soweit relevant):
1 | entity proxy is
|
2 | Port ( PROXY_ADDR : in std_logic_vector(7 downto 0);
|
3 | PROXY_DATA : out std_logic_vector(7 downto 0) := (others => 'Z');
|
4 | PROXY_SELECT : in std_logic; -- alle Signale active low
|
5 | PROXY_READ : in std_logic;
|
6 |
|
7 | RAM_DATA : inout std_logic_vector(7 downto 0) := (others => 'Z');
|
8 | RAM_ADDR : out std_logic_vector(15 downto 0);
|
9 | RAM_OE : out std_logic := '1';
|
10 | RAM_WR : out std_logic := '1';
|
11 |
|
12 | -- Schreiber setzt LOAD auf 0
|
13 | LOAD : in std_logic;
|
14 | LOAD_DATA : in std_logic_vector(7 downto 0);
|
15 | LOAD_WE : in std_logic );
|
16 | end logic;
|
17 |
|
18 | architecture Behavioral of proxy is
|
19 | signal load_addr : std_logic_vector(15 downto 0);
|
20 | begin
|
21 |
|
22 | RAM_ADDR <= load_addr when LOAD = '0' else
|
23 | "00110000" & PROXY_ADDR when PROXY_SEL = '0' else
|
24 | (others => '-');
|
25 |
|
26 | with LOAD select
|
27 | RAM_DATA <= LOAD_DATA when '0',
|
28 | (others => 'Z') when others;
|
29 |
|
30 | RAM_OE <= '1' when LOAD = '0' else
|
31 | '0' when PROXY_SEL = '0' else
|
32 | '1';
|
33 |
|
34 | with LOAD select
|
35 | RAM_WE <= LOAD_WE when '0',
|
36 | '1' when others;
|
37 |
|
38 | PROXY_DATA <= RAM_DATA when LOAD = '1' and PROXY_SEL = '0' and
|
39 | PROXY_READ = '0' else
|
40 | (others => 'Z');
|
41 |
|
42 | RAMLOAD: process(...)
|
43 | begin
|
44 | -- Schreiblogik ...
|
45 | end process;
|
46 |
|
47 | end Behavioral;
|
Der Schreiber setzt zu Beginn LOAD auf 0 und füllt das RAM. Nach einer
Sekunde geht LOAD auf 1 und ändert sich nicht mehr. Das funktioniert
problemlos.
Der Leser legt pro Lesevorgang PROXY_ADDR an und setzt PROXY_SEL auf 0.
Nach kurzer Zeit geht dann auch PROXY_READ auf 0, und die Daten werden
gelesen. Danach geht erst PROXY_READ und dann PROXY_SEL auf 1.
Ich freue mich, daß noch jemand bis hierhin mitgelesen hat. :-) Aber hat
der- oder diejenige auch eine Idee, was diese sporadischen Lesefehler
verursachen kann? Selbst wenn der Code wie oben reduziert ist, treten
sie auf.
Ich selbst habe nur zwei Theorien, die aber für mich unwahrscheinlich
klingen.
(1) Irgendeines der Signal kommt zu früh/zu spät an, bevor sich alles
stabilisieren kann. Ich wüßte nur nicht, welches Signal das sein sollte.
Die Bedingungen von RAM_ADDR und RAM_OE erfüllen sich früher, damit sich
das RAM stabilisieren kann.
(2) Die Signale kommen nicht rechtzeitig an. Es dauert einige Zeit, bis
sich die Leseanforderung zum RAM und wieder zurück gekämpft hat. Aber
PROXY_READ ist ca. 500 ns auf 0, was doch ausreichen sollte?!
Ich bin noch ein ziemlicher VHDL-Anfänger und arbeite schon zwei Wochen
an dem Problem, aber ohne Ideen komme ich hier nicht mehr weiter.