quartus latch защелка
Рассмотрим код, написанный для реализации задачи «бегающих» светодиодов с помощью ПЛИС Altera Cyclone IV в САПР Quartus Prime.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity running_LEDs is
port (
clk : in std_logic;
led : out std_logic_vector(7 downto 0)
);
end running_LEDs;
architecture rtl of running_LEDs is
signal count : std_logic_vector(25 downto 0) := (others => '0');
signal temp : std_logic_vector(7 downto 0) := (0 => '1', others => '0');
signal rst : std_logic := '0';
begin
process (clk)
begin
if (rst = '1') then
count <= (others => '0');
elsif (rising_edge(clk)) then
count <= count + 1;
end if;
end process;
process (count)
begin
if count = 50000000 then
rst <= '1';
temp(7 downto 0) <= temp (6 downto 0) & temp(7);
else
rst <= '0';
end if;
end process;
led <= temp;
end rtl;
Идея программы заключалась в создании 8-битного регистра – «temp», а также счетчика – «count», который считает до 50 миллионов тактов и сбрасывается с помощью сигнала «rst». При каждом обнулении счетчика «зажженный» светодиод сдвигается влево. Правильность функционала подтверждает проведенное моделирование в ModelSim (рисунок 1).
Рисунок 1 Моделирование программы
С помощью инструмента RTL Viewer представим данный проект в графическом виде. На рисунке 2 можно заметить, что в программе образуются защелки – «temp». Как известно, не все программы-синтезаторы хорошо справляются с ними. В данном случае Quartus неверно инициализирует защелку, определяя начальное значение переменной «temp» как “11111111” вместо “00000001”. Используя логический анализатор SignalTap, подтверждаем это (рисунок 3). В результате, значение «temp» не будет меняться при каждом обнулении счетчика, как было задумано изначально.
Рисунок 2 – Графическая реализация проекта
Рисунок 3 – Анализ сигналов, полученный при помощи SignalTap
В конечном итоге, восемь светодиодов светятся одновременно (рисунок 4).
Рисунок 4 – Реализация программы на ПЛИС Altera Cyclone IV
Таким образом, из-за использования защелки в коде Quartus неверно выполняет программу. Исправить это можно, заменив защелку на D-триггер. Пример кода приведен ниже.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity running_LEDs is
port (
clk : in std_logic;
led : out std_logic_vector(7 downto 0)
);
end running_LEDs;
architecture rtl of running_LEDs is
signal count : std_logic_vector(25 downto 0) := (others => '0');
signal temp : std_logic_vector(7 downto 0) := (0 => '1', others => '0');
signal rst : std_logic := '0';
begin
process (clk)
begin
if (rst = '1') then
count <= (others => '0');
elsif (rising_edge(clk)) then
count <= count + 1;
end if;
end process;
process (clk)
begin
if (rising_edge(clk)) then
if count = 50000000 then
rst <= '1';
temp(7 downto 0) <= temp (6 downto 0) & temp(7);
else
rst <= '0';
end if;
end if;
end process;
led <= temp;
end rtl;