«…лишь недалекие люди боятся конкуренции, а люди подлинного творчества ценят общение с каждым талантом…» А. Бек, Талант.

ПЦУСБ/Лекция 4

Материал из Wiki
Перейти к: навигация, поиск
Лекции ПЦУСБ

Лекции

Практические
Тесты

Лабораторные

Доп. материалы

Заголовок
Цифровые автоматы
Автор
Авдеев Н.А.
Нижний колонтитул
ПЦУСБ/Лекция 4
Дополнительный нижний колонтитул
Авдеев Н.А., 18:44, 25 марта 2014


Содержание

Слайд: Провести анализ схемы (1)

Book-ddu-risx5-42.png


Слайд: Провести анализ схемы (2)

Book-ddu-risx5-57.png


Слайд: Абстра́ктный автома́т

  • Абстра́ктный автома́т (в теории алгоритмов) — математическая абстракция, модель дискретного устройства, имеющего один вход, один выход и в каждый момент времени находящегося в одном состоянии из множества возможных. На вход этому устройству поступают символы одного алфавита, на выходе оно выдаёт символы (в общем случае) другого алфавита.


Формально абстрактный автомат определяется как пятерка
где
  • S — конечное множество состояний автомата,
  • X, Y — конечные входной и выходной алфавиты соответственно, из которых формируются строки, считываемые и выдаваемые автоматом,
  • — функция переходов,
  • — функция выходов.


Слайд: Автомат Мили

Avtomat-mili.png
  • Следующее состояние = F (текущее состояние, вход)
  • Выход = G (текущее состояние, вход)

Слайд: Автомат Мура

Avtomat-mura.png
  • Следующее состояние = F (текущее состояние, вход)
  • Выход = G (текущее состояние)

Слайд: Литература по построению автоматов

  • Потемкин И.С. Функциональные узлы цифровой автоматики. – 1988, 320 с.
  • Д. Уэйкерли Пректирование цифровых устройств. В 2-х томах / Том 2 — М., 2002 Т. 2. — 536 с. – глава 7 посвящена проектированию автоматов.
  • Бибило П.Н. Основы языка VHDL: Учебное пособие. – М.: Книжный дом «ЛИБРОКОМ», 2012. – 328 с. – Глава 4.3 посвящена описанию автоматов на VHDL

Слайд: Граф состояний и переходов

[svg]

Кодирование выходов
Состояние выхода Значение y[1:0]
y1 00
y2 10
y3 11


Кодирование состояний
Состояние Код
Q1 0001
Q2 0010
Q3 0100
Q4 1000

Слайд: Выбор состояний для выходов и кодирование состояний

  • Для хранения значения текущего состояния автомата используется 4-х разрядный регистр со сбросом в "0001" (код состояния Q1), который реализуется с помощью 4-х D-триггеров с асинхронными сбросом и установкой.

Слайд: Таблица переходов (таблица истинности логики переходов F)

  • таблица переходов представляет собой альтернативную запись исходного графа
Текущее состояние
state
Входы
автомата
Следующее состояние
next_state
Код Имя x[2] x[1] Код Имя
"0001" Q1 '1' "0010" Q2
"0001" Q1 '0' "0001" Q1
"0010" Q2 '1' '0' "0100" Q3
"0010" Q2 '1' "1000" Q4
"0010" Q2 '0' "0010" Q2
"1000" Q4 '1' "0001" Q1
"1000" Q4 '0' "1000" Q4
"0100" Q3 "0100" Q3

[svg]

Обозначения в таблице:

  • знак '–' - значение лог. '0' либо '1'

Слайд: Таблица истинности выходной логики G

Состояние
State[3:0]
Выход
y[1:0]
Имя Код Имя Код
Q1 "0001" y1 "00"
Q2 "0010" y2 "10"
Q3 "0100" y1 "00"
Q4 "1000" y3 "11"

Слайд: VHDL-модель автомата

Вариант 1 Вариант 2 Вариант 3
library ieee;
use ieee.std_logic_1164.all;
 
entity automat is
 
  port (
    x   : in  std_logic_vector(2 downto 1);
    rst : in  std_logic;
    clk : in  std_logic;
    y   : out std_logic_vector(1 downto 0));
 
end automat;
 
architecture beh of automat is
 
  signal state      : std_logic_vector(3 downto 0);
  signal next_state : std_logic_vector(3 downto 0);
 
begin  -- beh
 
  -- Задание логики переходов (F)
  next_state <=
    "0010" when state="0001" and x(1)='1' else
    "0001" when state="0001" else
    "0100" when state="0010" and x(2 downto 1) = "10" else
    "1000" when state="0010" and x(1)='1' else
    "0010" when state="0010" else
    "0001" when state="1000" and x(1)='1' else
    "1000" when state="1000" else
    "0100" when state="0100" else
    "0000";
 
  -- Задание выходной логики (G)
  y <=
    "00" when state="0001" else
    "10" when state="0010" else
    "00" when state="0100" else
    "11" when state="1000" else
    "00";
 
  -- регистр, хранящий текущее состояние
  p1: process (clk, rst)
  begin  -- process p1
    if rst = '1' then
      state <= "0001";
    elsif clk'event and clk = '1' then
      state <= next_state;
    end if;
  end process p1;
 
end beh;
architecture beh2 of automat is
 
  type state_type is (Q1, Q2, Q3, Q4);
  signal state      : state_type;
  signal next_state : state_type;
 
begin  -- beh
 
  c1: process (state, x) is
  begin  -- process c1
    case state is
      when Q1 =>
        y <= "00";
        if x(1)='1' then
          next_state <= Q2;
        else
          next_state <= Q1;
        end if;
      when Q2 =>
        y <= "10";
        if x = "10" then
          next_state <= Q3;
        elsif x(1) = '1' then
          next_state <= Q4;
        else
          next_state <= Q2;
        end if;
      when Q3 =>
        y <= "00";
        next_state <= Q3;
      when Q4 =>
        y <= "11";
        if x(1) = '1' then
          next_state <= Q1;
        else
          next_state <= Q4;
        end if;
      when others => null;
    end case;
  end process c1;
 
  -- регистр, хранящий текущее состояние
  p1: process (clk, rst)
  begin  -- process p1
    if rst = '1' then
      state <= Q1;
    elsif clk'event and clk = '1' then
      state <= next_state;
    end if;
  end process p1;
 
end beh2;
library ieee;
use ieee.std_logic_1164.all;
 
architecture beh3 of automat is
 
  type state_type is (Q1, Q2, Q3, Q4);
  signal state      : state_type;
 
begin  -- beh
 
  p1: process (clk, rst)
  begin  -- process p1
    if rst = '1' then
      state <= Q1;
    elsif clk'event and clk = '1' then
 
      if state = Q1 then
        if x(1)='1' then
          state <= Q2;
        end if;
 
      elsif state = Q2 then
 
        if x = "10" then
          state <= Q3;
        elsif x(1) = '1' then
          state <= Q4;
        end if;
 
      elsif state = Q3 then
 
      elsif state = Q4 then
 
        if x(1) = '1' then
          state <= Q1;
        end if;
 
      else   -- защита от сбоя
        state <= Q1;
 
      end if;
 
    end if;
  end process p1;
  -- Задание выходной логики (G)
  y <=
    "00" when state = Q1 else
    "10" when state = Q2 else
    "00" when state = Q3 else
    "11" when state = Q4 else
    "00";
 
end beh3;

Слайд: Последовательный оператор CASE

  • Последовательный — значит может использоваться только в process
case Выражение is
   when Значение =>
     Последовательные операторы
   when Значение [ | Значение ] =>
      Последовательные операторы
end case;
  • Значение может быть числом (литералом), простым выражением (например, a + b), диапазоном значений (1 to 10), ключевым словом others.


Примеры
case SEL is
  when "01"   => Z <= A;
  when "10"   => Z <= B;
  when others => Z <= 'X';
end case;
case INT_A is
  when 0      => Z <= A;
  when 1 to 3 => Z <= B;
  when 4|6|8  => Z <= C;
  when others => Z <= 'X';
end case;
Примеры ошибок
Nuvola apps error.png перекрытие диапазонов
case INT_A is
  when 0      => Z <= A;
  when 1 to 3 => Z <= B;
  when 2|6|8  => Z <= C;   -- illegal
  when others => Z <= 'X';
end case;
Nuvola apps error.png Диапазон для вектора задавать нельзя
signal VEC : unsigned(2 downto 0);
....
case VEC is
  when "000" to "010" 
               =>  Z <= A;   -- illegal
  when "111"   =>  Z <= B;
  when others  =>  Z <= 'X';
end case;


Слайд: Перечислимый тип (TYPE)

  • Перечислимый тип — это такой тип данных, при котором количество всех возможных значений конечно.
    • улучшение смысловой читаемости программы;
    • более четкий и простой визуальный контроль значений.
  • Наиболее часто перечислимый тип используется для обозначения состояний конечных автоматов.
  • Перечислимый тип объявляется путем перечисления названий элементов-значений.
  • Элементы перечислимого типа должны быть идентификаторами или символами, которые должны быть уникальными в пределах одного типа.
  • Повторное использование названий элементов в других перечислимых типах разрешается.
  • Объявление перечислимого типа имеет вид:
TYPE имя_типа IS ( название_элемента [, название_элемента] );
  • Пример
type State_type IS (stateA, stateB, stateC);
signal State : State_type;
. . .
State <= stateB
  • Примеры предопределенных перечислимых типов:
TYPE SEVERITY_LEVEL IS (NOTE, WARNING, ERROR, FAILURE);
TYPE BOOLEAN IS (FALSE, TRUE);
TYPE BIT IS ('0', '1');
TYPE STD_LOGIC IS ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-');
  • Любой перечислимый тип имеет внутреннюю нумерацию: первый элемент всегда имеет номер 0, второй - номер 1 и т.д. Порядок нумерации соответствует порядку перечисления.

Слайд: VHDL-модель тестбенча

library ieee;
use ieee.std_logic_1164.all;
 
entity tb is
 
end tb;
 
architecture beh of tb is
 
  component automat
    port (
      x   : in  std_logic_vector(2 downto 1);
      rst : in  std_logic;
      clk : in  std_logic;
      y   : out std_logic_vector(1 downto 0));
  end component;
  signal x   : std_logic_vector(2 downto 1);
  signal rst : std_logic;
  signal clk : std_logic := '0';
  signal y   : std_logic_vector(1 downto 0);
 
begin  -- beh
 
  automat_1: automat
    port map (
      x   => x,
      rst => rst,
      clk => clk,
      y   => y);
 
  clk <= not clk after 10 ns;
  rst <= '1', '0' after 30 ns,
         '1' after 400 ns, '0' after 405 ns;
 
  process
  begin  -- process
 
    x <= "00";
    wait for 55 ns;
    x <= "01";
    wait for 20 ns;
    x <= "01";
    wait for 20 ns;
    x <= "01";
    wait for 20 ns;
    x <= "01";
    wait for 40 ns;
    x <= "10";
    wait for 40 ns;
    x <= "11";
    wait for 40 ns;
    x <= "10";
    wait for 40 ns;
    x <= "01";
    wait;
  end process;
 
end beh;

Слайд: Временные диаграммы

Временные диаграммы проверки автоматов

Слайд: Словесное описание автомата

Панель ввода пароля

  • обеспечить возможность задания нового пароля по нажатию специальной кнопки и ввода старого пароля (пароль по умолчанию 000), а затем ввода нового. При неправильном вводе переходит в начальное состояние (ожидание ввода). При правильном старом пароле включить сигнал "доступ открыт", а после ввода нового пароля отключить сигнал "доступ открыт".
  • ввод пароля с клавиатуры (3х значное десятичное число от 000 до 999). Предусмотреть кнопку сброса введённого пароля (при неправильнном вводе).
  • после ввода 3 цифр система проверяет введённый пароль с внутренним значением:
    • если пароли совпадают, то включается светодиод "Доступ открыт" на 3 сек., после чего система переходит в режим ввода пароля
    • если пароли не совпадают, то включается звуковой сигнал "Доступ закрыт" на 0.5 сек., после чего система переходит в режим ввода пароля
    • если после ввода 1й или 2й цифры, следующая цифра (т.е. 2-я или 3я соответственно) не введены более чем через 5 секунд, то включается звуковой сигнал "Доступ закрыт" на 0.5 секунды

Слайд: Алгоритм

[svg]

Слайд: Таблица переходов :step

Элементы системы и управляющие сигналы (входы/выходы)

  • Входы
    • кнопка ввода пароля - сигнал SetPassword
    • цифровые кнопки 0-9 - сигналы DigitalKey[8 downto 0]
    • кнопка отмены ввода - сигнал Esc
    • сигналы (со счетчика) отсчитывающие 0.5, 3, 5 с - Dalay05s, Dalay3s, Dalay5s
    • сигнал синхронизации - clk (активный положительный фронт)
    • асинхронный сброс - RST
  • Выходы
    • управление трехразрядным семисегментным индикатором - Digits2[6:0], Digits1[6:0], Digits0[6:0] (реально Digits[6:0] и Index[2:0])
    • светодиод "Доступ открыт" - сигнал Open
    • Динамик - сигнал Speaker
    • Сигнал запуск отсчета паузы - StartCount

Слайд: Таблица переходов

Текущее состояние Событие (входы) Следующее состояние
Любое RST = 1 Начальное состояние (ожидание ввода)
Начальное состояние Нажата кнопка ввода пароля Режим смены пароля: ввод старого пароля
Начальное состояние Нажата цифровая кнопка Режим ввода пароля (для доступа) (1)
Начальное состояние Нажата кнопка Esc Начальное состояние
Режим смены пароля: ввод старого пароля (0) Ввод первой цифры Режим смены пароля: ввод старого пароля (1), отобразить введённую цифру
Режим смены пароля: ввод старого пароля (0) Прошло 5 с Начальное состояние
Режим смены пароля: ввод старого пароля (1) Ввод второй цифры Режим смены пароля: ввод старого пароля (2), отобразить введённую цифру
Режим смены пароля: ввод старого пароля (1) Прошло 5 с Начальное состояние
Режим смены пароля: ввод старого пароля (2) Ввод третьей цифры Режим смены пароля:
  • если пароль правильный - включить светодиод "доступ открыт" и перейти к "ввод нового пароля (0)"
  • если пароль неправильный - перейти в "Начальное состояние"
Режим смены пароля: ввод старого пароля (0-2) Нажата кнопка Esc Начальное состояние

Слайд: Таблица переходов (2)

Текущее состояние Событие (входы) Следующее состояние
Режим ввода пароля (для доступа) (1) Ввод второй цифры Режим ввода пароля (для доступа) (2)
Режим ввода пароля (для доступа) (2) Ввод третьей цифры Переход в состояние:
  • включение "доступ открыт", если пароль правильный
  • включение сигнала "Доступ закрыт", если пароль не правильный
Режим ввода пароля (для доступа) (1 или 2) Прошло 5 с Начальное состояние
доступ открыт Прошло 3 с Начальное состояние
Доступ закрыт Прошло 0.5 с Начальное состояние

Слайд: Тоже самое в виде графа

[svg]

Слайд: Схема обработки нажатия клавиши

Рисунок - Схема обработки нажатия кнопки Esc (Edit)


Таблица истинности комбинационного блока
EscPress_i1 EscPress_i0 EscPress_i
0 0 0
0 1 0
1 0 1
1 1 0
Логическое выражение
EscPress_i <= EscPress_i1 and not EscPress_i0


Слайд: Схема обработки нажатия клавиши (VHDL)

  signal EscPress_i0 : std_logic;
  signal EscPress_i1 : std_logic;
  signal EscPress_i  : std_logic;
  signal EscPress    : std_logic;
 
begin  -- architecture beh
 
  -- обработка нажатия клавиш
  trig: process (clk, rst) is
  begin  -- process trig
    if rst = '1' then
 
      -- асинхронный сброс
      EscPress <= '0';
      EscPress_i0 <= '0';
      EscPress_i1 <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      EscPress_i1 <= Esc;
      EscPress_i0 <= EscPress_i1;
      EscPress <= EscPress_i;
 
    end if;
  end process trig;
 
  EscPress_i <= EscPress_i1 and not EscPress_i0;

Слайд: Блоки обработки нажатия клавиш

Рисунок - Блоки обработки нажатия кнопок (Edit)


Слайд: Блок обработки нажатия цифровых клавиш

Рисунок - Блок обработки нажатия цифровых клавиш (Edit)
  • Bombilla amarilla - yellow Edison lamp.png не согласованы строб нажатия и код клавиши во времени

Слайд: Блок обработки нажатия цифровых клавиш (VHDL)

  InputCodePress <=
    '0' when KeyCode = "1111" else
    '1';
 
  p_KeyCode: process (clk, rst) is
  begin
    if rst = '1' then
      KeyCode <= "1111";
    elsif clk'event and clk = '1' then  -- rising clock edge
      KeyCode <= KeyCode_i;
    end if;
  end process p_KeyCode;
 
  KeyCode_i <=
    "0000" when DigitalKey(0) = '1' else
    "0001" when DigitalKey(1) = '1' else
    "0010" when DigitalKey(2) = '1' else
    "0011" when DigitalKey(3) = '1' else
    "0100" when DigitalKey(4) = '1' else
    "0101" when DigitalKey(5) = '1' else
    "0110" when DigitalKey(6) = '1' else
    "0111" when DigitalKey(7) = '1' else
    "1000" when DigitalKey(8) = '1' else
    "1001" when DigitalKey(9) = '1' else
    "1111";

Слайд: Граф переходов

[svg]


Слайд: Режимы работы счетчика

[svg]

  signal count : unsigned(12 downto 0);
  signal Delay05s, Delay3s, Delay5s :  boolean;
 
begin  -- architecture beh
 
  -- описание счетчика для отсчета времени
  p_count: process (clk, rst) is
  begin  -- process p_count
    if rst = '1' then 
      count <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      if EscPress = '1' or SetPasswordPress = '1' or DigitalKeyPress = '1' or Delay5s then
        count <= (others => '0');
      else
        count <= count + 1;
      end if;
    end if;
  end process p_count;
 
  Delay05s <= (count = 500);            -- отсчет 0.5 с
  Delay3s  <= (count = 3000);           -- отсчет 3 с
  Delay5s  <= (count = 5000);           -- отсчет 5 с
  • тип boolean (Delay05s)
  • тип unsigned (count)

Слайд: Режимы работы регистра ввода

[svg]

Слайд: Режимы работы регистра ввода (VHDL)

  signal KeyCode_i, KeyCode : std_logic_vector(3 downto 0);
  type STATE_TYPE is (
    Start
    , InputPassword1
    , InputPassword2
    , InputPasswordCompare
    , OpenAccess
    , InputPasswordNotCompared
    );
  signal state, next_state : STATE_TYPE;
 
  type WORD_TYPE is array (1 to 3) of std_logic_vector(3 downto 0);
  signal Password  :  WORD_TYPE := ("0001", "0010", "0011");
  signal InputCode :  WORD_TYPE;
 
begin
 
  p2: process (clk, rst) is
  begin
    if rst = '1' then
      InputCode <= ("0000", "0000", "0000");
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      if state = Start then
        if DigitalKeyPress = '1' then
          InputCode(1) <= KeyCode;
        end if;
      elsif state = InputPassword1 then
        if DigitalKeyPress = '1' then
          InputCode(2) <= KeyCode;
        end if;
      elsif state = InputPassword2 then
        if DigitalKeyPress = '1' then
          InputCode(3) <= KeyCode;
        end if;
      else
        InputCode <= ("0000", "0000", "0000");
      end if;
    end if;
  end process p2;

Слайд: VHDL-модель

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
--entity block1 is
 
--  port (
--    SetPassword : in  std_logic;
--    DigitalKey  : in  std_logic_vector(9 downto 0);
--    Esc         : in  std_logic;
--    clk         : in  std_logic;        -- синхросигнал 25 МГц
--    rst         : in  std_logic;
--    LedOpen     : out std_logic;
--    Speaker     : out std_logic);
 
--end entity block1;
 
architecture beh2 of block1 is
 
  signal count : unsigned(12 downto 0);
  signal KeyCode_i, KeyCode : std_logic_vector(3 downto 0);
  type STATE_TYPE is (
    Start
    , InputPassword1
    , InputPassword2
    , InputPasswordCompare
    , OpenAccess
    , InputPasswordNotCompared
    );
  signal state, next_state : STATE_TYPE;
 
  type WORD_TYPE is array (1 to 3) of std_logic_vector(3 downto 0);
  signal Password  :  WORD_TYPE := ("0001", "0010", "0011");
  signal InputCode :  WORD_TYPE;
  signal Delay05s, Delay3s, Delay5s :  boolean;
 
  signal InputCodePress    : std_logic;
  signal InputCodePress_i0 : std_logic;
  signal InputCodePress_i1 : std_logic;
  signal InputCodePress_i  : std_logic;
  signal DigitalKeyPress   : std_logic;
 
  signal SetPasswordPress_i0 : std_logic;
  signal SetPasswordPress_i1 : std_logic;
  signal SetPasswordPress_i  : std_logic;
  signal SetPasswordPress    : std_logic;
 
  signal EscPress_i0 : std_logic;
  signal EscPress_i1 : std_logic;
  signal EscPress_i  : std_logic;
  signal EscPress    : std_logic;
 
begin  -- architecture beh
 
  -- обработка нажатия клавиш
  trig: process (clk, rst) is
  begin  -- process trig
    if rst = '1' then
      -- асинхронный сброс
 
      EscPress <= '0';
      EscPress_i0 <= '0';
      EscPress_i1 <= '0';
 
      SetPasswordPress <= '0';
      SetPasswordPress_i0 <= '0';
      SetPasswordPress_i1 <= '0';
 
      DigitalKeyPress <= '0';
      InputCodePress_i0 <= '0';
      InputCodePress_i1 <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      InputCodePress_i1 <= InputCodePress;
      InputCodePress_i0 <= InputCodePress_i1;
      DigitalKeyPress <= InputCodePress_i;
 
      EscPress_i1 <= Esc;
      EscPress_i0 <= EscPress_i1;
      EscPress <= EscPress_i;
 
      SetPasswordPress_i1 <= SetPassword;
      SetPasswordPress_i0 <= SetPasswordPress_i1;
      SetPasswordPress <= SetPasswordPress_i;
 
    end if;
  end process trig;
 
  SetPasswordPress_i <= SetPasswordPress_i1 and not SetPasswordPress_i0 ;
  EscPress_i <= EscPress_i1 and not EscPress_i0;
  InputCodePress_i <= InputCodePress_i1 and not InputCodePress_i0;
 
  -- описание счетчика для отсчета времени
  p_count: process (clk, rst) is
  begin  -- process p_count
    if rst = '1' then 
      count <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      if EscPress = '1' or SetPasswordPress = '1' or DigitalKeyPress = '1' or Delay5s then
        count <= (others => '0');
      else
        count <= count + 1;
      end if;
    end if;
  end process p_count;
 
  Delay05s <= (count = 500);            -- отсчет 0.5 с
  Delay3s  <= (count = 3000);           -- отсчет 3 с
  Delay5s  <= (count = 5000);           -- отсчет 5 с
 
  p_state: process (clk, rst) is
  begin
    if rst = '1' then
      state <= Start;
    elsif clk'event and clk = '1' then  -- rising clock edge
      state <= next_state;
    end if;
  end process p_state;
 
  p_next_state: process (state, EscPress, SetPasswordPress, DigitalKeyPress, Delay5s, Delay3s, Delay05s) is
  begin
    case state is
 
      when Start =>
 
        if DigitalKeyPress = '1' then
          next_state <= InputPassword1;
        else
          next_state <= Start;
        end if;
 
      when InputPassword1 =>
 
        if DigitalKeyPress = '1' then
          next_state <= InputPassword2;
        elsif EscPress = '1' or Delay5s then
          next_state <= Start;
        else
          next_state <= InputPassword1;
        end if;
 
      when InputPassword2 =>
 
        if DigitalKeyPress = '1' then
          next_state <= InputPasswordCompare;
        elsif EscPress = '1' or Delay5s then
          next_state <= Start;
        else
          next_state <= InputPassword2;
        end if;
 
      when InputPasswordCompare =>
 
        if InputCode = Password then
          next_state <= OpenAccess;
        else
          next_state <= InputPasswordNotCompared;
        end if;
 
      when OpenAccess =>
 
        if Delay3s then
          next_state <= Start;
        end if;
 
      when InputPasswordNotCompared =>
 
        if Delay05s then
          next_state <= Start;
        end if;
 
      when others =>
        next_state <= Start;
    end case;
  end process p_next_state;
 
  LedOpen <=
    '1' when state = OpenAccess else
    '0';
 
  Speaker <=
    '1' when state = InputPasswordNotCompared else
    '0';
 
  p2: process (clk, rst) is
  begin
    if rst = '1' then
      InputCode <= ("0000", "0000", "0000");
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      if state = Start then
        if DigitalKeyPress = '1' then
          InputCode(1) <= KeyCode;
        end if;
      elsif state = InputPassword1 then
        if DigitalKeyPress = '1' then
          InputCode(2) <= KeyCode;
        end if;
      elsif state = InputPassword2 then
        if DigitalKeyPress = '1' then
          InputCode(3) <= KeyCode;
        end if;
      else
        InputCode <= ("0000", "0000", "0000");
      end if;
    end if;
  end process p2;
 
  InputCodePress <=
    '0' when KeyCode = "1111" else
    '1';
 
  p_KeyCode: process (clk, rst) is
  begin
    if rst = '1' then
      KeyCode <= "1111";
    elsif clk'event and clk = '1' then  -- rising clock edge
      KeyCode <= KeyCode_i;
    end if;
  end process p_KeyCode;
 
  KeyCode_i <=
    "0000" when DigitalKey(0) = '1' else
    "0001" when DigitalKey(1) = '1' else
    "0010" when DigitalKey(2) = '1' else
    "0011" when DigitalKey(3) = '1' else
    "0100" when DigitalKey(4) = '1' else
    "0101" when DigitalKey(5) = '1' else
    "0110" when DigitalKey(6) = '1' else
    "0111" when DigitalKey(7) = '1' else
    "1000" when DigitalKey(8) = '1' else
    "1001" when DigitalKey(9) = '1' else
    "1111";
 
end architecture beh2;


Слайд: VHDL-модель тестбенча

library ieee;
use ieee.std_logic_1164.all;
 
-------------------------------------------------------------------------------
 
entity block1_tb is
 
end entity block1_tb;
 
-------------------------------------------------------------------------------
 
architecture tb of block1_tb is
 
  -- component ports
  signal SetPassword : std_logic;
  signal DigitalKey  : std_logic_vector(9 downto 0);
  signal Esc         : std_logic;
  signal rst         : std_logic;
  signal LedOpen     : std_logic;
  signal Speaker     : std_logic;
 
  signal Clk : std_logic := '1';
 
begin  -- architecture tb
 
  -- component instantiation
  DUT: entity work.block1(beh2)
    port map (
      SetPassword => SetPassword,
      DigitalKey  => DigitalKey,
      Esc         => Esc,
      clk         => clk,
      rst         => rst,
      LedOpen     => LedOpen,
      Speaker     => Speaker);
 
  -- clock generation
  Clk <= not Clk after 5 ns;
 
  -- waveform generation
  WaveGen_Proc: process
  begin
    -- insert signal assignments here
 
    SetPassword <= '0';
    DigitalKey <= (others => '0');
    Esc        <= '0';
    rst        <= '1';
 
 
    wait for 21 ns;
    rst        <= '0';
 
    wait for 10 ns;
    DigitalKey(1) <= '1';
    wait for 50 ns;
    DigitalKey(1) <= '0';
    Esc <= '0';
    wait for 50 ns;
    DigitalKey(2) <= '1';
    wait for 50 ns;
    DigitalKey(2) <= '0';
    wait for 50 ns;
    Esc <= '0';
    DigitalKey(3) <= '1';
    wait for 50 ns;
    DigitalKey(3) <= '0';
 
    wait for 10 ns;
    wait;
  end process WaveGen_Proc;
 
end architecture tb;


Слайд: Временные диаграммы

Временные диаграммы работы тестбенча

Слайд: VHDL-модель (другой вариант описания)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity block1 is
 
  port (
    SetPassword : in  std_logic;
    DigitalKey  : in  std_logic_vector(9 downto 0);
    Esc         : in  std_logic;
    clk         : in  std_logic;        -- синхросигнал 25 МГц
    rst         : in  std_logic;
    LedOpen     : out std_logic;
    Speaker     : out std_logic);
 
end entity block1;
 
architecture beh of block1 is
 
  signal count : unsigned(12 downto 0);
  signal KeyCode : std_logic_vector(3 downto 0);
-- access denied
-- open access
  type STATE_TYPE is (
    Start
    , InputPassword1
    , InputPassword2
    , InputPasswordCompare
    , OpenAccess
    , InputPasswordNotCompared
    );
  signal state : STATE_TYPE;
--  type WORD_TYPE is array (3 downto 0) of std_logic;
  type WORD_TYPE is array (1 to 3) of std_logic_vector(3 downto 0);
--  signal password : array (1 to 3) of WORD_TYPE;
  signal Password  :  WORD_TYPE := ("0000", "0000", "0000");
  signal InputCode :  WORD_TYPE;
  signal Delay05s, Delay3s, Delay5s :  boolean;
 
 
begin  -- architecture beh
 
  p1: process (clk, rst) is
  begin  -- process p1
    if rst = '1' then  
      count <= (others => '0');
      state <= Start;
      LedOpen <= '0';
      Speaker <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      count <= count + 1;               -- непрерывный отсчет времени
 
      if state = Start then
        LedOpen <= '0';
        Speaker <= '0';
 
        if KeyCode /= "1111" then
          state <= InputPassword1;
          InputCode(1) <= KeyCode;
          count <= (others => '0');     -- сброс счетчика
        end if;
 
      elsif state = InputPassword1 then
        if KeyCode /= "1111" then
          state <= InputPassword2;
          InputCode(2) <= KeyCode;
          count <= (others => '0');     -- сброс счетчика
        end if;
 
      elsif state = InputPassword2 then
        if KeyCode /= "1111" then
          state <= InputPasswordCompare;
          InputCode(3) <= KeyCode;
          count <= (others => '0');     -- сброс счетчика
        end if;
 
      elsif state = InputPasswordCompare then
        if Password = InputCode then
          state <= OpenAccess;
          LedOpen <= '1';
        else
          state <= InputPasswordNotCompared;
          Speaker <= '1';
        end if;
 
        count <= (others => '0');     -- сброс счетчика
 
      elsif state = InputPasswordNotCompared then
        if Delay05s then
          Speaker <= '0';
          state <= Start;
 
        end if;
 
 
      elsif state = OpenAccess then
        if Delay3s then
          LedOpen <= '0';
          state <= Start;
 
        end if;
 
      else
        -- сброс в начальное состояние
        state <= Start;
      end if;
    end if;
 
    -- сброс в начальное состояние
    -- если 5 с не были нажаты кнопки
    -- или нажат Esc
    if Delay5s or Esc = '1' then
      state <= Start;
    end if;
 
  end process p1;
 
  Delay05s <= (count = 500);            -- отсчет 0.5 с
  Delay3s  <= (count = 3000);           -- отсчет 3 с
  Delay5s  <= (count = 5000);           -- отсчет 5 с
 
  KeyCode <=
    "0000" when DigitalKey(0) = '1' else
    "0001" when DigitalKey(1) = '1' else
    "0010" when DigitalKey(2) = '1' else
    "0011" when DigitalKey(3) = '1' else
    "0100" when DigitalKey(4) = '1' else
    "0101" when DigitalKey(5) = '1' else
    "0110" when DigitalKey(6) = '1' else
    "0111" when DigitalKey(7) = '1' else
    "1000" when DigitalKey(8) = '1' else
    "1001" when DigitalKey(9) = '1' else
    "1111";
 
end architecture beh;

Слайд: NEW