Forum: FPGA, VHDL & Co. State Machine mit Signalzuweisung


von Flo _. (mcolf)


Lesenswert?

Hallo Leute,

hab ne State Machine nach Moore mit drei Prozessen geschrieben.
Die States arbeiten Synchron.
Ich will damit bei bestimmten Zuständen verschieden Werte einem Signal 
zuweisen. Sollte also eigentlich kein Problem sein.

Die Folgenden States gibt es vom Prinzip:
Idle state -> keine änderung des Signals. (null;)
State A -> MySignal(15 downto 0) <= x"AAAA";
State B -> MySignal(15 downto 0) <= x"BBBB";

(Ist klar dass es kein richtiger VHDL-Code ist!)

Problem:
Solange ich mich im State A befinde ist MySignal = "AAAA" und im State B 
= "BBBB". So wie es sein soll.
Geht er aber wieder in den Idle State ist mein Signal plötzlich wieder 
auf "0000". Ich verstehe einfach nicht warum. Es gibt keine weiter 
Signalzuweisung im gesamten Code!

Habe jetzt auch schon porbiert im Idle State oder vor der case-Abfrage
MySignal <= MySignal;
Hilft aber auch nicht.

An was könnte es liegen?

Hoffe ihr könnt mir weiterhelfen.

von Philip (Gast)


Lesenswert?

Der Fehler ist in Zeile 42

von Flo _. (mcolf)


Lesenswert?

Philip schrieb:
> Der Fehler ist in Zeile 42

Arsch

von Käpt'n Fjutscher (Gast)


Lesenswert?

Coste mal den Pode?

von Flo _. (mcolf)


Lesenswert?

Okay, dann ist hier mal der Code. Ist halt schon recht viel.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity fb_Top_Module is
  port(
    --RSTn     : in std_logic; -- low activ
    clk    : in std_logic; -- Clock 50Mhz from external Quarz
    clk_60MHz_out: out std_logic; -- System Clock 60Mhz from DCM

    Button1  : in std_logic; -- init
    Button2  : in std_logic; -- send next
    Button3  : in std_logic; -- get next byte
    Switch  : in std_logic_vector(4 downto 1);

    -- RS232-PC anschluss zum debuggen
    RS232_sRX    : in std_logic;
    RS232_sTX    : out std_logic;

    -- Moduleinterface anschlüsse nach außen
    Module_Conect  : in std_logic;
    MI1_UA_sRX     : in std_logic;
    MI1_UA_sTX     : out std_logic;
    MI1_UB_sRX     : in std_logic;
    MI1_UB_sTX     : out std_logic;
    MI1_UA_DataReceive_o : out std_logic_vector(7 downto 0);
    MI1_DataSend_o : out std_logic_vector(15 downto 0);
    MI2_UA_sRX     : in std_logic;
    MI2_UA_sTX     : out std_logic;
    MI2_UB_sRX     : in std_logic;
    MI2_UB_sTX     : out std_logic;

    SaveData2     : out std_logic_vector(15 downto 0);

    DebugSig    : out std_logic_vector(7 downto 0)
  );
end fb_Top_Module;

architecture Behavioral of fb_Top_Module is

signal clk_60MHz   : std_logic;
signal RSTn     : std_logic;
-- -------------------------------------------------------------
-- Moduleinterfaces & RS232
signal rst  : std_logic;
signal Uart_Command   : std_logic_vector(2 downto 0):="000";
-- RS232
signal RS232_Uart_Command   : std_logic_vector(2 downto 0):="000";
signal RS232_IRQ      : std_logic_vector(1 downto 0);
signal RS232_DataSend     : std_logic_vector(15 downto 0);
signal RS232_DataReceive   : std_logic_vector(15 downto 0);
signal RS232_rdy        : std_logic;
-- Moduleinterface 1
signal MI1_IRQ        : std_logic_vector(1 downto 0);
signal MI1_DataSend     : std_logic_vector(15 downto 0);
signal iMI1_DataSend     : std_logic_vector(15 downto 0);
signal MI1_DataReceive   : std_logic_vector(15 downto 0);
signal MI1_rdy        : std_logic;
-- Moduleinterface 2
signal MI2_IRQ        : std_logic_vector(1 downto 0);
signal MI2_DataSend     : std_logic_vector(15 downto 0);
signal MI2_DataReceive   : std_logic_vector(15 downto 0);

signal Zeichen     : std_logic_vector(7 downto 0);
signal SaveData     : std_logic_vector(15 downto 0);

-- -------------------------------------------------------------
-- Haupt FSM
type state_type is (TopFSMrst, TopFSM1, TopFSM2, TopFSM3, TopFSM4, 
TopFSM5, TopFSM5a, TopFSM5b, TopFSM5c, TopFSM6, TopFSM7, TopFSM8, 
TopFSM9, TopFSM10);
signal state_TopFSM, next_state_TopFSM : state_type;

component DCM_60MHz is
   port(
    CLKIN_IN        : in    std_logic;
    CLKFX_OUT       : out   std_logic;
    CLKIN_IBUFG_OUT : out   std_logic;
    CLK0_OUT        : out   std_logic
  );
end component;

component Uart_ctrl is
  generic (Divisor : std_logic_vector(15 downto 0):= x"0001");
  port(
    -- Module Interface anschlüsse
    rst     : in std_logic; -- high activ
    clk    : in std_logic;

    Uart_Command : in std_logic_vector(2 downto 0);
    rdy       : out std_logic;
    TXRDYn  : out std_logic;
    RXRDYn  : out std_logic;
    IRQ      : out std_logic_vector(1 downto 0);
    DataReceive  : out std_logic_vector(15 downto 0);
    DataSend    : in std_logic_vector(15 downto 0);
    -- Module Interface anschlüsse nach außen
    UA_sRX     : in std_logic;
    UA_sTX     : out std_logic;
    UB_sRX     : in std_logic;
    UB_sTX     : out std_logic;

    DebugSig    : out std_logic_vector(7 downto 0)
  );
end component;

begin
clk_60MHz_out <= clk_60MHz; -- System Clock 60Mhz from DCM

RSTn  <= Switch(1);
rst  <= not RSTn;
--MI1_DataSend(15 downto 0) <= x"2ACC";
MI1_UA_DataReceive_o <= MI1_DataReceive(7 downto 0);
MI1_DataSend_o <= MI1_DataSend;

  -- 
--------------------------------------------------------------------
  -- Haupt FSM zur erzeugung der Kommandos durch Tastendruck oder IRQ
   SYNC_PROC: process (clk_60MHz)
   begin
      if ( clk_60MHz'event and clk_60MHz = '1') then
         if (RSTn = '0') then
            state_TopFSM <= TopFSMrst;

         else
            state_TopFSM <= next_state_TopFSM;
--        MI1_DataSend <= MI1_DataSend;
         end if;
      end if;
   end process;

   --MOORE State-Machine - Outputs based on state only
   OUTPUT_DECODE: process (state_TopFSM)
   begin
    Uart_Command <= "000";
    RS232_Uart_Command <= "000";
    MI1_DataReceive <= MI1_DataReceive;

      case (state_TopFSM) is
      when TopFSMrst    => Uart_Command <= "000";
                    RS232_Uart_Command <= "000";
                    RS232_DataSend(15 downto 8) <= (others=>'0');
                    RS232_DataSend(7 downto 0) <= (others=>'0');
                    SaveData <= (others=>'0');

      --Idle
      when TopFSM1    => null;
      --Init
      when TopFSM2    => Uart_Command <= "010";
                    RS232_Uart_Command <= "010";
      --Send to MI1
      when TopFSM3    =>  MI1_DataSend <= x"2ACC";--x"01e1";
      when TopFSM4    => Uart_Command <= "100";
      when TopFSM5    => null;
      when TopFSM5a    =>  MI1_DataSend <= x"CC0A";--x"0001";
      when TopFSM5b    => null;
      when TopFSM5c    => Uart_Command <= "100";
      --Get next byte from MI1 and send to RS232
      when TopFSM6    => Uart_Command <= "101";
                    SaveData <= MI1_DataReceive;
      when TopFSM7    => null;
      when TopFSM8    => RS232_Uart_Command <= "100";
                    RS232_DataSend(7 downto 0) <= x"46";--SaveData(15 
downto 8);
      when TopFSM9    => null;
      when TopFSM10    => RS232_Uart_Command <= "100";
                    RS232_DataSend(7 downto 0) <= x"42";--SaveData( 7 
downto 0);
    end case;
   end process;

   NEXT_STATE_DECODE: process (state_TopFSM, Button1, Button2, Button3, 
MI1_IRQ, RS232_rdy, MI1_rdy)
   begin
      next_state_TopFSM <= state_TopFSM;
      case (state_TopFSM) is
      when TopFSMrst => next_state_TopFSM <= TopFSM1;
         when TopFSM1 =>    -- Idle
                  if    Button1 = '1' then
                    next_state_TopFSM <= TopFSM2;
                  elsif Button2 = '1' then
                    next_state_TopFSM <= TopFSM3;
                  elsif Button3 = '1' then
                    next_state_TopFSM <= TopFSM6;
                  end if;
         -- Button1
      when TopFSM2 =>  -- Init
                  next_state_TopFSM <= TopFSM1;
      -- Button2
      when TopFSM3 =>  -- release button wait
                  if Button2 = '0' then
                    next_state_TopFSM <= TopFSM4;
                  else
                    next_state_TopFSM <= state_TopFSM;
                  end if;
      when TopFSM4 =>  next_state_TopFSM <= TopFSM5;
      when TopFSM5 =>  if MI1_rdy = '1' then
                    next_state_TopFSM <= TopFSM1;
                  else
                    next_state_TopFSM <= state_TopFSM;
                  end if;

      when TopFSM5a =>  next_state_TopFSM <= TopFSM5b;

      when TopFSM5b =>  next_state_TopFSM <= TopFSM5c;
      when TopFSM5c =>
                  next_state_TopFSM <= TopFSM1;
      -- Button3
      when TopFSM6 =>  -- Read MI1 and wait for MI1_IRQ = 0;        -- 
Status kann evtl. weg/ übersprungen werden
                  next_state_TopFSM <= TopFSM7;
      when TopFSM7 =>  -- get next byte from MI1
--                  if MI1_IRQ = "00" then
                    next_state_TopFSM <= TopFSM8;
--                  end if;
      when TopFSM8 =>  -- send higher byte to RS232
                  next_state_TopFSM <= TopFSM9;
      when TopFSM9 =>  -- wait
                  if RS232_rdy = '1' then
                    next_state_TopFSM <= TopFSM10;
                  end if;
      when TopFSM10=>  -- send lower byte to RS232
                  next_state_TopFSM <= TopFSM1;
      end case;
   end process;


DCM60 : DCM_60MHz
   port map(
    CLKIN_IN    => clk,
    CLKFX_OUT  => clk_60MHz, -- System Clock 60Mhz from DCM
    CLKIN_IBUFG_OUT=> open,
    CLK0_OUT    => open
);

RS232 : Uart_Ctrl
  generic map (divisor => x"0021")
  port map(
    rst     => rst,
    clk    => clk_60MHz,
    Uart_Command => RS232_Uart_Command,
    rdy       => RS232_rdy,
    TXRDYn     => open,
    RXRDYn     => open,
    IRQ       => RS232_IRQ,
    DataReceive => RS232_DataReceive,
    DataSend    => RS232_DataSend,
    UA_sRX     => RS232_sRX,
    UA_sTX     => RS232_sTX,
    UB_sRX     => '0',
    UB_sTX     => open,
    DebugSig    => open
);

ModulInterface1 : Uart_Ctrl
  generic map (divisor => x"0001")
  port map(
    rst     => rst,
    clk    => clk_60MHz,
    Uart_Command => Uart_Command,
    rdy       => MI1_rdy,
    TXRDYn     => open,
    RXRDYn     => open,
    IRQ       => MI1_IRQ,
    DataReceive => MI1_DataReceive,
    DataSend    => MI1_DataSend,
    UA_sRX     => MI1_UA_sRX,
    UA_sTX     => MI1_UA_sTX,
    UB_sRX     => MI1_UB_sRX,
    UB_sTX     => MI1_UB_sTX,
    DebugSig    => DebugSig
);
end Behavioral;

von Falk B. (falk)


Lesenswert?

@  Flo B. (mcolf)

>Okay, dann ist hier mal der Code. Ist halt schon recht viel.

Aber lesen kannst du?

"Wichtige Regeln - erst lesen, dann posten!"

Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Dein Problem ist eigentlich klar. Durch die von mir mehrfach als 
unsinnig ausgewiesene 2/3 Prozessmethode baut man sich viel schneller 
Latches in die Schaltung (-> SCHLECHT!) und muss ich um JEDE Zuweisung 
selber kümmern, vor allem die impliziten, wenn KEIN Datenwechsel 
erfolgen soll.
Schreib deine State Machine zumindest in einen Prozess, die Dekodierung 
zusätzlicher Ausgänge KANN man in einem anderen machen. Aber das sind 
REINE kombinatorische Signale, KEINE Speicher. Die muss man dann direkt 
in die FSM packen. Ist auch übersichtlicher.

MFG
Falk

von Daniel (root) (Gast)


Lesenswert?

Es klingt so als willst du einen latch einbauen, sodass
bei den Zustandsübergängen A->IDLE, B->IDLE Signal den alten
Wert beibehält. Die Umsetzung ist aber Kacke.

Mach aus den Ausgangssignale Register. ala

1
signal val_next, val_reg : bit_vector(3 downto 0);
2
3
update: process
4
begin
5
    wait until rising_edge(clk);
6
    state_reg <= state_next;
7
    val_reg <= val_next;
8
end process;
9
10
ausgabe: process(state_reg)
11
begin
12
    val_next <= val_reg;
13
    state_next <= state_reg;
14
    case state_reg is
15
        when IDLE => null; -- im grunde tut er das was in Zeile 1,2 steht
16
        when A => val_next <= "aaaa";
17
        when B => val_next <= "bbbb";
18
    end case;
19
end process;
20
21
state_transiotion: process
22
begin
23
    -- up to you ;)
24
end process;

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.