Задача
Определять направление вращения и вести счёт положения вала.
Тип схемы: Синхронная схема: синхронизаторы каналов и счётчик со знаком.
Модуль: quad_decoder. Среда: Quartus, Vivado, ISE или свободный GHDL для моделирования.
Теорию по языку смотрите в статье VHDL — язык описания аппаратуры,
по самим микросхемам — на странице ПЛИС.
Алгоритм
- Пропустить оба канала через синхронизаторы.
- Обнаружить фронт канала A детектором фронта.
- В этот момент прочитать канал B: его уровень задаёт направление.
- Увеличить или уменьшить счётчик положения.
Код на VHDL
Код проверен компилятором GHDL: проходит анализ и элаборацию без ошибок и предупреждений. Скачать: v19.vhd
--=====================================================
-- Проект 19. Декодер квадратурного энкодера
-- По двум сигналам со сдвигом фаз определяем
-- направление вращения и ведём счёт положения.
--=====================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity quad_decoder is
port (
clk : in std_logic;
rst : in std_logic;
a, b : in std_logic; -- каналы энкодера
position : out std_logic_vector(15 downto 0);
cw : out std_logic; -- импульс: по часовой
ccw : out std_logic -- импульс: против
);
end entity quad_decoder;
architecture rtl of quad_decoder is
signal a_sync, b_sync : std_logic_vector(2 downto 0) := "000";
signal pos : signed(15 downto 0) := (others => '0');
begin
process (clk, rst)
begin
if rst = '1' then
pos <= (others => '0');
a_sync <= "000";
b_sync <= "000";
cw <= '0';
ccw <= '0';
elsif rising_edge(clk) then
-- синхронизация и запоминание прошлого состояния
a_sync <= a_sync(1 downto 0) & a;
b_sync <= b_sync(1 downto 0) & b;
cw <= '0';
ccw <= '0';
-- реагируем на фронт канала A
if a_sync(2) = '0' and a_sync(1) = '1' then
if b_sync(1) = '0' then
pos <= pos + 1; -- B отстаёт — вращение вперёд
cw <= '1';
else
pos <= pos - 1; -- B опережает — назад
ccw <= '1';
end if;
end if;
end if;
end process;
position <= std_logic_vector(pos);
end architecture rtl;
Пояснения
- Счётчик объявлен типом
signed, поэтому корректно работает с отрицательными значениями при вращении назад. - Синхронизация каналов обязательна: энкодер — механическое устройство, полностью асинхронное относительно тактовой сетки.
- Схема считает по одному фронту канала A. Учитывая оба фронта и оба канала, разрешение можно увеличить вчетверо.
Что дальше
Следующие проекты — в разделе проекты на VHDL. Сравнить подход с языком Verilog можно в статье Verilog, а разобраться в устройстве самих кристаллов — в статье ПЛИС: FPGA и CPLD.