Hi ich hab hier einen kleinen FPGA (LatticeMACHXO) an einem Adress/Datenbus. Im FPGA sind eine paar Register die über den Datenbus gelesen und beschrieben werden können. Ein gemeinsamer Takt steht nicht zur Verfügung. Der Takt des FPGAs ist aber so hoch das ich mindestens eine (evtl. mehr) Flanken während der Low-Zeit des WR-Signals habe. Das Ganze sieht (vereinfacht) zur Zeit etwa so aus:
1 | library ieee; |
2 | use ieee.std_logic_1164.all; |
3 | use ieee.numeric_std.all; |
4 | |
5 | entity slave is |
6 | |
7 | port( |
8 | -- data bus from host
|
9 | DATA: inout std_logic_vector(15 downto 0); |
10 | ADR: in std_logic_vector(5 downto 1); |
11 | RD: in std_logic; |
12 | WR: in std_logic; |
13 | CS: in std_logic; |
14 | |
15 | -- system interface
|
16 | RST: in std_logic; -- Global system reset |
17 | CLK: in std_logic; -- 25MHz clock |
18 | |
19 | );
|
20 | end; |
21 | |
22 | architecture behavior of slave is |
23 | |
24 | -- internal mapping register of direct inputs
|
25 | signal gpio_out : std_logic_vector(15 downto 0); |
26 | |
27 | -- internal spi related register
|
28 | signal spi_reg_out : std_logic_vector(0 to 15); |
29 | |
30 | begin
|
31 | |
32 | ----------------------------------------------------------------------------
|
33 | -- clock synchronous stuff for SPI and data bus connection
|
34 | process (CLK, RST, WR) |
35 | begin
|
36 | if RST = '0' then |
37 | |
38 | spi_reg_out <= (others => '0'); |
39 | gpio_out <= (others => '0'); |
40 | |
41 | elsif falling_edge(CLK) then |
42 | |
43 | if CS = '0' and WR = '0' then |
44 | |
45 | if ADR = "10000" then -- write to 16 (spi output) |
46 | spi_reg_out <= DATA; |
47 | elsif ADR = "10010" then -- write to 18 (gpio output) |
48 | gpio_out <= DATA; |
49 | end if; |
50 | |
51 | elsif cs_int = '1' then |
52 | |
53 | --SPI state machine
|
54 | -- some code here
|
55 | |
56 | end if; |
57 | |
58 | end if; |
59 | end process; |
60 | |
61 | end behavior; |
Leider hab ich damit ab und an (bei rund 1% der Zugriffe) falsche Daten im FPGA. Wie macht man sowas den richtig? Ich würde die Daten ja mit der steigenden Flanke von WR übernehmen wenn CS = '0'. Aber dann hab ich zwei asynchrone Takte im System was die Sache auch nicht wirklich vereinfacht. Ich bin leider nicht so der VHDL Experte. Matthias