Поскольку предполагается, что вы проектируете только правый конечный автомат (кулер), вам следует сосредоточиться на этом, отдельном от левого конечного автомата (главного контроллера).
Поговорите с вашим коллегой кто разрабатывает главный контроллер для добавления вывода под названием enable_cooler
для включения конечного автомата кулера. Сущность Incubator
может включать в себя две сущности с именами MainController
и Cooler
.
Я выделил логи c более прохладного конечного автомата в отдельную сущность под названием Cooler
. Это в трех процессах, которые поддерживают синхронизацию выходов как с часами, так и с состоянием:
- регистр состояния и регистр выходов.
- логика следующего состояния c.
- Следующие выходы Logi c.
Я также добавил несколько предложений else
для предотвращения предполагаемых защелок и добавил некоторые константы, чтобы сделать его более читаемым и поддерживаемым.
Конечный автомат кулера
Диаграмма состояний
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;
Моделирование
Figure 2 – Simulation of incubator
Quartus RTL Schematics
Figure 3 – Incubator RTL
Figure 4 – Main Controller RTL
Кулер RTL Рисунок 5 - Охладитель RTL