Forum: FPGA, VHDL & Co. [VHDL] FSM springt in states ohne trigger


von Steffen Kern (Gast)


Lesenswert?

Einen guten Morgen miteinander,

ich habe eine FSM in VHDL, die nacheinander states abarbeiten soll.

Die Ports start, reset und push_button2 sind jeweils push_buttons mit 
debounce.
Nachdem ein Reset ausgeführt wurde, sollte die State-Machine eigentlich 
in den IDLE-state springen und im ready_state "00" verweilen, bis 
entweder start <= '1' gesetzt wird durch einen Pushbutton oder ein Reset 
kommt per Pushbutton.

Nach dem Reset springt die FSM direkt in den SENDING_ADDRESS_BITS-state.

Irgendjemand eine Idee warum?

Wenn ich den SENDING_ADDRESS_BITS-state auskommentiere und nur im 
IDLE-state verweile, funktioniert alles wunderbar.

Gruß,
Steffen

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity spi_transceiver is
5
    Port (
6
        SCLK_IN             : in  STD_LOGIC;                            -- Base frequency clock. 
7
    
8
        SCLK                : out STD_LOGIC;                           -- Master Clock for SPI-Slave.
9
        CSB                 : out STD_LOGIC;                            -- Chip select to enable/disable data transfers.
10
        SDI                 : out STD_LOGIC;                            -- Serial data stream to DAC SPI-Interface.
11
        SDO                 : in  STD_LOGIC;                            -- Serial data stream from DAC SPI-Interface
12
13
        start               : in  STD_LOGIC;                            -- Start tx/rx process.
14
        reset               : in  STD_LOGIC;                            -- Reset to default state.
15
        done                : out STD_LOGIC;                            -- Status bit to indicate end of tx/rx process.
16
17
        tx_address_vector   : in  STD_LOGIC_VECTOR (11 downto 0);       -- Address vector inluding R/W-Bit.
18
        tx_data_vector      : in  STD_LOGIC_VECTOR (7 downto 0);        -- Data vector to send to DAC-SPI.
19
        rx_data_vector      : out STD_LOGIC_VECTOR (7 downto 0);        -- Received data from SPI-slave.
20
        
21
        test_led0               : out STD_LOGIC;        -- LED for indicating successfull write and read operation.
22
        test_led1               : out STD_LOGIC;
23
        test_led2               : out STD_LOGIC;
24
        test_led3               : out STD_LOGIC;
25
        push_button2            : in  STD_LOGIC
26
        
27
    );
28
end spi_transceiver;
29
30
architecture Behavioral of spi_transceiver is
31
32
    signal SPI_counter  : integer range 0 to 43 := 0;
33
    signal SPI_enable   : std_logic := '0';
34
    
35
    type state is (IDLE, SENDING_ADDRESS_BITS);
36
    signal sig_state    : state := IDLE;
37
    
38
    -- Debug-signals
39
    signal tmp_test_led0        : std_logic := '0';
40
    signal tmp_test_led1        : std_logic := '0';
41
    signal tmp_test_led2        : std_logic := '0';
42
    signal tmp_test_led3        : std_logic := '0';
43
    signal ready_state          : std_logic_vector(1 downto 0) := (others => '0');
44
45
begin
46
47
    test_led0   <= tmp_test_led0;
48
    test_led1   <= tmp_test_led1;
49
    test_led2   <= tmp_test_led2;
50
    test_led3   <= tmp_test_led3;
51
    ready_state <= start & SPI_enable;
52
53
    process(SCLK_IN)
54
    begin
55
    
56
        -- Connect output SCLK synchronously to SCLK_IN
57
        SCLK <= SCLK_IN;
58
        
59
        -- Reset logic
60
        if(reset = '1') then
61
            CSB             <= '1';                     -- Make SPI closed to communication.
62
            done            <= '0';
63
            SDI             <= '0';
64
            
65
            SPI_counter     <= 0;
66
            SPI_enable      <= '0';
67
            sig_state       <= IDLE;
68
            
69
            tmp_test_led0 <= '1';
70
            tmp_test_led1 <= '0';
71
            tmp_test_led2 <= '0';
72
            tmp_test_led3 <= '0';
73
74
        else
75
        
76
            case sig_state is
77
                when IDLE =>
78
                        -- ready_state <= start & SPI_enable;
79
                        case ready_state is
80
                            when "00" =>    -- NOT RESET, NOT STARTED YET = IDLE - DEBUG-LEDs: 0010
81
                                    tmp_test_led0 <= '0';
82
                                    tmp_test_led1 <= '0';
83
                                    tmp_test_led2 <= '1';
84
                                    tmp_test_led3 <= '0';
85
                            when "01" =>    -- ERROR-STATE - DEBUG-LEDs: 1010
86
                                    tmp_test_led0 <= '1';
87
                                    tmp_test_led1 <= '0';
88
                                    tmp_test_led2 <= '1';
89
                                    tmp_test_led3 <= '0';
90
                                    
91
                            when "10" =>    -- Enable tx/rx-process - DEBUG-LEDs: 0100
92
                                    SPI_counter     <= 0;
93
                                    SPI_enable      <= '1';                     -- Start the tx/rx-process.
94
                                    sig_state       <= SENDING_ADDRESS_BITS;    -- Address-Bits-Transmission is always the first thing to do.
95
96
                                    tmp_test_led0 <= '0';
97
                                    tmp_test_led1 <= '1';
98
                                    tmp_test_led2 <= '0';
99
                                    tmp_test_led3 <= '0';
100
                                                        
101
                            when "11" =>    -- ERROR-STATE - DEBUG-LEDs: 1100
102
                                    tmp_test_led0 <= '1';
103
                                    tmp_test_led1 <= '1';
104
                                    tmp_test_led2 <= '0';
105
                                    tmp_test_led3 <= '0';
106
                                    
107
                            when others =>  -- ERROR-STATE
108
109
                        end case; -- ready_state
110
111
                when SENDING_ADDRESS_BITS =>
112
                
113
                        if(push_button2 = '1') then
114
                            sig_state <= IDLE;
115
                        end if;
116
                        -- DEBUG: 0110
117
                        tmp_test_led0 <= '0';
118
                        tmp_test_led1 <= '1';
119
                        tmp_test_led2 <= '1';
120
                        tmp_test_led3 <= '0';
121
                
122
                when others =>
123
                        -- It should not occur to come into this state here.
124
                        sig_state   <= IDLE;
125
                        SDI         <= '0';
126
                        SPI_enable  <= '0';
127
                        
128
                        -- DEBUG: 0101
129
                        tmp_test_led0 <= '0';
130
                        tmp_test_led1 <= '1';
131
                        tmp_test_led2 <= '0';
132
                        tmp_test_led3 <= '1';
133
            end case;
134
            
135
        end if; --RESET
136
    
137
    end process;
138
139
end Behavioral;

: Verschoben durch Moderator
von Alexander F. (alexf91)


Lesenswert?

Hast du das Design simuliert oder direkt in der Hardware getestet?

Mir fällt nämlich auf, dass du keinen Takt im Design hast.
Es reicht nicht, SCLK_IN in die Sensitivity-List zu schreiben, das ist 
nur für die Simulation relevant.

von Steffen Kern (Gast)


Lesenswert?

Beides.
Kannst du das mit dem Takt etwas genuer erklären, oder Referenzen dazu 
aufführen?

von Steffen Kern (Gast)


Lesenswert?

Hmm... meinst du vielleicht, dass ich innerhalb meines processes noch 
ein rising_edge(clk_SCLK) bräuchte oder clk_SCLK'event AND clk_SCLK = 
'1', je nachdem was man präferiert.

von Steffen Kern (Gast)


Lesenswert?

Ich habe im Internet noch etwas rumgesucht und bin selbst auf die Lösung 
gekommen.
Die Sensitivity List ist wirklich rein für Simulation gedacht.
D.h. mein process wurde kombinatorisch synthetisiert.
Wenn man einen process taktsynchron haben will, brauch man immer die 
rising/falling_edge außerhalb seiner Verarbeitungslogik.

von Bronco (Gast)


Lesenswert?

Wenn Du planst, dies in einem FPGA zu realisieren, solltest Du unbedingt 
einen Takt verwenden. Idealerweise einen einzigen Takt für die gesamte 
Logik.
Mit Takt meine ich nicht so etwas wie das SCKL-Signal des SPI, sondern 
einen "Systemtakt", der idealerweise deutlich schneller ist, als alle 
vom FPGA zu verarbeitenden I/O-Signale.
Der SPI-Takt würde dann zu einem weiteren I/O-Signal "degradiert".

Die Taktung ist notwendig, um die unterschiedlichen Laufzeiten der 
internen Signale zu synchronisieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.