Forum: FPGA, VHDL & Co. Probleme mit Statemachine


von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
entweder es is schon zu spät oder ich werde bekloppt.
Habe bis jetz meines Erachtens immer so eine StateMachine kodiert, die 
auch immer funktionierte.
Mein Problem ist folgendes:
Das busy-signal wird richtig gesetzt, aber der state wird nicht sofort 
gewechselt. z.b Zeitpunkt 50ms müsste state in work gehen und nicht erst 
bei 70ms...
Was übersehe ich da gerade?
Gruß
Chris
1
architecture Behavioral of wishbone_master is
2
  
3
  type state_type is (IDLE, WORK);
4
  signal state, state_next: state_type;
5
  signal tmp_busy  : STD_LOGIC;
6
  signal tmp_dat_o : STD_LOGIC_VECTOR(31 downto 0);
7
  signal tmp_adr_o : STD_LOGIC_VECTOR(10 downto 0);
8
  signal tmp_dat_i : STD_LOGIC_VECTOR(31 downto 0);
9
  signal tmp_we_o  : STD_LOGIC;
10
  
11
begin
12
  
13
  busy  <= tmp_busy;
14
  dat_o <= tmp_dat_o;
15
  adr_o <= tmp_adr_o;
16
  rd    <= tmp_dat_i;
17
  we_o  <= tmp_we_o;
18
  
19
  process(clk)
20
  begin
21
    if rising_edge(clk) then
22
      if rst = '1' then
23
        state <= idle;
24
      else
25
        state <= state_next;
26
      end if;
27
    end if;
28
  end process;
29
  
30
  process(state,cmd,ack_i)
31
  begin
32
    
33
    state_next <= state;
34
    tmp_busy   <= '0';
35
    tmp_we_o   <= '0';
36
    stb_o      <= '0';
37
    
38
    case state is
39
      when IDLE =>
40
        state_next <= IDLE;
41
        if cmd(0) = '1'  then  -- 0|1 lesen 1|1 schreiben
42
          state_next <= WORK;
43
          tmp_busy <= '1';
44
          tmp_we_o <= cmd(1);
45
          stb_o <= '1';
46
          cyc_o <= '1';
47
          tmp_dat_o <= wd;
48
          tmp_adr_o <= a(10 downto 0);
49
          tmp_dat_i <= dat_i;
50
        end if;
51
      
52
      when WORK =>
53
        state_next <= WORK;
54
        tmp_busy <= '1';
55
        stb_o <= '1';
56
        cyc_o <= '1';
57
        tmp_dat_o <= wd;
58
        tmp_adr_o <= a(10 downto 0);
59
        tmp_dat_i <= dat_i;
60
        
61
        if ack_i = '1' then
62
          state_next <= IDLE;
63
          tmp_busy <= '0';
64
          stb_o <= '0';
65
          cyc_o <= '0';
66
        end if;
67
    end case;
68
    
69
  end process;
70
  
71
end Behavioral;

von Leonard Lebewohl (Gast)


Lesenswert?

Chris schrieb:

Ohne zeiten für den takt oder simu-waveform fällt es schwer denn problem 
zu versetehen. Mit fällt nur auf das tmp_busy ungetaktet ist und state 
getaktet (so wie es sein soll). Daraus folgt das sich zuers tmp_busy 
ändert und dann state zu WORK wechselt. Vielleicht liegt das problem 
auch an dem taktteiler, 50 Milisekunden sind nicht gerade typisch für 
einen takt. Taktet deine statemachine wirklich im kHz - Bereich ?!.

MfG,


> Hallo,
> entweder es is schon zu spät oder ich werde bekloppt.
> Habe bis jetz meines Erachtens immer so eine StateMachine kodiert, die
> auch immer funktionierte.
> Mein Problem ist folgendes:
> Das busy-signal wird richtig gesetzt, aber der state wird nicht sofort
> gewechselt. z.b Zeitpunkt 50ms müsste state in work gehen und nicht erst
> bei 70ms...

von Leonard Lebewohl (Gast)


Lesenswert?

Vielleicht hält der rst den statemachine im IDLE?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Leonard Lebewohl schrieb:
> Mit fällt nur auf das tmp_busy ungetaktet ist und state getaktet (so
> wie es sein soll).
Mir fällt auf, dass in der Sensitivliste des kombinatorischen Prozesses 
fast alle nötigen Signale (dat_i, a und wd) fehlen...

Chris schrieb:
> Das busy-signal wird richtig gesetzt, aber der state wird nicht sofort
> gewechselt.
Ja nun, das busy Signal ist ja auch kombinatorisch, der State getaktet. 
Wie sieht das denn mit dem Zeitbezug zwischen state_next und (tmp_)busy 
aus? Kommen die gelichzeitig?

Was ist das für eine angehängte Datei namens "plot"? Mach doch einfach 
Screenshots im png oder gif Format...

: Bearbeitet durch Moderator
von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
sorry die plot datei stellt die simulations datei dar. irgendwie hatte 
die keine endung.... sollte jetzt klappen.
Ist das nicht egal mit welchem takt ich das takte? zur einfachen und 
schnelleren simulation habe ich einfach 20 ms als periode angenommen, 
hier meine testbench:
1
--------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer:
4
--
5
-- Create Date:   14:09:08 11/11/2013
6
-- Design Name:   
7
-- Module Name:   /home/kppe13d/Komplexprakitkum/brutal-pineapple/MIPS/data_memory_tb.vhd
8
-- Project Name:  MIPS_Proc
9
-- Target Device:  
10
-- Tool versions:  
11
-- Description:   
12
-- 
13
-- VHDL Test Bench Created by ISE for module: data_memory
14
-- 
15
-- Dependencies:
16
-- 
17
-- Revision:
18
-- Revision 0.01 - File Created
19
-- Additional Comments:
20
--
21
-- Notes: 
22
-- This testbench has been automatically generated using types std_logic and
23
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends
24
-- that these types always be used for the top-level I/O of a design in order
25
-- to guarantee that the testbench will bind correctly to the post-implementation 
26
-- simulation model.
27
--------------------------------------------------------------------------------
28
LIBRARY ieee;
29
USE ieee.std_logic_1164.ALL;
30
use work.mips_constants.all;
31
 
32
-- Uncomment the following library declaration if using
33
-- arithmetic functions with Signed or Unsigned values
34
--USE ieee.numeric_std.ALL;
35
 
36
ENTITY data_memory_tb IS
37
END data_memory_tb;
38
 
39
ARCHITECTURE behavior OF data_memory_tb IS 
40
 
41
    -- Component Declaration for the Unit Under Test (UUT)
42
 
43
    COMPONENT data_memory
44
    PORT(
45
      clk  : in STD_LOGIC;
46
      rst  : in STD_LOGIC;
47
      cmd  : in STD_LOGIC_VECTOR(1 downto 0);
48
      wd   : in STD_LOGIC_VECTOR(31 downto 0);
49
      a    : in STD_LOGIC_VECTOR(31 downto 0);
50
      rd   : out STD_LOGIC_VECTOR(31 downto 0);
51
      busy : out STD_LOGIC
52
        );
53
    END COMPONENT;
54
    
55
56
   --Inputs
57
      signal clk : STD_LOGIC :='0';
58
      signal rst : STD_LOGIC :='0';
59
      signal cmd : STD_LOGIC_VECTOR(1 downto 0);
60
      signal wd  : STD_LOGIC_VECTOR(31 downto 0);
61
      signal a   : STD_LOGIC_VECTOR(31 downto 0);
62
   --Outputs
63
      signal rd  : STD_LOGIC_VECTOR(31 downto 0);
64
      signal busy: STD_LOGIC;
65
  -- Indicates end of simulation
66
  signal finished : std_logic := '0';
67
BEGIN
68
 
69
  -- Instantiate the Unit Under Test (UUT)
70
   uut: data_memory PORT MAP (
71
      clk => clk,
72
      rst => rst,
73
      cmd => cmd,
74
      wd => wd,
75
      a => a,
76
      rd => rd,
77
      busy => busy
78
        );
79
  
80
  -- Generate Clock
81
  clk <= not clk after 10 ms when finished ='0' else clk;
82
   
83
  -- Stimulus process
84
   stim_proc: process
85
   begin    
86
      -- hold reset state for 100 ns.
87
    rst <= '1';
88
    cmd <= b"11";
89
    wait until rising_edge(clk);
90
    cmd <= b"00";
91
    rst <= '0';
92
    wait until rising_edge(clk);
93
      -- insert stimulus here 
94
    wait until rising_edge(clk);
95
    cmd <= b"01";
96
    a <= x"00000001";
97
    wait until rising_edge(clk);
98
    cmd <= b"00";
99
    wait until rising_edge(clk);
100
    cmd <= b"11";
101
    a <= x"00000001";
102
    wd <= x"ffffffff";
103
    wait for 100ms;
104
    finished <= '1';
105
    --Test 1
106
   end process;
107
108
END;

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

komisch, state_next macht genau das was ich haben will???

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chris schrieb:
> komisch, state_next macht genau das was ich haben will???
Herzlichen Glühstrumpf, du hast das entdeckt, was man "synchrones 
Design" nennt: nach der Taktflanke herrscht Hektik im FPGA, bis alle 
signale durch die Kombinatorik gelaufen sind. Und rechtzeitig vor dem 
nächsten Takt muss alles ruhig sein, damit die Flipflops korrekte Daten 
übernehmen können.

Ich empfehle dir, dass du mal das buch "VHDL Synthese" von 
Reichardt&Schwarz genauer anschaust...

von Chris (Gast)


Lesenswert?

Hallo,
stimmt schon hab mir das heute morgen nochmal angeguckt und eigentlich 
ziemlich logisch, dass das so nicht klappen kann. habe jetzt eine 
asynchrone version implementiert, wobei ich mir jetzt unsicher bin ob 
man sowas macht. in unserem praktikum wurden wir geimpft bloß alles 
immer synchron zu implementieren, alles andere sei böse :(
vielleicht könnt ihr mir ja eine beurteilung zu meinem jetztigen entwurf 
geben.
Aufgabenstellung: (handelt sich um enen mips proc mit wishbone 
anbindung)
ich soll einen master für einen wishbone slave programmieren, wie man 
vielleicht aus den signalen erkennen kann.
Lösung:
dafür habe ich jetzt ein data_memory als art top-level erstellt das die 
signale: clk,rst,cmd,wd,a von der pipeline erhält und als ausgabe rd und 
busy ausgibt.
intern werden dann diese signale an den wishbone-master weitergegeben, 
was ich jetzt asynchron programmiert habe.
Sollte man sowas so lösen? oder ist das garnicht gut? das asynchrone 
macht mich etwas verrückt

siehe meine beiden files unten
1
-- data_memory.vhd
2
3
library ieee;
4
use ieee.std_logic_1164.all;
5
6
entity data_memory is
7
  Port(
8
    clk  : in std_logic;
9
    rst  : in std_logic;
10
    cmd  : in std_logic_vector(1 downto 0);
11
    wd   : in std_logic_vector(31 downto 0);
12
    a    : in std_logic_vector(31 downto 0);
13
    
14
    rd   : out std_logic_vector(31 downto 0);
15
    busy : out std_logic
16
  );
17
end data_memory;
18
19
architecture Behavioral of data_memory is
20
21
  -- Wishbone buffers
22
  signal dat_i_con : std_logic_vector(31 downto 0);
23
  signal ack_i_con : std_logic;
24
  signal adr_o_con : std_logic_vector(10 downto 0);
25
  signal dat_o_con : std_logic_vector(31 downto 0);
26
  signal we_o_con  : std_logic;
27
  signal stb_o_con : std_logic;
28
  signal cyc_o_con : std_logic;
29
30
  -- Bootram buffers
31
  signal ram_ce_con : std_logic;
32
  signal ram_we_con : std_logic_vector(3 downto 0);
33
  signal ram_a_con  : std_logic_vector(12 downto 2);
34
  signal ram_d_con  : std_logic_vector(31 downto 0);
35
  signal ram_q_con  : std_logic_vector(31 downto 0);
36
37
begin
38
39
  WishboneMaster: entity work.wishbone_master
40
  port map(
41
  
42
    -- Top level signals
43
    clk  => clk,
44
    rst  => rst,
45
    cmd  => cmd,
46
    wd   => wd,
47
    a    => a,
48
    rd   => rd,
49
    busy => busy,
50
    
51
    -- Wishbone signals
52
    dat_i => dat_i_con,
53
    ack_i => ack_i_con,
54
    adr_o => adr_o_con,
55
    dat_o => dat_o_con,
56
    we_o  => we_o_con,
57
    stb_o => stb_o_con,
58
    cyc_o => cyc_o_con
59
    
60
  );
61
  
62
  WishboneSlave: entity work.bootram_wb
63
  generic map (
64
    A_BITS      => 13,
65
    BA_BITS     => 2,
66
    D_BITS      => 32,
67
    PIPE_STAGES => 1
68
  )
69
  port map(
70
    
71
    -- Generic signals
72
    clk => clk,
73
    rst => rst,
74
    
75
    -- Wishbone signals
76
    wb_dat_o => dat_i_con,
77
    wb_ack_o => ack_i_con,
78
    wb_adr_i => adr_o_con,
79
    wb_dat_i => dat_o_con,
80
    wb_we_i  => we_o_con,
81
    wb_sel_i => "1111", --sel_o_con,
82
    wb_stb_i => stb_o_con,
83
    wb_cyc_i => cyc_o_con,
84
    wb_cti_i => "000",
85
    wb_bte_i => "00",
86
    
87
    -- Bootram signals
88
    ram_ce => ram_ce_con,
89
    ram_we => ram_we_con,
90
    ram_a  => ram_a_con,
91
    ram_d  => ram_d_con,
92
    ram_q  => ram_q_con
93
    
94
  );
95
  
96
  BootRam: entity work.bootram_mips
97
  port map(
98
  
99
    -- Generic signals
100
    clk => clk,
101
    
102
    -- Bootram signals
103
    ce1 => ram_ce_con,
104
    we1 => ram_we_con,
105
    a1  => ram_a_con,
106
    d1  => ram_d_con,
107
    q1  => ram_q_con,
108
    ce2 => '0',
109
    a2  => b"00000000000",
110
    q2  => x"00000000"
111
  
112
  );
113
  
114
end Behavioral;
1
-- wishbone_master.vhd
2
3
library ieee;
4
use ieee.std_logic_1164.all;
5
6
entity wishbone_master is
7
8
  Port(
9
    -- Memory interface
10
    clk : in  std_logic;
11
    rst : in  std_logic;
12
    cmd : in  std_logic_vector(1 downto 0);
13
    wd  : in  std_logic_vector(31 downto 0);
14
    a   : in  std_logic_vector(31 downto 0);
15
    rd  : out std_logic_vector(31 downto 0);
16
    
17
    -- Wishbone interface
18
    dat_i : in  std_logic_vector(31 downto 0);
19
    ack_i : in  std_logic;
20
    adr_o : out std_logic_vector(12 downto 2);
21
    dat_o : out std_logic_vector(31 downto 0);
22
    we_o  : out std_logic;
23
    stb_o : out std_logic;
24
    cyc_o : out std_logic;
25
    busy  : out std_logic
26
  );
27
  
28
end wishbone_master;
29
30
architecture Behavioral of wishbone_master is
31
  
32
  type state_type is (IDLE, WORK);
33
  signal state     : state_type;
34
  signal tmp_dat_o : std_logic_vector(31 downto 0);
35
  signal tmp_adr_o : std_logic_vector(10 downto 0);
36
  signal tmp_dat_i : std_logic_vector(31 downto 0);
37
  signal tmp_we_o  : std_logic;
38
  
39
begin
40
  
41
  dat_o <= tmp_dat_o;
42
  adr_o <= tmp_adr_o;
43
  rd    <= tmp_dat_i;
44
  we_o  <= tmp_we_o;
45
  
46
  process(cmd,ack_i,rst,a)
47
  begin
48
    
49
    -- Initializations
50
    busy       <= '0';
51
    stb_o      <= '0';
52
    
53
    if rst = '1' then
54
      state <= IDLE;
55
    else
56
      case state is
57
        when IDLE =>
58
          
59
          if cmd(0) = '1' then -- 0|1 = read, 1|1 = write
60
            state     <= WORK;
61
            busy      <= '1';
62
            stb_o     <= '1';
63
            cyc_o     <= '1';
64
            tmp_we_o  <= cmd(1);
65
            tmp_dat_o <= wd;
66
            tmp_adr_o <= a(10 downto 0);
67
            tmp_dat_i <= dat_i;
68
          else 
69
            state     <= IDLE;
70
          end if;
71
        
72
        when WORK =>
73
          
74
          if ack_i = '1' then
75
            state <= IDLE;
76
            busy  <= '0';
77
            stb_o <= '0';
78
            cyc_o <= '0';
79
          else
80
            state     <= WORK;
81
            busy      <= '1';
82
            stb_o     <= '1';
83
            cyc_o     <= '1';
84
          end if;
85
        
86
      end case;
87
    end if;
88
  end process;
89
  
90
end Behavioral;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chris schrieb:
1
  process(cmd,ack_i,rst,a)
2
    begin
3
          :
4
             tmp_dat_o <= wd;
5
             :
6
             tmp_dat_i <= dat_i;
7
  end process;
Ich meine, ich hätte dazu schon mal was geschrieben...

Das hier ghet natürlich nicht, denn das wäre eine komplett asynchrone 
Statemachine. Sowas ist im echten Leben nicht beherrschbar:
1
  process(cmd,ack_i,rst,a)
2
  begin
3
    :    
4
    if rst = '1' then
5
      state <= IDLE;
6
    else
7
      case state is
8
         when IDLE =>
9
          :
10
            state     <= WORK;

Mein Tipp immer noch: besorg dir das angesprochene Buch.

von Chris (Gast)


Lesenswert?

Sooooo, hab das Buch noch ergattern können, zwar nur ne Version von 2000 
aber ich denke seitdem sollte sich bei so grundlegenden Sachen wohl 
nichts getan haben. Hab auch noch paar Quellcodes im Inet durchforstet 
und komme jetzt auf folgende Lösung für einen Wishbone-Master in VHDL:
Wir sollten über einen Bootram testen und wenn ich mich nicht ganz irre 
scheint alles in der Simulation zupassen :) Hoffentlich klappt dann auch 
die Synthese
Vielen Dank Lothar, irgendwie stand ich gestern Nacht, heute morgen aufm 
Schlauch :D
Was meintest du mit den tmp_* Signalen? Hab das jetzt auch ausgebessert 
soweit wie ich konnte. Sieht das vernünftig aus?
1
-- wishbone_master.vhd
2
3
library ieee;
4
use ieee.std_logic_1164.all;
5
6
entity wishbone_master is
7
8
  Port(
9
    -- Memory interface
10
    clk : in  std_logic;
11
    rst : in  std_logic;
12
    cmd : in  std_logic;
13
    wd  : in  std_logic_vector(31 downto 0);
14
    a   : in  std_logic_vector(31 downto 0);
15
    rd  : out std_logic_vector(31 downto 0);
16
    
17
    -- Wishbone interface
18
    dat_i : in  std_logic_vector(31 downto 0);
19
    ack_i : in  std_logic;
20
    adr_o : out std_logic_vector(12 downto 2);
21
    dat_o : out std_logic_vector(31 downto 0);
22
    we_o  : out std_logic;
23
    stb_o : out std_logic;
24
    cyc_o : out std_logic;
25
    done  : out std_logic
26
  );
27
  
28
end wishbone_master;
29
30
architecture Behavioral of wishbone_master is
31
  
32
  type state_type is (S_IDLE, S_READ, S_WRITE, S_FINITE);
33
  signal state,next_state  : state_type;
34
35
begin
36
  adr_o <= a(10 downto 0);
37
  dat_o <= wd;
38
  rd <= dat_i;
39
  process(clk)
40
  begin
41
    if rising_edge(clk) then
42
      if (rst = '1') then
43
        state <= S_IDLE;
44
      else
45
        state <= next_state;
46
      end if;
47
    end if;
48
  end process;
49
  
50
  process(state)
51
  begin
52
   cyc_o <= '0';
53
   stb_o <= '0';
54
   we_o  <= '0';   
55
   done  <= '0';
56
   case (state) is
57
      when S_IDLE =>
58
         cyc_o  <= '0';
59
         stb_o  <= '0';
60
         we_o  <= '0';
61
      when S_READ  =>
62
         cyc_o  <= '1';
63
         stb_o  <= '1';
64
         we_o  <= '0';
65
      when S_WRITE  =>
66
         cyc_o  <= '1';
67
         stb_o  <= '1';
68
         we_o  <= '1';
69
      when S_FINITE =>
70
         done <= '1';
71
      when others =>
72
         null;
73
   end case;
74
  end process;
75
  
76
  process (state,cmd,ack_i)
77
  begin
78
    next_state <= state;
79
    case state is
80
      when S_IDLE =>
81
        if cmd = '0' then
82
          next_state  <= S_READ;
83
        else
84
          next_state  <= S_WRITE;
85
        end if;
86
        
87
      when S_READ =>
88
        if (ack_i = '1') then
89
          next_state <= S_FINITE;
90
        end if;
91
        
92
      when S_WRITE =>
93
        if (ack_i = '1') then
94
          next_state <= S_FINITE;
95
        end if;
96
      
97
      when S_FINITE =>
98
        next_state <= S_IDLE;
99
      
100
      when others =>
101
        next_state <= S_FINITE;
102
    end case;
103
    
104
  end process;
105
end Behavioral;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Chris schrieb:
> Was meintest du mit den tmp_* Signalen?
Ich meinte, dass sie in der Sensitivliste des kombinatorischen Prozesses 
fehlten und deshalb die Simulation nicht zur Realität gepasst hätte...

> Wir sollten über einen Bootram testen und wenn ich mich nicht ganz irre
> scheint alles in der Simulation zupassen :)
Bei der letzten Version sieht das gut aus, die Sensitivlisten passen.

> Hoffentlich klappt dann auch die Synthese
Viel Erfolg... ;-)

von pks (Gast)


Lesenswert?

Warum ist nur die Zwei-Prozess-Schreibweise bei FSMs so beliebt :-(

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

pks schrieb:
> Warum ist nur die Zwei-Prozess-Schreibweise bei FSMs so beliebt :-(
Sie ist nicht unbedingt beliebt, aber sie wird gelehrt...

Ich verweise auf die immer wieder auftauchenden Diskussionen hier im 
Forum wie z.B. im Beitrag "FSM möglichst einfach und übersichtlich" und die 
Zusammenfassung auf 
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

von Chris (Gast)


Lesenswert?

Hi,
ich muss zugeben, dass in zwei prozesse aufzuteilen hab ich gesehen und 
fand dies sehr zugänglich. gelehrt wurde uns das so aber nicht muss ich 
sagen. wobei was wird schon gelehrt, hier fpga+board, vhdl kann man hier 
nachlesen macht doch mal...

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.