мой код vhdl для реализации некоторых fsm работает неправильно

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)

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

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


person fatecsa    schedule 06.08.2020    source источник
comment
Может быть, вы могли бы задать конкретные вопросы? (can anyone tell me that where am i doing wrong? не является конкретным и fsm работает некорректно.) Немного поискав и устранив неполадки, вы обнаружите отсутствует тактовый интервал для перехода к состоянию S3 в тестовой среде. (Вы должны иметь возможность добавить сигналы инкубатора к вашей волне, как это сделано здесь. Вы обнаружите, что просто не достигаете S3, потому что температура изменилась на более высокое значение.)   -  person    schedule 07.08.2020
comment
Реляционные операторы для std_logic_vector, предоставляемые пакетом std_logic_1164, не являются числовыми.   -  person    schedule 08.08.2020
comment
ты имеешь в виду, что я неправильно устанавливал сигналы в тестовом стенде? @user1155120   -  person fatecsa    schedule 10.08.2020
comment
о вашем втором комментарии, что вы имеете в виду, мешает ли он выводам? @user1155120   -  person fatecsa    schedule 10.08.2020
comment
Ваши предыдущие комментарии не содержат понятных вопросов. В тестовом стенде вам не хватает тактового цикла между падением температуры ниже порогового значения и повышением ее выше порогового значения, необходимого для перехода от S1 к S3, что приводит к тому, что on_heater = '1' не появляется, что-то обнаруживаемое при устранении неполадок. Если › не является числовой операцией, она будет основана на сравнении элементов, включая метазначения, что может привести к несоответствию симуляции и синтеза (вероятно, здесь это не так, предостережение - используйте арифметические реляционные операторы). В вашем дизайне нет ничего принципиально неправильного.   -  person    schedule 11.08.2020
comment
понятно, большое вам спасибо. извините, я просто не смог установить какой-либо симулятор, поэтому я пишу код онлайн, поэтому я не могу хорошо устранять неполадки .. что вы имеете в виду .. я должен заменить › на что-то еще? потому что › сам по себе является арифметическим оператором отношения, не так ли? и, кстати, вы знаете бесплатный онлайн-синтезатор? @user1155120   -  person fatecsa    schedule 11.08.2020
comment
Обычные операторы упорядочивания предопределены для любого типа одномерного массива (семантически сразу после объявления типа) и сопоставляются со значением позиции элемента в соответствии со стандартом IEEE Std 1076-2008 9.2.3 Реляционные операторы. Присвоение числового значения литералам перечисления в противном случае требует объявлений функций, предоставляющих перегруженные операторы, обычно в математических пакетах.   -  person    schedule 11.08.2020


Ответы (1)


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

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

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

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

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

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

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

Конечный автомат кулера Рисунок 1. Конечный автомат кулера


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;

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

Моделирование инкубатора Рисунок 2 – Моделирование инкубатора


Схемы Quartus RTL

Инкубатор RTL Рисунок 3 – Инкубатор RTL


Главный контроллер RTL Рисунок 4. Главный контроллер RTL


Cooler RTL Рисунок 5 – Cooler RTL


person tim    schedule 09.08.2020
comment
большое спасибо, я очень ценю это!! кстати, когда температура 38 во второй раз, разве crs не должно быть сразу 4? или в этом есть какая-то логика? потому что это должно быть 4 при частоте около 576000 пс .. @tim - person fatecsa; 10.08.2020
comment
@fatecsa, это связано с тем, как я интерпретировал ваше утверждение: правый fsm активируется только тогда, когда левый fsm находится в состоянии s2. Я добавил сигнал включения, чтобы добиться этого. Если вы полностью исключите логику включения, я думаю, вы получите то, что описываете, но два конечных автомата будут работать одновременно и независимо, что повлияет на то, как Cooler переходит из S_3 в S_OUT при изменении температуры с 48 до 10. - person tim; 11.08.2020
comment
@fatecsa, я изменил логику включения. Раньше это был синхронный вывод MainController, поэтому добавлялся дополнительный такт. Теперь это асинхронный сигнал, который будет синхронизирован в пределах Cooler. - person tim; 11.08.2020
comment
буквально большое спасибо, так вы имеете в виду, что предыдущий код был ответом на сам вопрос? когда вопрос говорит о том, что правая fsm активируется только тогда, когда левая fsm находится в состоянии 2, означает ли это, что должна быть задержка, которая была в моделировании предыдущего кода? и кстати, вы знаете, можно ли синтезировать этот код, потому что у меня просто нет синтезатора, я имею в виду, что я просто не мог его установить. - person fatecsa; 11.08.2020
comment
Я думаю, было бы точнее сказать, что я неправильно истолковал ваш первоначальный вопрос. Думаю, что второй вариант без задержки правильный. И его можно синтезировать, по крайней мере, в Quartus. Я обновлю свой пост схемами Quartus. - person tim; 11.08.2020
comment
Большое спасибо за вашу помощь, я очень ценю это !! @Тим - person fatecsa; 11.08.2020