ПЦУСБ/Лекция 4 — различия между версиями
Материал из Wiki
< ПЦУСБ
ANA (обсуждение | вклад) м (→Слайд: Словесное описание автомата) |
ANA (обсуждение | вклад) м (→Слайд: Автомат Мили) |
||
| (не показаны 42 промежуточные версии 1 участника) | |||
| Строка 15: | Строка 15: | ||
[[Файл:Book-ddu-risx5-57.png|center]] | [[Файл:Book-ddu-risx5-57.png|center]] | ||
| + | |||
| + | |||
| + | == Слайд: Абстра́ктный автома́т == | ||
| + | |||
| + | *[http://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82 '''Абстра́ктный автома́т'''] (в теории алгоритмов) — математическая абстракция, модель дискретного устройства, имеющего один вход, один выход и в каждый момент времени находящегося в одном состоянии из множества возможных. На вход этому устройству поступают символы одного алфавита, на выходе оно выдаёт символы (в общем случае) другого алфавита. | ||
| + | |||
| + | |||
| + | : Формально абстрактный автомат определяется как пятерка | ||
| + | |||
| + | :: <math>\boldsymbol{A = (S, X , Y, \delta , \lambda)},</math> | ||
| + | |||
| + | :где | ||
| + | :* S — конечное множество состояний автомата, | ||
| + | :* X, Y — конечные входной и выходной алфавиты соответственно, из которых формируются строки, считываемые и выдаваемые автоматом, | ||
| + | :* <math>\delta : S \times X \rightarrow S</math> — функция переходов, | ||
| + | :* <math>\lambda : S \times X \rightarrow Y</math> — функция выходов. | ||
| Строка 30: | Строка 46: | ||
* Следующее состояние = F (текущее состояние, вход) | * Следующее состояние = F (текущее состояние, вход) | ||
* {{Сн|Выход <nowiki>=</nowiki> G (текущее состояние)}} | * {{Сн|Выход <nowiki>=</nowiki> G (текущее состояние)}} | ||
| + | |||
| + | == Слайд: Литература по построению автоматов == | ||
| + | |||
| + | * Потемкин И.С. ''Функциональные узлы цифровой автоматики.'' – 1988, 320 с. | ||
| + | * {{книга | ||
| + | | автор = Д. Уэйкерли | ||
| + | | название = ''Пректирование цифровых устройств.'' В 2-х томах / Том 2 | ||
| + | | ссылка = http://www.ph4s.ru/books/elektronika/tom_2.rar | ||
| + | | город = М. | ||
| + | | издательство = | ||
| + | | страниц = 536 | ||
| + | | том = 2 | ||
| + | | isbn = | ||
| + | | год = 2002 | ||
| + | }} – глава 7 посвящена проектированию автоматов. | ||
| + | * Бибило П.Н. ''Основы языка VHDL: Учебное пособие.'' – М.: Книжный дом «ЛИБРОКОМ», 2012. – 328 с. – Глава 4.3 посвящена описанию автоматов на VHDL | ||
== Слайд: Граф состояний и переходов == | == Слайд: Граф состояний и переходов == | ||
| + | |||
| + | {| | ||
| + | | | ||
<graph> | <graph> | ||
| + | |||
digraph G { | digraph G { | ||
| − | node[color="red",shape="rectangle",style="rounded",fontsize= | + | node[color="red",shape="rectangle",style="rounded",fontsize=12]; |
| + | edge[fontsize=10, style="bold"]; | ||
| − | + | { rank=source Q1 [label="Q1\n y1",style="rounded,bold"] } | |
| − | + | ||
| − | + | ||
| − | + | Q1 -> Q2 [label="x[1]=1", constraint=false] | |
| + | Q2 -> Q3 [label="x[1]=0, x[2]=1", constraint=false] | ||
| + | Q2 -> Q4 [label="x[1]=1"] | ||
| + | Q4 -> Q1 [label="x[1]=1", constraint=false] | ||
| + | |||
| + | |||
| + | edge [color="blue", style="dashed", fontsize=10]; | ||
| + | |||
| + | Q2 -> Q1 [label="RST=1"] | ||
| + | Q3 -> Q1 [label="RST=1"] | ||
| + | Q4 -> Q1 [label="RST=1"] | ||
| + | |||
| + | Q2 [label="Q2\n y2"] | ||
| + | Q3 [label="Q3\n y1"] | ||
| + | Q4 [label="Q4\n y3"] | ||
} | } | ||
</graph> | </graph> | ||
| + | | | ||
| + | {| class=standard align=center | ||
| + | |+ Кодирование выходов | ||
| + | ! Состояние выхода || Значение y[1:0] | ||
| + | |- | ||
| + | | y1 || 00 | ||
| + | |- | ||
| + | | y2 || 10 | ||
| + | |- | ||
| + | | y3 || 11 | ||
| + | |} | ||
| + | |||
| + | |||
| + | {| class=standard align=center | ||
| + | |+ Кодирование состояний | ||
| + | ! Состояние || Код | ||
| + | |- | ||
| + | | Q1 || 0001 | ||
| + | |- | ||
| + | | Q2 || 0010 | ||
| + | |- | ||
| + | | Q3 || 0100 | ||
| + | |- | ||
| + | | Q4 || 1000 | ||
| + | |} | ||
| + | |} | ||
| + | |||
| + | == Слайд: Выбор состояний для выходов и кодирование состояний == | ||
| + | |||
| + | <html><img src="https://docs.google.com/drawings/d/1ihtCm4nSz_DzSkTY3GN5mXHUEA6U95vSyryTTofTIIw/pub?w=907&h=296"></html> | ||
| + | |||
| + | * Для хранения значения текущего состояния автомата используется 4-х разрядный регистр со сбросом в "0001" (код состояния Q1), который реализуется с помощью 4-х D-триггеров с асинхронными сбросом и установкой. | ||
| + | |||
| + | == Слайд: Таблица переходов (таблица истинности логики переходов F) == | ||
| + | |||
| + | * таблица переходов представляет собой альтернативную запись исходного графа | ||
| + | {|align=center | ||
| + | | | ||
| + | {| class=standard align=center | ||
| + | !colspan=2| Текущее состояние <br /> state ||colspan=2| Входы <br />автомата ||colspan=2| Следующее состояние<br />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 | ||
| + | |- | ||
| + | |} | ||
| + | | | ||
| + | <graph> | ||
| + | |||
| + | digraph G { | ||
| + | |||
| + | node[color="red",shape="rectangle",style="rounded",fontsize=12]; | ||
| + | edge[fontsize=10, style="bold"]; | ||
| + | |||
| + | { rank=source Q1 [label="Q1\n y1",style="rounded,bold"] } | ||
| + | |||
| + | Q1 -> Q2 [label="x[1]=1", constraint=false] | ||
| + | Q2 -> Q3 [label="x[1]=0, x[2]=1", constraint=false] | ||
| + | Q2 -> Q4 [label="x[1]=1"] | ||
| + | Q4 -> Q1 [label="x[1]=1", constraint=false] | ||
| + | |||
| + | |||
| + | edge [color="blue", style="dashed", fontsize=10]; | ||
| + | |||
| + | Q2 -> Q1 [label="RST=1"] | ||
| + | Q3 -> Q1 [label="RST=1"] | ||
| + | Q4 -> Q1 [label="RST=1"] | ||
| + | |||
| + | Q2 [label="Q2\n y2"] | ||
| + | Q3 [label="Q3\n y1"] | ||
| + | Q4 [label="Q4\n y3"] | ||
| + | |||
| + | } | ||
| + | </graph> | ||
| + | |} | ||
| + | Обозначения в таблице: | ||
| + | * знак '–' - значение лог. '0' либо '1' | ||
| + | |||
| + | == Слайд: Таблица истинности выходной логики G == | ||
| + | |||
| + | {| class=standard align=center | ||
| + | !colspan=2| Состояние <br />State[3:0] ||colspan=2| Выход <br />y[1:0] | ||
| + | |- | ||
| + | ! Имя || Код || Имя || Код | ||
| + | |- | ||
| + | | Q1 || "0001" || y1 || "00" | ||
| + | |- | ||
| + | | Q2 || "0010" || y2 || "10" | ||
| + | |- | ||
| + | | Q3 || "0100" || y1 || "00" | ||
| + | |- | ||
| + | | Q4 || "1000" || y3 || "11" | ||
| + | |- | ||
| + | |} | ||
| + | |||
| + | == Слайд: VHDL-модель автомата == | ||
| + | |||
| + | {| cellspacing="0" cellpadding="5" border="1" | ||
| + | ! Вариант 1 || Вариант 2 || Вариант 3 | ||
| + | |- | ||
| + | |<source lang="vhdl"> | ||
| + | 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; | ||
| + | </source> | ||
| + | | | ||
| + | <source lang="vhdl"> | ||
| + | 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; | ||
| + | </source> | ||
| + | | | ||
| + | <source lang="vhdl"> | ||
| + | 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; | ||
| + | </source> | ||
| + | |} | ||
| + | |||
| + | == Слайд: Последовательный оператор CASE == | ||
| + | |||
| + | * ''Последовательный'' — значит может использоваться только в process | ||
| + | |||
| + | '''case''' ''Выражение'' '''is''' | ||
| + | '''when''' ''Значение'' '''=>''' | ||
| + | Последовательные операторы | ||
| + | '''when''' ''Значение'' [ '''|''' ''Значение'' ] '''=>''' | ||
| + | Последовательные операторы | ||
| + | '''end case'''; | ||
| + | |||
| + | * ''Значение'' может быть числом (литералом), простым выражением (например, a + b), диапазоном значений (1 '''to''' 10), ключевым словом '''others'''. | ||
| + | |||
| + | |||
| + | {| align=center cellspacing="0" cellpadding="5" border="1" | ||
| + | ! colspan=2 | Примеры | ||
| + | |- | ||
| + | | | ||
| + | <source lang="vhdl">case SEL is | ||
| + | when "01" => Z <= A; | ||
| + | when "10" => Z <= B; | ||
| + | when others => Z <= 'X'; | ||
| + | end case; | ||
| + | </source> | ||
| + | |<source lang="vhdl"> | ||
| + | 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; | ||
| + | </source> | ||
| + | |- | ||
| + | ! colspan=2 | Примеры ошибок | ||
| + | |- | ||
| + | |valign=top| {{X|24px}} перекрытие диапазонов | ||
| + | <source lang="vhdl"> | ||
| + | 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; | ||
| + | </source> | ||
| + | | {{X|24px}} Диапазон для вектора задавать нельзя | ||
| + | <source lang="vhdl"> | ||
| + | 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; | ||
| + | </source> | ||
| + | |} | ||
| + | |||
| + | |||
| + | == Слайд: Перечислимый тип (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-модель тестбенча == | ||
| + | |||
| + | <source lang="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; | ||
| + | </source> | ||
| + | |||
| + | == Слайд: Временные диаграммы == | ||
| + | |||
| + | [[Файл:Avtomat-wave.png|center|thumb|800px|Временные диаграммы проверки автоматов]] | ||
== Слайд: Словесное описание автомата == | == Слайд: Словесное описание автомата == | ||
| Строка 53: | Строка 536: | ||
* обеспечить возможность задания нового пароля по нажатию специальной кнопки и ввода старого пароля (пароль по умолчанию 000), а затем ввода нового. При неправильном вводе переходит в начальное состояние (ожидание ввода). При правильном старом пароле включить сигнал "доступ открыт", а после ввода нового пароля отключить сигнал "доступ открыт". | * обеспечить возможность задания нового пароля по нажатию специальной кнопки и ввода старого пароля (пароль по умолчанию 000), а затем ввода нового. При неправильном вводе переходит в начальное состояние (ожидание ввода). При правильном старом пароле включить сигнал "доступ открыт", а после ввода нового пароля отключить сигнал "доступ открыт". | ||
| − | * ввод пароля с клавиатуры (3х значное десятичное число от 000 до 999). Предусмотреть кнопку сброса введённого пароля (при | + | * ввод пароля с клавиатуры (3х значное десятичное число от 000 до 999). Предусмотреть кнопку сброса введённого пароля (при неправильнном вводе). |
* после ввода 3 цифр система проверяет введённый пароль с внутренним значением: | * после ввода 3 цифр система проверяет введённый пароль с внутренним значением: | ||
** если пароли совпадают, то включается светодиод "Доступ открыт" на 3 сек., после чего система переходит в режим ввода пароля | ** если пароли совпадают, то включается светодиод "Доступ открыт" на 3 сек., после чего система переходит в режим ввода пароля | ||
** если пароли не совпадают, то включается звуковой сигнал "Доступ закрыт" на 0.5 сек., после чего система переходит в режим ввода пароля | ** если пароли не совпадают, то включается звуковой сигнал "Доступ закрыт" на 0.5 сек., после чего система переходит в режим ввода пароля | ||
** если после ввода 1й или 2й цифры, следующая цифра (т.е. 2-я или 3я соответственно) не введены более чем через 5 секунд, то включается звуковой сигнал "Доступ закрыт" на 0.5 секунды | ** если после ввода 1й или 2й цифры, следующая цифра (т.е. 2-я или 3я соответственно) не введены более чем через 5 секунд, то включается звуковой сигнал "Доступ закрыт" на 0.5 секунды | ||
| − | |||
== Слайд: Алгоритм == | == Слайд: Алгоритм == | ||
| Строка 182: | Строка 664: | ||
<graph> | <graph> | ||
| + | |||
digraph G { | digraph G { | ||
| − | node[color="red",shape="rectangle",style="rounded",fontsize=12]; | + | #rankdir=LR; |
| + | |||
| + | node[color="red",shape="rectangle",style="rounded",fontsize=12 ]; | ||
edge[fontsize=10]; | edge[fontsize=10]; | ||
| + | splines=spline | ||
| + | #splines=true | ||
| + | |||
| + | |||
| + | # subgraph cluster1 { | ||
| + | # node [style=filled]; | ||
| + | # label = "Ввод старого пароля"; | ||
| + | # color=blue | ||
| + | # clusterrank=global | ||
| + | # InputOldPassword0 | ||
| + | # InputOldPassword1 | ||
| + | # InputOldPassword2 | ||
| + | # } | ||
| + | |||
| + | # subgraph cluster2 { | ||
| + | # node [style=filled]; | ||
| + | # label = "Ввод пароля"; | ||
| + | # color=blue | ||
| + | # InputPassword1 | ||
| + | # InputPassword2 | ||
| + | # } | ||
| + | |||
| + | # subgraph cluster3 { | ||
| + | # node [style=filled]; | ||
| + | # label = "Ввод нового пароля"; | ||
| + | # color=blue | ||
| + | # InputNewPassword1 | ||
| + | # InputNewPassword2 | ||
| + | # } | ||
| + | |||
| + | { rank = same InputOldPassword0 InputPassword1 } | ||
| + | { rank=min Start } | ||
Start -> InputOldPassword0 [label="SetPassword = '1'", style="bold"] | Start -> InputOldPassword0 [label="SetPassword = '1'", style="bold"] | ||
Start -> InputPassword1 [label="DigitalKey[9:0]", style="bold"] | Start -> InputPassword1 [label="DigitalKey[9:0]", style="bold"] | ||
| − | Start -> Start [label="Esc", color="blue", style="dashed"] | + | #Start -> Start [label="Esc", color="blue", style="dashed"] |
| + | InputPassword1 -> InputOldPassword0 [label="SetPassword = '1'", style="dashed"] | ||
InputPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | InputPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
#InputPassword1 -> Start [label="Delay5s", color="blue", style="dashed"] | #InputPassword1 -> Start [label="Delay5s", color="blue", style="dashed"] | ||
InputPassword1 -> InputPassword2 [label="DigitalKey[9:0]"] | InputPassword1 -> InputPassword2 [label="DigitalKey[9:0]"] | ||
| + | InputPassword2 -> InputOldPassword0 [label="SetPassword = '1'", style="dashed"] | ||
InputPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | InputPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
#InputPassword2 -> Start [label="Delay5s", color="blue", style="dashed"] | #InputPassword2 -> Start [label="Delay5s", color="blue", style="dashed"] | ||
InputPassword2 -> InputPasswordCompare [label="DigitalKey[9:0]"] | InputPassword2 -> InputPasswordCompare [label="DigitalKey[9:0]"] | ||
| − | InputPasswordCompare -> | + | InputPasswordCompare -> OpenAccess [label="InCode = Password"] |
InputPasswordCompare -> InputPasswordNotCompared [label="InCode /= Password"] | InputPasswordCompare -> InputPasswordNotCompared [label="InCode /= Password"] | ||
| − | + | OpenAccess -> Start [label="Delay3s"] | |
InputPasswordNotCompared -> Start [label="Delay05s"] | InputPasswordNotCompared -> Start [label="Delay05s"] | ||
| − | InputOldPassword0 -> InputOldPassword1 [label="DigitalKey[9:0]"] | + | InputOldPassword0 -> InputOldPassword1 [label="DigitalKey[9:0]"] |
| + | InputOldPassword1 -> InputOldPassword0 [label="SetPassword = '1'", style="dashed"] | ||
InputOldPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | InputOldPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
#InputOldPassword1 -> Start [label="Delay5s", color="blue", style="dashed"] | #InputOldPassword1 -> Start [label="Delay5s", color="blue", style="dashed"] | ||
| − | InputOldPassword1 -> InputOldPassword2 [label="DigitalKey[9:0]"] | + | InputOldPassword1 -> InputOldPassword2 [label="DigitalKey[9:0]"] |
| + | InputOldPassword2 -> InputOldPassword0 [label="SetPassword = '1'", style="dashed"] | ||
InputOldPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | InputOldPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
#InputOldPassword2 -> Start [label="Delay5s", color="blue", style="dashed"] | #InputOldPassword2 -> Start [label="Delay5s", color="blue", style="dashed"] | ||
| − | InputOldPassword2 -> InputOldPasswordCompare [label="DigitalKey[9:0]"] | + | InputOldPassword2 -> InputOldPasswordCompare [label="DigitalKey[9:0]"] |
| − | InputOldPasswordCompare -> InputOldPasswordCompareOk [label="InCode=OldPassword"] | + | InputOldPasswordCompare -> InputOldPasswordCompareOk [label="InCode=OldPassword"] |
| − | InputOldPasswordCompare -> InputPasswordNotCompared [label="InCode /= OldPassword"] | + | InputOldPasswordCompare -> InputPasswordNotCompared [label="InCode /= OldPassword"] |
InputOldPasswordCompareOk -> InputNewPassword1 [label="DigitalKey[9:0]"] | InputOldPasswordCompareOk -> InputNewPassword1 [label="DigitalKey[9:0]"] | ||
| + | InputNewPassword1 -> InputOldPassword0 [label="SetPassword = '1'", style="dashed"] | ||
InputNewPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | InputNewPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
#InputNewPassword1 -> Start [label="Delay5s", color="blue", style="dashed"] | #InputNewPassword1 -> Start [label="Delay5s", color="blue", style="dashed"] | ||
InputNewPassword1 -> InputNewPassword2 [label="DigitalKey[9:0]"] | InputNewPassword1 -> InputNewPassword2 [label="DigitalKey[9:0]"] | ||
| − | InputNewPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | + | InputNewPassword2 -> InputOldPassword0 [label="SetPassword = '1'", style="dashed"] |
| + | InputNewPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed", constraint=false] | ||
#InputNewPassword2 -> Start [label="Delay5s", color="blue", style="dashed"] | #InputNewPassword2 -> Start [label="Delay5s", color="blue", style="dashed"] | ||
InputNewPassword2 -> InputNewPassword3 [label="DigitalKey[9:0]"] | InputNewPassword2 -> InputNewPassword3 [label="DigitalKey[9:0]"] | ||
| Строка 238: | Строка 761: | ||
} | } | ||
| + | |||
</graph> | </graph> | ||
| + | |||
| + | === Слайд: Схема обработки нажатия клавиши === | ||
| + | |||
| + | {| align=center | ||
| + | ! <html><img src="https://docs.google.com/drawings/d/1FlCvBFGo7C3qryX2i1buM6AvKdTYrOhXznx0qP5uLoA/pub?w=800"></html> | ||
| + | |- | ||
| + | ! Рисунок - Схема обработки нажатия кнопки Esc ([https://docs.google.com/drawings/d/1FlCvBFGo7C3qryX2i1buM6AvKdTYrOhXznx0qP5uLoA/edit Edit]) | ||
| + | |} | ||
| + | |||
| + | |||
| + | {| align=center cellspacing="0" cellpadding="5" border="1" | ||
| + | |+ Таблица истинности комбинационного блока | ||
| + | ! EscPress_i1 || EscPress_i0 || EscPress_i | ||
| + | |- | ||
| + | | 0 || 0 || 0 | ||
| + | |- | ||
| + | | 0 || 1 || 0 | ||
| + | |- | ||
| + | | 1 || 0 || 1 | ||
| + | |- | ||
| + | | 1 || 1 || 0 | ||
| + | |- | ||
| + | !colspan=3| Логическое выражение | ||
| + | |- | ||
| + | | colspan=3| EscPress_i <= EscPress_i1 and not EscPress_i0 | ||
| + | |} | ||
| + | |||
| + | |||
| + | === Слайд: Схема обработки нажатия клавиши (VHDL) === | ||
| + | |||
| + | <source lang="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; | ||
| + | </source> | ||
| + | |||
| + | === Слайд: Блоки обработки нажатия клавиш === | ||
| + | |||
| + | {| align=center | ||
| + | ! <html><img src="https://docs.google.com/drawings/d/1vC772cniS3jfx_yXlQ5u1EmqA_3WSlj7Gr5mNFnZB40/pub?w=529"></html> | ||
| + | |- | ||
| + | ! Рисунок - Блоки обработки нажатия кнопок ([https://docs.google.com/drawings/d/1vC772cniS3jfx_yXlQ5u1EmqA_3WSlj7Gr5mNFnZB40/edit Edit]) | ||
| + | |} | ||
| + | |||
| + | |||
| + | === Слайд: Блок обработки нажатия цифровых клавиш === | ||
| + | |||
| + | {| align=center | ||
| + | ! <html><img src="https://docs.google.com/drawings/d/1txTGsAlg1iYZqzRObaEq81buGOWM4ZqjurAszBiKgc4/pub?w=800"></html> | ||
| + | |- | ||
| + | ! Рисунок - Блок обработки нажатия цифровых клавиш ([https://docs.google.com/drawings/d/1txTGsAlg1iYZqzRObaEq81buGOWM4ZqjurAszBiKgc4/edit Edit]) | ||
| + | |} | ||
| + | |||
| + | * {{ЖЛампа|24px}} не согласованы строб нажатия и код клавиши во времени | ||
| + | |||
| + | ==== Слайд: Блок обработки нажатия цифровых клавиш (VHDL) ==== | ||
| + | |||
| + | <source lang="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"; | ||
| + | </source> | ||
| + | |||
| + | == Слайд: Граф переходов == | ||
| + | |||
| + | <graph> | ||
| + | digraph G { | ||
| + | |||
| + | #rankdir=LR; | ||
| + | |||
| + | node[color="red",shape="rectangle",style="rounded",fontsize=12 ]; | ||
| + | edge[fontsize=10]; | ||
| + | splines=spline | ||
| + | #splines=true | ||
| + | |||
| + | Start [label="Start\n————————\nLedOpen = 0\nSpeaker = 0"] | ||
| + | InputPassword1 [label="InputPassword1\n————————\nLedOpen = 0\nSpeaker = 0\nInputCode[1] = KeyCode1[3:0]"] | ||
| + | InputPassword2 [label="InputPassword2\n————————\nLedOpen = 0\nSpeaker = 0\nInputCode[2] = KeyCode2[3:0]"] | ||
| + | InputPasswordCompare [label="InputPasswordCompare\n————————\nLedOpen = 0\nSpeaker = 0\nInputCode[3] = KeyCode3[3:0]"] | ||
| + | OpenAccess [label="OpenAccess\n————————\nLedOpen = 1\nSpeaker = 0\n"] | ||
| + | InputPasswordNotCompared [label="InputPasswordNotCompared\n————————\nLedOpen = 0\nSpeaker = 1\n"] | ||
| + | |||
| + | |||
| + | { rank=min Start } | ||
| + | |||
| + | Start -> InputPassword1 [label="DigitalKey[9:0]", style="bold"] | ||
| + | |||
| + | InputPassword1 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
| + | InputPassword1 -> InputPassword2 [label="DigitalKey[9:0]"] | ||
| + | |||
| + | InputPassword2 -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
| + | InputPassword2 -> InputPasswordCompare [label="DigitalKey[9:0]"] | ||
| + | |||
| + | InputPasswordCompare -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
| + | InputPasswordCompare -> OpenAccess [label="InputCode[1:3] = Password[1:3]"] | ||
| + | InputPasswordCompare -> InputPasswordNotCompared [label="InputCode[1:3] /= Password[1:3]"] | ||
| + | |||
| + | OpenAccess -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
| + | OpenAccess -> Start [label="Delay3s"] | ||
| + | |||
| + | InputPasswordNotCompared -> Start [label="Esc\n Delay5s", color="blue", style="dashed"] | ||
| + | InputPasswordNotCompared -> Start [label="Delay05s"] | ||
| + | |||
| + | } | ||
| + | </graph> | ||
| + | |||
| + | |||
| + | === Слайд: Режимы работы счетчика === | ||
| + | |||
| + | {| | ||
| + | ! | ||
| + | <graph> | ||
| + | digraph G { | ||
| + | |||
| + | #rankdir=LR; | ||
| + | |||
| + | node[color="red",shape="rectangle",style="rounded",fontsize=12 ]; | ||
| + | edge[fontsize=10]; | ||
| + | splines=spline | ||
| + | |||
| + | count_rst [label="Сброс счетчика\nCount=0"] | ||
| + | count [label="Режим счета\nCount=Count+1"] | ||
| + | |||
| + | count_rst -> count [label="Нет событий"] | ||
| + | count -> count_rst [label="DigitalKey[9:0],\n Esc,\n Delay5s",fontcolor="blue", color="blue", style="dashed"] | ||
| + | |||
| + | } | ||
| + | </graph> | ||
| + | | | ||
| + | <source lang="vhdl"> | ||
| + | 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 с | ||
| + | </source> | ||
| + | |} | ||
| + | * тип boolean (Delay05s) | ||
| + | * тип unsigned (count) | ||
| + | |||
| + | === Слайд: Режимы работы регистра ввода === | ||
| + | |||
| + | <graph> | ||
| + | digraph G { | ||
| + | |||
| + | #rankdir=LR; | ||
| + | |||
| + | node[color="red",shape="rectangle",style="rounded",fontsize=12 ]; | ||
| + | edge[fontsize=10]; | ||
| + | splines=spline | ||
| + | |||
| + | InputCode0 [label="InputCode[1:3]\n————————\n(0, 0, 0)"] | ||
| + | InputCode1 [label="InputCode[1:3]\n————————\n(KeyCode1, 0, 0)"] | ||
| + | InputCode2 [label="InputCode[1:3]\n————————\n(KeyCode1, KeyCode2, 0)"] | ||
| + | InputCode3 [label="InputCode[1:3]\n————————\n(KeyCode1, KeyCode2, KeyCode3)"] | ||
| + | |||
| + | InputCode0 -> InputCode1 [label="DigitalKey[9:0] & state=Start"] | ||
| + | InputCode1 -> InputCode2 [label="DigitalKey[9:0] & state=InputPassword1"] | ||
| + | InputCode2 -> InputCode3 [label="DigitalKey[9:0] & state=InputPassword2"] | ||
| + | InputCode3 -> InputCode0 [label="state /= InputPasswordCompare"] | ||
| + | |||
| + | } | ||
| + | </graph> | ||
| + | |||
| + | ==== Слайд: Режимы работы регистра ввода (VHDL) ==== | ||
| + | |||
| + | <source lang="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; | ||
| + | </source> | ||
| + | |||
| + | == Слайд: VHDL-модель == | ||
| + | |||
| + | <source lang="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; | ||
| + | </source> | ||
| + | |||
| + | |||
| + | === Слайд: VHDL-модель тестбенча === | ||
| + | |||
| + | <source lang="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; | ||
| + | </source> | ||
| + | |||
| + | |||
| + | === Слайд: Временные диаграммы === | ||
| + | |||
| + | [[Файл:Prj2 beh2 wave.png|thumb|800px|center|Временные диаграммы работы тестбенча]] | ||
| + | |||
| + | === Слайд: VHDL-модель (другой вариант описания) === | ||
| + | |||
| + | <source lang="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; | ||
| + | </source> | ||
== Слайд: NEW == | == Слайд: NEW == | ||
Текущая версия на 18:44, 25 марта 2014
- Заголовок
- Цифровые автоматы
- Автор
- Авдеев Н.А.
- Нижний колонтитул
- ПЦУСБ/Лекция 4
- Дополнительный нижний колонтитул
- Авдеев Н.А., 18:44, 25 марта 2014
Слайд: Провести анализ схемы (1)
Слайд: Провести анализ схемы (2)
Слайд: Абстра́ктный автома́т
- Абстра́ктный автома́т (в теории алгоритмов) — математическая абстракция, модель дискретного устройства, имеющего один вход, один выход и в каждый момент времени находящегося в одном состоянии из множества возможных. На вход этому устройству поступают символы одного алфавита, на выходе оно выдаёт символы (в общем случае) другого алфавита.
- Формально абстрактный автомат определяется как пятерка
- где
- S — конечное множество состояний автомата,
- X, Y — конечные входной и выходной алфавиты соответственно, из которых формируются строки, считываемые и выдаваемые автоматом,
- — функция переходов,
- — функция выходов.
Слайд: Автомат Мили
- Следующее состояние = F (текущее состояние, вход)
- Выход = G (текущее состояние, вход)
Слайд: Автомат Мура
- Следующее состояние = F (текущее состояние, вход)
- Выход = G (текущее состояние)
Слайд: Литература по построению автоматов
- Потемкин И.С. Функциональные узлы цифровой автоматики. – 1988, 320 с.
- Д. Уэйкерли Пректирование цифровых устройств. В 2-х томах / Том 2 — М., 2002 Т. 2. — 536 с. – глава 7 посвящена проектированию автоматов.
- Бибило П.Н. Основы языка VHDL: Учебное пособие. – М.: Книжный дом «ЛИБРОКОМ», 2012. – 328 с. – Глава 4.3 посвящена описанию автоматов на VHDL
Слайд: Граф состояний и переходов
|
|
|
Слайд: Выбор состояний для выходов и кодирование состояний
- Для хранения значения текущего состояния автомата используется 4-х разрядный регистр со сбросом в "0001" (код состояния Q1), который реализуется с помощью 4-х D-триггеров с асинхронными сбросом и установкой.
Слайд: Таблица переходов (таблица истинности логики переходов F)
- таблица переходов представляет собой альтернативную запись исходного графа
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Обозначения в таблице:
- знак '–' - значение лог. '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.
Слайд: Перечислимый тип (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 секунды
Слайд: Алгоритм
Слайд: Таблица переходов :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-2) | Нажата кнопка Esc | Начальное состояние |
Слайд: Таблица переходов (2)
| Текущее состояние | Событие (входы) | Следующее состояние |
|---|---|---|
| Режим ввода пароля (для доступа) (1) | Ввод второй цифры | Режим ввода пароля (для доступа) (2) |
| Режим ввода пароля (для доступа) (2) | Ввод третьей цифры | Переход в состояние:
|
| Режим ввода пароля (для доступа) (1 или 2) | Прошло 5 с | Начальное состояние |
| доступ открыт | Прошло 3 с | Начальное состояние |
| Доступ закрыт | Прошло 0.5 с | Начальное состояние |
Слайд: Тоже самое в виде графа
Слайд: Схема обработки нажатия клавиши
| |
|---|
| Рисунок - Схема обработки нажатия кнопки 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) |
Слайд: Блок обработки нажатия цифровых клавиш (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";
Слайд: Граф переходов
Слайд: Режимы работы счетчика
|
|
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)
Слайд: Режимы работы регистра ввода
Слайд: Режимы работы регистра ввода (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;




