State Machines VHDL by U81d24

VIEWS: 0 PAGES: 11

									                                                                                               1



-- EXAMPLES of STATE MACHINES -- VHDL
-- Note: These examples are given for illustration purposes only
-- Note: Debugging is your responsibility.

-- controller.vhd
library IEEE;
use ieee.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

ENTITY controller is PORT
      ( external_clk                      : in std_logic;
         reset_ext                        : in std_logic;
         start_ext                        : in std_logic;
         state_debug_ext                  : out std_logic_vector ( 3 downto 0);
         serial_data_ext                  : out std_logic;
         angle_sensor1_ext,
         angle_sensor2_ext                : in std_logic;
         motor_pwm_ext                    : out std_logic;
         sensorSerialData0,
         sensorSerialData1,
         sensorSerialData2                : in std_logic; -- Data in from sensors
         seg7LSB, seg7MSB                 : out std_logic_vector (6 downto 0);
         sensor1clk, sensor2clk,
         sensor3clk                       : out std_logic;-- clocks for sensors
         DataProcessorStage1OnOff,
         DataProcessorStage2OnOff : in std_logic
         -- this is for debugging, it turns on/off the individual stages of data processing.
         );
END controller;

ARCHITECTURE arch of controller is

COMPONENT clk_div is PORT
     ( clock_25Mhz     : IN              STD_LOGIC;
        clock_1MHz     : OUT             STD_LOGIC;
        clock_100KHz   : OUT             STD_LOGIC;
        clock_10KHz    : OUT             STD_LOGIC;
        clock_1KHz     : OUT             STD_LOGIC;
        clock_100Hz    : OUT             STD_LOGIC;
        clock_10Hz     : OUT             STD_LOGIC;
        clock_1Hz      : OUT             STD_LOGIC);
END COMPONENT;

COMPONENT seg7 is PORT
  ( Data              : IN STD_LOGIC_VECTOR (7 DOWNTO 0); -- input
    SegLSB, SegMSB    : OUT STD_LOGIC_VECTOR (6 DOWNTO 0)); -- 7 segment outputs
END COMPONENT;

COMPONENT controller_fsm is
 PORT ( reset_ext, clk     : in std_logic;
        start_it           : in std_logic;
        state_debug        : out std_logic_vector(3 downto 0 );
                   --DC Motor control section
        motor_rst          : out std_logic; --Calibrated
        motor_go           : out std_logic; --Go/Stop
        motor_red          : in std_logic;
                   --Communication section
                                                                                                      2


          comm_rst            : out std_logic; --Do initialization
          comm_select         : out std_logic_vector(1 downto 0); --Data to send
          comm_send           : out std_logic; --Send it
          comm_red            : in std_logic; --Comm ready
                    --IR Section
          ir_red              : in std_logic; --Ready
          ir_measure          : out std_logic; -- Take measurement
          ir_rst              : out std_logic;
          ir_reg_load         : out std_logic;
                    --Angle recovery section
          angle_change        : in std_logic; --Change in angle
          angle_reg_load      : out std_logic);

END COMPONENT;

COMPONENT uart is PORT
     ( clk      : IN std_logic;
       write    : IN std_logic;
        reset   : IN std_logic;
        data    : IN std_logic_vector(7 downto 0);
                 -- [00 -> no parity; 01,10 -> odd parity; 11 -> even parity]
       parityMode : IN std_logic_vector(1 downto 0);
                -- [00 -> 5 bits; 01 -> 6 bits; 10 -> 7 bits; 11 -> 8 bits]
       bitMode : IN std_logic_vector(1 downto 0);
                -- transmitter output SIGNAL and status flag
       tx       : OUT std_logic;
       txrdy    : OUT std_logic);
END COMPONENT;

--COMPONENT uart is PORT (
--         mclkx16 : IN std_logic;
--         write     : IN std_logic;
--         reset      : IN std_logic;
--         data       : IN std_logic_vector(7 downto 0);
    -- transmitter output SIGNAL and status flag
--         tx         : OUT std_logic;
--         txrdy     : OUT std_logic);
--end COMPONENT;

        --IR Subsystem
COMPONENT IR_subsystem is
PORT ( clk_1ms, go, RESET                : in std_logic;
        sensorSerialData0,
        sensorSerialData1,
        sensorSerialData2                : in std_logic;
                               -- from external sensors.
        done,                                                  -- raised when subsystem is done
        sensor1clk, sensor2clk,
        sensor3clk                       :out std_logic;       -- clock lines to sensors
        ProcessedOutput2                 : out std_logic_vector(7 downto 0);
                               -- Processed data out
        dataout_0, dataout_1,
        dataout_2                        :out std_logic_vector(7 downto 0); -- raw data out.
        distanceDataOut0, distanceDataOut1,
         distanceDataOut2                : out std_logic_vector (7 downto 0);
                               -- for debugging - looked up value of the sensors.
        DataProcessorStage1OnOff,
        DataProcessorStage2OnOff : in std_logic);
                -- this is for debugging, it turns on/off the individual stages of data processing.
END COMPONENT ;

COMPONENT motor_back_and_forth is
                                                                                    3


 PORT ( clk, reset         : in std_logic;
        angle_sensor1,
        angle_sensor2, start : in std_logic;
        angle_out          : out std_logic_vector (15 downto 0);
        pwm                : out std_logic;
        motor_red_out,
        angle_change       : out std_logic);
END COMPONENT;

COMPONENT ir_clk_div is
 PORT ( clk_in          : in std_logic;
        clk_div24       : out std_logic);
END COMPONENT;

COMPONENT uart_clk_div is
 PORT ( rst     : in STD_LOGIC;
        clk     : in STD_LOGIC;
        uartclk : out STD_LOGIC);
END COMPONENT;

COMPONENT reg16 is
  PORT ( rst, load        : in std_logic;
      data_in : in std_logic_vector ( 15 downto 0);
      data_out : out std_logic_vector ( 15 downto 0));
END COMPONENT;

COMPONENT mux32 is
  PORT ( clk, rst            : in std_logic;
       cntrl                 : in std_logic_vector ( 1 downto 0);
       data_in1, data_in2,
       data_in3, data_in4    : in std_logic_vector(7 downto 0);
       data_out              : out std_logic_vector ( 7 downto 0));
END COMPONENT;

COMPONENT debounce is
  PORT ( raw : in std_logic;
       clean : out std_logic;
       clk   : in std_logic );
END COMPONENT;

       --Main Signals
SIGNAL reset, start_it: std_logic;
SIGNAL rst, clean_start: std_logic; --debounced signals

       --Clock divider signals
SIGNAL div_uartclk, div_clock_1MHz, div_clock_100KHz, div_clock_10KHz: std_logic;
SIGNAL div_clock_1KHz, div_clock_100Hz, div_clock_10Hz, div_clock_1Hz: std_logic;

       --Serial Comm signals
SIGNAL ir_load_sig, angle_load_sig: std_logic;
SIGNAL ir_reg_out_sig, angle_reg_out_sig : std_logic_vector( 15 downto 0);
SIGNAL comm_sEND_sig, comm_rst_sig, comm_red_sig : std_logic;
SIGNAL mux_sel_sig: std_logic_vector ( 1 downto 0);
SIGNAL uart_data_sig : std_logic_vector( 7 downto 0);
SIGNAL uart_par_sig, uart_nbits_sig:std_logic_vector(1 downto 0);

       --IR Signals
SIGNAL ir_read_sig, ir_rst_sig, ir_red_sig : std_logic;
SIGNAL ir_data_out_sig: std_logic_vector(7 downto 0);
SIGNAL dataout_0, dataout_1, dataout_2: std_logic_vector( 7 downto 0);
SIGNAL distance0, distance1, distance2: std_logic_vector( 7 downto 0);
SIGNAL ir_clk: std_logic;
                                                                                          4


SIGNAL padded_ir_data: std_logic_vector ( 15 downto 0);

       --Servo and Azimuth Signals
SIGNAL motor_go_sig, motor_rst_sig: std_logic;
SIGNAL angle_data_sig: std_logic_vector( 15 downto 0);
SIGNAL motor_red_sig, cmotor_red_temp1 : std_logic;

       --Angle Signals
SIGNAL angle_change_sig: std_logic;

       --Debug
SIGNAL cstate_temp :std_logic_vector ( 3 downto 0);
       --Delete these

BEGIN
                     -- All PORT MAPS

reset      <= not reset_ext;   --Reset Button is active high (FLEX PB1)
start_it   <= not start_ext;   -- Start active high ( FLEX PB2)

              --Debounce External Buttons
RESET_DEBOUNCE: debounce
       PORT map ( reset, rst, div_clock_1Mhz);
START_DEBOUNCE: debounce
       PORT map ( start_it, clean_start, div_clock_1Mhz);

--angle_change_sig <= angle_data_sig(0);

                 --Clock Dividers
MAIN_CD: clk_div
       PORT map ( external_clk, div_clock_1MHz, div_clock_100KHz, div_clock_10KHz,
                   div_clock_1KHz, div_clock_100Hz, div_clock_10Hz, div_clock_1Hz);
IRCKLDIV: ir_clk_div
       PORT map (external_clk, ir_clk);

UART_CLK_DIVDR: uart_clk_div
      PORT map ( rst, external_clk, div_uartclk);

                  --Controller State Machine
FSM: controller_fsm
        PORT map ( rst, div_clock_1Mhz, clean_start, cstate_temp, motor_rst_sig, motor_
                    go_sig, motor_red_sig , comm_rst_sig, mux_sel_sig, comm_sEND_sig,
                    comm_red_sig, ir_red_sig, ir_read_sig, ir_rst_sig, ir_load_sig,
                    angle_change_sig, angle_load_sig);

                     --Serial Output section
uart_par_sig         <= "00";
uart_nbits_sig       <= "11";

REG_16_0: reg16
       PORT map (rst, angle_load_sig, angle_data_sig, angle_reg_out_sig);

REG_16_1: reg16
       PORT map (rst, ir_load_sig, padded_ir_data, ir_reg_out_sig);

MUX_32: mux32
       PORT map (external_clk, rst, mux_sel_sig, angle_reg_out_sig(15 downto 8),
       angle_reg_out_sig(7 downto 0), ir_reg_out_sig(15 downto 8),
       ir_reg_out_sig(7 downto 0), uart_data_sig);

--UART_L: uart
       PORT map ( div_uartclk, comm_sEND_sig, comm_rst_sig, uart_data_sig,
                                                                                           5


               serial_data_ext, comm_red_sig );
UART_L: uart
       PORT map ( div_uartclk, comm_send_sig, comm_rst_sig, uart_data_sig,
                uart_par_sig, uart_nbits_sig, serial_data_ext, comm_red_sig);

                         --IR Subsystem
IR_SUBSYS: IR_subsystem
       PORT map ( ir_clk, ir_read_sig, ir_rst_sig, sensorSerialData0, sensorSerialData1,
                 sensorSerialData2, ir_red_sig, sensor1clk, sensor2clk, sensor3clk,
                 ir_data_out_sig, dataout_0, dataout_1, dataout_2, distance0,
                 distance1, distance2, DataProcessorStage1OnOff,
                 DataProcessorStage2OnOff);

padded_ir_data (15 downto 8)          <= ir_data_out_sig;
padded_ir_data (7 downto 0) <= distance1;

              --Servo and Azimuth Subsystem
SER_MOTOR: motor_back_and_forth
      PORT map (external_clk, rst, angle_sensor1_ext, angle_sensor2_ext, motor_go_sig,
                angle_data_sig, motor_pwm_ext, motor_red_sig, angle_change_sig );

         --cmotor_red_temp1           <= cmotor_red_temp;

                --Debug Display
SEVEN_SEG: seg7
      PORT map(ir_data_out_sig, seg7LSB, seg7MSB);          ---For debugging.

         state_debug_ext              <= cstate_temp;

END arch;
                                                                                                 6




-- controller_fsm.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

ENTITY controller_fsm is
  PORT ( reset_ext, clk : in std_logic;
       start_it          : in std_logic;
       state_debug       : out std_logic_vector(3 downto 0 );
                --DC Motor control section
       motor_rst         : out std_logic; --Calibrated
       motor_go          : out std_logic; --Go/Stop
       motor_red         : in std_logic;
                --Communication section
       comm_rst          : out std_logic; --Do initialization
       comm_select       : out std_logic_vector(1 downto 0); --Data to send
       comm_send         : out std_logic; --Send it
       comm_red          : in std_logic; --Comm ready
                --IR Section
       ir_red            : in std_logic; --Ready
       ir_measure        : out std_logic; -- Take measurement
       ir_rst            : out std_logic;
       ir_reg_load       : out std_logic;
                --Angle recovery section
       angle_change      : in std_logic; --Change in angle
       angle_reg_load : out std_logic);
END controller_fsm;


ARCHITECTURE fsm_arch of controller_fsm is
      type states is (init, S1, S3, S2, S7, S6, S4, S5, S15, S14, S12, S13, S8, S9, S11, S10);

         SIGNAL next_state:states:=init;
         SIGNAL curr_state: states;
         SIGNAL temp_send: std_logic_vector( 1 downto 0);
         SIGNAL prev_angle: std_logic;

begin

process( reset_ext, clk)
begin
         IF (reset_ext = '1' and start_it = '1') THEN
                  curr_state <= init;
         ELSIF ( clk'event and clk = '1') THEN
                  curr_state <= next_state;
         END IF;
END process;
                                                                               7



process ( curr_state, angle_change, comm_red, motor_red, ir_red, start_it)
begin
         wait until clk'event and clk ='0';
         case curr_state is
         when init =>
                             --Reset everything.
                   state_debug          <= "0000";
                   prev_angle           <= angle_change;
                   IF(reset_ext = '1' and start_it = '0') THEN
                             next_state <= S1;
                   ELSE
                             next_state <= init;
                   END IF;
         when S1=> --1
                   state_debug <= "0001";
                   IF (start_it = '1' and reset_ext = '0') THEN
                             next_state <= S2;
                   ELSE
                             next_state <= S1; --Wait till done cal.
                   END IF;
         when S2 =>--2
                   state_debug <= "0010";
                             --Wait for everything to be initialized
                   IF (ir_red = '1' AND motor_red = '1' and comm_red = '1' )
                   THEN         --Caused be all ready
                             next_state <= S3;
                   ELSE
                             next_state <= S2;
                   END IF;
         when S3 => --3
                   state_debug <= "0011";
                   IF ( motor_red = '0') THEN
                             next_state <= S4;
                   ELSE
                             next_state <= S3;
                   END IF;
         when S4 => --4
                   state_debug <= "0100";
                             --All ready, wait for angle change
                   IF ( angle_change /= prev_angle) THEN
                             next_state <= S5;
                   ELSE
                             next_state <= S4;
                   END IF;
         when S5 => --5
                   state_debug <= "0101";
                             --Wait for ir to get message
                   IF (ir_red = '0') THEN
                             next_state <= S6;
                   ELSE
                             next_state <=S5;
                   END IF;
         when S6 => --6
                   state_debug <= "0110";
                             --Wait for IR Data
                                                      8


        IF ( ir_red = '1' ) THEN
                  next_state <= S7;
        ELSE
                  next_state <= S6;
        END IF;
when S7 => --7
        state_debug <= "0111";
        IF (comm_red = '1') THEN
                  --We are ready to sEND Angle MSBs
                  next_state <= S8;
        ELSE
                  next_state <=S7;
        END IF;
when S8 => --8
        state_debug <= "1000";
        IF (comm_red = '0') THEN
                  next_state <= S9;
        ELSE
                  next_state <= S8;
        END IF;
when S9 => --9
        state_debug <= "1001";
        IF (comm_red = '1' ) THEN
                  --Angle LSBs
                  next_state <= S10;
        ELSE
                  next_state <= S9;
        END IF;
when S10 => --10
        state_debug <= "1010";
        IF ( comm_red = '0') THEN
                  prev_angle <= angle_change;
                  next_state <= S11;
        ELSE
                  next_state <= S10;
        END IF;
when S11 => --11
        state_debug <= "1011";
        IF ( comm_red = '1') THEN
                  next_state <= S12;
        ELSE
                  next_state <= S11;
        END IF;
when S12 => --12
        state_debug <= "1100";
                  --Wait for comm unit to reply
        IF(comm_red = '0') THEN
                  next_state <= S13;
        ELSE
                  next_state <= S12;
        END IF;
when S13 => --13
        state_debug <= "1100";
        IF ( comm_red = '1') THEN
                  next_state <= S14;
        ELSE
                                                                                 9


                        next_state <= S13;
               END IF;
       when S14 => --14
               state_debug <= "1101";
                        --Wait for comm unit to reply
               IF(comm_red = '0') THEN
                        next_state <= S15;
               ELSE
                        next_state <= S14;
               END IF;
       when S15 => --15
               state_debug <= "1110";
               IF (motor_red = '1') THEN
                        next_state <= S3;
               ELSE
                        next_state <= S15;
               END IF;
       when others =>
               next_state <= init;
       END case;

END process;

       comm_select      <= "01" when (curr_state = S9 OR curr_state = S10)
                        ELSE "10" when (curr_state = S11 OR curr_state = S12)
                        ELSE "11" when (curr_state = S13 or curr_state = S14)
                        ELSE "00";

       angle_reg_load   <= '1' when curr_state = S5 ELSE '0';
       ir_reg_load      <= '1' when curr_state = S7 ELSE '0';
       motor_rst        <= '1' when curr_state = S1 ELSE '0';
       comm_rst         <= '1' when curr_state = S1 ELSE '0';
       ir_rst           <= '1' when curr_state = S1 ELSE '0';
       comm_send        <= '1' when ( curr_state = S8 OR curr_state = S10
                            OR curr_state = S12 or curr_state = S14) ELSE '0';
       ir_measure       <= '1' when ( curr_state = S5 ) ELSE '0';
       motor_go         <= '1' when (curr_state = S3 ) ELSE '0';

END fsm_arch;
                                                                        10



compass.vhd

-- Dinsmore compass code

LIBRARY ieee;
USE ieee.std_logic_1161.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY compass IS
PORT ( clock_6900Hz           : IN std_logic; --
       reset                  : IN std_logic; --
        pulse, trigger        : IN std_logic; --
        init, data_done       : OUT std_logic; --
        comp_counter          : OUT std_logic_vector (7 down to 0));
END compass;

ARCHITECTURE state_machine OF compass IS

TYPE StateType IS ( start, init_high, error_state, measure, output );

SIGNAL CurrentState, NextState    : StateType;
SIGNAL pulse_timer                : std_logic_vector ( 7 downto 0 );
SIGNAL hold_time          : INTEGER RANGE 0 to 25600;
SIGNAL timer, error_count : INTEGER RANGE 0 to 6;

BEGIN

comb: PROCESS (CurrentState)
BEGIN
   WAIT UNTIL rising_edge (clock_6900Hz);
   CASE CurrentState IS
        WHEN start =>                -- reset timer
               pulse_timer           <= “0000000”;
               init                  <= ‘0’;
               data_done             <= ‘0’;
               hold_time             <= 0;
               IF ( trigger = ‘1’ ) THEN
                    NextState        <= init_high;
               ELSE
                    NextState        <= start;
               ENDIF;

          WHEN init_high =>
                 init              <= ‘1’;
                 NextState <= measure;

          WHEN measure =>
                IF ( pulse = ‘0’ ) THEN
                     init            <= ‘0’;
                     NextState       <= output;
                ELSE
                     pulse_timer     <= pulse_timer + 1;
                     IF ( pulse_timer = “11111111” ) THEN
                           init               <= ‘0’;
                           comp_counter       <= pulse_timer;
                           NextState <= error_state;
                      ELSE
                           NextState          <= measure;
                    ENDIF;
                ENDIF;

          WHEN error_state =>
                                                                          11


                  comp_counter       <= “11111111”;
                  data_done          <= ‘1’;
                  NextState <= output;

         WHEN output =>
                comp_counter          <= pulse_counter;
                data_done             <= ‘1’;
                IF ( trigger = ‘1’ ) THEN
                     NextState        <= output;
                ELSE
                     NextState        <= start;
                ENDIF;

         WHEN OTHERS =>
               NextState             <= start;

   END CASE;
END PROCESS comb;

seq: PROCESS (clock_6900, reset) -- process to cycle through the states
BEGIN
     IF ( reset = ‘1’ ) THEN
           CurrentState      <= start;
     ELSIF rising_edge (clock_6900Hz) THEN
           CurrentState      <= NextState;
     ENDIF;
END PROCESS seq;


END ARCHITECTURE state_machine;

								
To top