мой код vhdl для реализации некоторых fsm работает некорректно - PullRequest
0 голосов
/ 06 августа 2020
library IEEE;
use IEEE.std_logic_1164.all;

entity INCUBATOR2 is
    port(temperature: in std_logic_vector(7 downto 0);
    CLK,RESET: in std_logic;
    on_cooler,on_heater: out std_logic;
    CRS:out std_logic_vector(3 downto 0));

end entity INCUBATOR2;

architecture ARCH of INCUBATOR2 is



TYPE STATE_TYPE_left IS (S1, S2, S3);
SIGNAL STATE,NEXT_STATE   : STATE_TYPE_left;

TYPE STATE_TYPE_right IS (S_OUT,S_1, S_2, S_3);
SIGNAL cooler_STATE,cooler_NEXT_STATE   : STATE_TYPE_right;


begin
    --T<= temprature;
    REG: process (clk, reset) begin
        if reset='1' then
            STATE <= S1 ;
            cooler_STATE<=S_OUT;
        elsif clk'event and clk='1' then
            STATE <= NEXT_STATE ;
            cooler_STATE<=cooler_NEXT_STATE;
        end if ;    
    end process REG ;
   
    CMB:process(STATE,temperature   ,cooler_STATE) 
    begin
        case STATE is
            when S1 => 
                if(temperature  > "00100011" ) then
                    NEXT_STATE<=S2;
                    
                elsif(temperature < "00001111") then
                    NEXT_STATE<= S3;
                end if;
                --cooler_NEXT_STATE<=S_OUT;
            when S2 =>
                if(temperature < "00011001" ) then
                    NEXT_STATE<=S1;
                end if;
                case cooler_STATE is
                    when S_OUT=>
                        if(temperature>"00100011") then
                            cooler_NEXT_STATE<=S_1;
                        end if;
                    when S_1=>
                        if(temperature>"00101000") then
                            cooler_NEXT_STATE<=S_2;
                        elsif(temperature<"00011001") then
                            cooler_NEXT_STATE<=S_OUT;
                        end if;
                    when S_2=>
                        if(temperature>"00101101") then
                            cooler_NEXT_STATE<=S_3;
                        elsif(temperature<"00100011") then
                            cooler_NEXT_STATE<=S_1;
                        end if;
                    when S_3=>
                        if(temperature<"00101000") then
                            cooler_NEXT_STATE<=S_2;
                        end if;
                end case;
                

                
            when S3 => 
                if(temperature>"00011110" ) then
                    NEXT_STATE<=S1;
                end if;
                --cooler_NEXT_STATE<=S_OUT;
        end case;
        
    end process CMB;
  --  with STATE select
--  heater<= '0' when S1|S2,
--      '1' when S3;
--  cooler<= '0' when S1|S3,
--      '1' when S2;
  --  label if( cooler='1') generate
    --  modul: COOLER port  map(temprature=>T,CRS=>CRS,clk=>clk,reset=>reset);
     --end generate;
    
    OUTPUT : process(STATE,cooler_STATE) 
    begin
            
        case STATE is
            when S1 =>
                on_heater<='0';
                on_cooler<='0';
                
            when S2 =>
                on_cooler<='1';
                on_heater<='0';

                
                case cooler_STATE is
                    when S_OUT =>
                        CRS<="0000";
                    when S_1 =>
                        CRS<="0100";
                    when S_2 =>
                        CRS<="0110";
                    when S_3 =>
                        CRS<="1000";
                    when others=>
                        CRS<="0000";
                end case;
                
            when S3 =>
                on_heater<='1';
                on_cooler<='0';

        end case;
        
    end process OUTPUT;

    
end ARCH;

и вот тестовый стенд:

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

entity incubator_tb is
end entity;

architecture testbench of incubator_tb is

component INCUBATOR2 is
    port(temperature: in std_logic_vector(7 downto 0);
    CLK,RESET: in std_logic;
    on_cooler,on_heater: out std_logic;
    CRS:out std_logic_vector(3 downto 0));
end component INCUBATOR2;

signal  CLK, reset: std_logic;
signal  on_cooler,on_heater:std_logic;
signal temperature:std_logic_vector(7 downto 0);
signal CRS: std_logic_vector(3 downto 0);
begin

modul: INCUBATOR2 port map(
temperature => temperature, clk => clk, reset => reset,
on_cooler => on_cooler,on_heater=>on_heater,CRS=>CRS);

stim: process
begin

temperature <= "00100110";
clk <= '0';
reset <= '1';
wait for 20 ns;

temperature <= "00100110";
clk <= '1';
reset <= '0';

wait for 20 ns;

reset <= '0';
clk <= '0';
temperature <= "00001010";
wait for 20 ns;

reset <= '0';
clk <= '1';
temperature <= "00001010";
wait for 20 ns;

reset <= '0';
clk <= '0';
temperature <= "00100110";
wait for 20 ns;
--clk <= '1';

reset <= '0';
clk <= '1';
temperature <= "00100110";
wait for 20 ns;

reset <= '0';
clk <= '1';
temperature <= "00101010";
wait for 20 ns;


wait;

end process;
end architecture testbench;

, как показано на рисунке ниже, выходы некоторых входов вычисляются неправильно и on_heater никогда не активируется ... (предполагается переключение до 1 при температуре a)

введите описание изображения здесь

может ли кто-нибудь сказать мне, что где я делаю неправильно? Я так запутался, любая помощь будет очень признательна.

1 Ответ

1 голос
/ 10 августа 2020

Поскольку предполагается, что вы проектируете только правый конечный автомат (кулер), вам следует сосредоточиться на этом, отдельном от левого конечного автомата (главного контроллера).

Поговорите с вашим коллегой кто разрабатывает главный контроллер для добавления вывода под названием enable_cooler для включения конечного автомата кулера. Сущность Incubator может включать в себя две сущности с именами MainController и Cooler.

Я выделил логи c более прохладного конечного автомата в отдельную сущность под названием Cooler. Это в трех процессах, которые поддерживают синхронизацию выходов как с часами, так и с состоянием:

  1. регистр состояния и регистр выходов.
  2. логика следующего состояния c.
  3. Следующие выходы Logi c.

Я также добавил несколько предложений else для предотвращения предполагаемых защелок и добавил некоторые константы, чтобы сделать его более читаемым и поддерживаемым.

Конечный автомат кулера

Диаграмма состояний

Cooler state machine Figure 1 – Cooler state machine


VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Cooler is
    port
    (
        clock: in std_logic;
        reset: in std_logic;
        enable: in std_logic;  -- ADDED: From cooler enable signal of modified left-hand state machine.
        temperature: in std_logic_vector(7 downto 0);  -- I've assumed this is a signed temperature.
        crs: out std_logic_vector(3 downto 0)
    );
end entity;

architecture V1 of Cooler is

    type TState is (S_OUT, S_1, S_2, S_3);
    signal state, next_state: TState;

    signal next_crs: std_logic_vector(3 downto 0);  -- ADDED to ensure the outputs are synchronised to the clock and state.

    constant TEMPERATURE_P25: integer := 25;  -- ADDED for readability and maintainability.
    constant TEMPERATURE_P35: integer := 35;
    constant TEMPERATURE_P40: integer := 40;
    constant TEMPERATURE_P45: integer := 45;

    constant RPS_0: std_logic_vector(3 downto 0) := "0000";  -- ADDED for readability and maintainability.
    constant RPS_4: std_logic_vector(3 downto 0) := "0100";
    constant RPS_6: std_logic_vector(3 downto 0) := "0110";
    constant RPS_8: std_logic_vector(3 downto 0) := "1000";

begin

    --
    -- State Register and Outputs Register
    --
    process(clock, reset)
    begin
        if reset then
            state <= S_OUT;
            crs <= RPS_0;  -- ADDED to specify outputs for reset condition.
        elsif rising_edge(clock) then
            state <= next_state;  -- State is synchronised to clock.
            crs <= next_crs;      -- Outputs are synchronised to clock and state.
        end if;
    end process;

    --
    -- Next State Logic
    --
    process(enable, state, temperature)
        variable i_temperature: integer;  -- ADDED for numeric comparisons.
    begin
        if enable then
            i_temperature := to_integer(signed(temperature));  -- I've assumed this is a signed temperature.
            case state is
                when S_OUT =>
                    if i_temperature > TEMPERATURE_P35 then
                        next_state <= S_1;
                    else
                        next_state <= S_OUT;  -- ADDED to prevent inferred latch.
                    end if;
                when S_1 =>
                    if i_temperature > TEMPERATURE_P40 then
                        next_state <= S_2;
                    elsif i_temperature < TEMPERATURE_P25 then
                        next_state <= S_OUT;
                    else
                        next_state <= S_1;  -- ADDED to prevent inferred latch.
                    end if;
                when S_2 =>
                    if i_temperature > TEMPERATURE_P45 then
                        next_state <= S_3;
                    elsif i_temperature < TEMPERATURE_P35 then
                        next_state <= S_1;
                    else
                        next_state <= S_2;  -- ADDED to prevent inferred latch.
                    end if;
                when S_3 =>
                    if i_temperature < TEMPERATURE_P40 then
                        next_state <= S_2;
                    else
                        next_state <= S_3;  -- ADDED to prevent inferred latch.
                    end if;
                when others =>
                    next_state <= S_OUT;
            end case;
        else
            next_state <= S_OUT;  -- Prevent inferred latch.
        end if;
    end process;

    --
    -- Next Outputs Logic
    --
    process(next_state)
    begin
        case next_state is
            when S_OUT =>
                next_crs <= RPS_0;
            when S_1 =>
                next_crs <= RPS_4;
            when S_2 =>
                next_crs <= RPS_6;
            when S_3 =>
                next_crs <= RPS_8;
            when others =>
                next_crs <= RPS_0;
        end case;
    end process;

end architecture;

Конечный автомат главного контроллера

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity MainController is
    port
    (
        clock: in std_logic;
        reset: in std_logic;
        temperature: in std_logic_vector(7 downto 0);
        on_cooler: out std_logic;
        on_heater: out std_logic;
        enable_cooler: out std_logic  -- ADDED to enable cooler when MainController is in state S2.
    );
end entity;

architecture V1 of MainController is

    type TState is (S1, S2, S3);
    signal state, next_state: TState;

    constant TEMPERATURE_P15: integer := 15;  -- ADDED for readability and maintainability.
    constant TEMPERATURE_P25: integer := 25;
    constant TEMPERATURE_P30: integer := 30;
    constant TEMPERATURE_P35: integer := 35;

    signal next_on_cooler: std_logic;  -- ADDED to ensure outputs are synchronised to the clock and state.
    signal next_on_heater: std_logic;

begin

    --
    -- State Register and Outputs Register
    --
    process(clock, reset)
    begin
        if reset then
            state <= S1;
            on_cooler <= '0';  -- ADDED to specify outputs for reset condition.
            on_heater <= '0';
        elsif rising_edge(clock) then
            state <= next_state;          -- State is synchronised to the clock.
            on_cooler <= next_on_cooler;  -- Outputs are synchronised to the clock and state.
            on_heater <= next_on_heater;
        end if;
    end process;

    --
    -- Next State Logic
    --
    process(state, temperature)
        variable i_temperature: integer;  -- ADDED for numeric comparisons.
    begin
        i_temperature := to_integer(signed(temperature));  -- I've assumed this is a signed temperature.
        case STATE is
            when S1 =>
                if i_temperature > TEMPERATURE_P35 then
                    next_state <= S2;
                elsif i_temperature < TEMPERATURE_P15 then
                    next_state <= S3;
                else
                    next_state <= S1;  -- ADDED to prevent inferred latch.
                end if;
            when S2 =>
                if i_temperature < TEMPERATURE_P25 then
                    next_state <= S1;
                else
                    next_state <= S2;  -- ADDED to prevent inferred latch.
                end if;
            when S3 =>
                if i_temperature > TEMPERATURE_P30 then
                    next_state <= S1;
                else
                    next_state <= S3;  -- ADDED to prevent inferred latch.
                end if;
            when others =>
                next_state <= S1;
        end case;
    end process;

    --
    -- Next Outputs Logic
    --
    process(next_state)
    begin
        case next_state is
            when S1 =>
                next_on_cooler <= '0';
                next_on_heater <= '0';
                enable_cooler <= '0';
            when S2 =>
                next_on_cooler <= '1';
                next_on_heater <= '0';
                enable_cooler <= '1';  -- ADDED to enable cooler when MainController is in state S2.
            when S3 =>
                next_on_cooler <= '0';
                next_on_heater <= '1';
                enable_cooler <= '0';
            when others =>
                next_on_cooler <= '0';
                next_on_heater <= '0';
                enable_cooler <= '0';
        end case;
    end process;

end architecture;

Инкубатор верхнего уровня

Это соединяет два конечных автомата вместе, т.е. Cooler и MainController.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Incubator is
    port
    (
        clock: in std_logic;
        reset: in std_logic;
        temperature: in std_logic_vector(7 downto 0);
        on_cooler: out std_logic;
        on_heater: out std_logic;
        crs: out std_logic_vector(3 downto 0)
    );
end entity;

architecture V1 of Incubator is

    signal enable_cooler: std_logic;  -- ADDED to enable cooler when MainController is in state S2.

    component MainController is
        port
        (
            clock: in std_logic;
            reset: in std_logic;
            temperature: in std_logic_vector(7 downto 0);
            on_cooler: out std_logic;
            on_heater: out std_logic;
            enable_cooler: out std_logic
        );
    end component;

    component Cooler is
        port
        (
            clock: in std_logic;
            reset: in std_logic;
            enable: in std_logic;  -- ADDED: From cooler enable signal of modified left-hand state machine.
            temperature: in std_logic_vector(7 downto 0);  -- I've assumed this is a signed temperature.
            crs: out std_logic_vector(3 downto 0)
        );
    end component;

begin

    MC: MainController
        port map
        (
            clock => clock,
            reset => reset,
            temperature => temperature,
            on_cooler => on_cooler,
            on_heater => on_heater,
            enable_cooler => enable_cooler
        );

    CLR: Cooler
        port map
        (
            clock => clock,
            reset => reset,
            enable => enable_cooler,
            temperature => temperature,
            crs => crs
        );

end architecture;

Испытательный стенд

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Incubator_TB is
end entity;

architecture V1 of Incubator_TB is

    constant CLOCK_PERIOD: time := 50 ns;

    signal halt_sys_clock: boolean := false;

    signal clock: std_logic := '0';
    signal reset: std_logic := '0';
    signal temperature: std_logic_vector(7 downto 0);
    signal on_cooler: std_logic;
    signal on_heater: std_logic;
    signal crs: std_logic_vector(3 downto 0);

    component Incubator is
        port
        (
            clock: in std_logic;
            reset: in std_logic;
            temperature: in std_logic_vector(7 downto 0);
            on_cooler: out std_logic;
            on_heater: out std_logic;
            crs: out std_logic_vector(3 downto 0)
        );
    end component;

begin

    ClockGenerator:
    process
    begin
        while not halt_sys_clock loop
            wait for CLOCK_PERIOD / 2.0;
            clock <= not clock;
        end loop;
        wait;
    end process ClockGenerator;

    Stimulus:
    process
    begin
        reset <= '0';
        temperature <= std_logic_vector(to_unsigned(38, temperature'length));
        wait for CLOCK_PERIOD / 4.0;
        reset <= '1';
        wait for CLOCK_PERIOD;
        reset <= '0';
        wait for CLOCK_PERIOD * 4;
        temperature <= std_logic_vector(to_unsigned(12, temperature'length));
        wait for CLOCK_PERIOD * 4;
        temperature <= std_logic_vector(to_unsigned(38, temperature'length));
        wait for CLOCK_PERIOD * 4;
        temperature <= std_logic_vector(to_unsigned(43, temperature'length));
        wait for CLOCK_PERIOD * 4;
        temperature <= std_logic_vector(to_unsigned(48, temperature'length));
        wait for CLOCK_PERIOD * 4;
        temperature <= std_logic_vector(to_unsigned(10, temperature'length));
        wait for CLOCK_PERIOD * 4;
        halt_sys_clock <= true;
        wait;
    end process;
    
    INC: Incubator
        port map
        (
            clock => clock,
            reset => reset,
            temperature => temperature,
            on_cooler => on_cooler,
            on_heater => on_heater,
            crs => crs
        );

end architecture;

Моделирование

Simulation of incubator Figure 2 – Simulation of incubator


Quartus RTL Schematics

Incubator RTL Figure 3 – Incubator RTL


Main Controller RTL Figure 4 – Main Controller RTL


Кулер RTL Рисунок 5 - Охладитель RTL


...