ПЦУСБ/Лекция 4 — различия между версиями
Материал из Wiki
< ПЦУСБ
ANA (обсуждение | вклад) м (→Слайд: NEW) |
ANA (обсуждение | вклад) м (→Слайд: Автомат Мили) |
||
(не показаны 32 промежуточные версии 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 | ||
== Слайд: Граф состояний и переходов == | == Слайд: Граф состояний и переходов == | ||
Строка 43: | Строка 75: | ||
edge[fontsize=10, style="bold"]; | edge[fontsize=10, style="bold"]; | ||
− | { rank=source Q1 [label="Q1\n y1"] } | + | { rank=source Q1 [label="Q1\n y1",style="rounded,bold"] } |
− | Q1 -> Q2 [label=" | + | Q1 -> Q2 [label="x[1]=1", constraint=false] |
− | Q2 -> Q3 [label=" | + | Q2 -> Q3 [label="x[1]=0, x[2]=1", constraint=false] |
− | Q2 -> Q4 [label=" | + | Q2 -> Q4 [label="x[1]=1"] |
− | Q4 -> Q1 [label=" | + | Q4 -> Q1 [label="x[1]=1", constraint=false] |
Строка 90: | Строка 122: | ||
|} | |} | ||
|} | |} | ||
− | |||
== Слайд: Выбор состояний для выходов и кодирование состояний == | == Слайд: Выбор состояний для выходов и кодирование состояний == | ||
Строка 96: | Строка 127: | ||
<html><img src="https://docs.google.com/drawings/d/1ihtCm4nSz_DzSkTY3GN5mXHUEA6U95vSyryTTofTIIw/pub?w=907&h=296"></html> | <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 | {| class=standard align=center | ||
− | ! Текущее состояние <br /> state || Входы || Следующее состояние<br />next_state | + | !colspan=2| Текущее состояние <br /> state ||colspan=2| Входы <br />автомата ||colspan=2| Следующее состояние<br />next_state |
|- | |- | ||
− | | | + | ! Код || Имя || x[2] || x[1] || Код || Имя |
|- | |- | ||
− | | "0001" | + | | "0001" || Q1 || – || '1' || "0010" || Q2 |
|- | |- | ||
− | | " | + | | "0001" || Q1 || – ||'0' || "0001" || Q1 |
|- | |- | ||
− | | "0010" | + | | "0010" || Q2 || '1' || '0' || "0100" ||Q3 |
|- | |- | ||
− | | "0010" | + | | "0010" || Q2 || – ||'1' || "1000" || Q4 |
|- | |- | ||
− | | " | + | | "0010" || Q2 || – ||'0' || "0010" || Q2 |
|- | |- | ||
− | | "1000" | + | | "1000" || Q4 || – ||'1' || "0001" || Q1 |
|- | |- | ||
− | | "0100" | + | | "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 | {| class=standard align=center | ||
− | ! Состояние <br />State[3:0] || Выход y[1:0] | + | !colspan=2| Состояние <br />State[3:0] ||colspan=2| Выход <br />y[1:0] |
+ | |- | ||
+ | ! Имя || Код || Имя || Код | ||
|- | |- | ||
− | | Q1 | + | | Q1 || "0001" || y1 || "00" |
|- | |- | ||
− | | Q2 | + | | Q2 || "0010" || y2 || "10" |
|- | |- | ||
− | | Q3 | + | | Q3 || "0100" || y1 || "00" |
|- | |- | ||
− | | Q4 | + | | Q4 || "1000" || y3 || "11" |
|- | |- | ||
|} | |} | ||
Строка 139: | Строка 208: | ||
{| cellspacing="0" cellpadding="5" border="1" | {| cellspacing="0" cellpadding="5" border="1" | ||
− | ! Вариант 1 || Вариант 2 | + | ! Вариант 1 || Вариант 2 || Вариант 3 |
|- | |- | ||
|<source lang="vhdl"> | |<source lang="vhdl"> | ||
Строка 249: | Строка 318: | ||
end beh2; | end beh2; | ||
</source> | </source> | ||
− | | | + | | |
− | + | ||
− | + | ||
− | + | ||
<source lang="vhdl"> | <source lang="vhdl"> | ||
library ieee; | library ieee; | ||
use ieee.std_logic_1164.all; | use ieee.std_logic_1164.all; | ||
− | + | architecture beh3 of automat is | |
− | + | ||
− | + | ||
− | + | type state_type is (Q1, Q2, Q3, Q4); | |
− | + | signal state : state_type; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | signal | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
begin -- beh | 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; | |
− | end | + | |
</source> | </source> | ||
+ | |} | ||
== Слайд: Последовательный оператор CASE == | == Слайд: Последовательный оператор CASE == | ||
Строка 370: | Строка 432: | ||
</source> | </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> | ||
== Слайд: Временные диаграммы == | == Слайд: Временные диаграммы == | ||
Строка 380: | Строка 536: | ||
* обеспечить возможность задания нового пароля по нажатию специальной кнопки и ввода старого пароля (пароль по умолчанию 000), а затем ввода нового. При неправильном вводе переходит в начальное состояние (ожидание ввода). При правильном старом пароле включить сигнал "доступ открыт", а после ввода нового пароля отключить сигнал "доступ открыт". | * обеспечить возможность задания нового пароля по нажатию специальной кнопки и ввода старого пароля (пароль по умолчанию 000), а затем ввода нового. При неправильном вводе переходит в начальное состояние (ожидание ввода). При правильном старом пароле включить сигнал "доступ открыт", а после ввода нового пароля отключить сигнал "доступ открыт". | ||
− | * ввод пароля с клавиатуры (3х значное десятичное число от 000 до 999). Предусмотреть кнопку сброса введённого пароля (при | + | * ввод пароля с клавиатуры (3х значное десятичное число от 000 до 999). Предусмотреть кнопку сброса введённого пароля (при неправильнном вводе). |
* после ввода 3 цифр система проверяет введённый пароль с внутренним значением: | * после ввода 3 цифр система проверяет введённый пароль с внутренним значением: | ||
** если пароли совпадают, то включается светодиод "Доступ открыт" на 3 сек., после чего система переходит в режим ввода пароля | ** если пароли совпадают, то включается светодиод "Доступ открыт" на 3 сек., после чего система переходит в режим ввода пароля | ||
Строка 634: | Строка 790: | ||
|} | |} | ||
+ | |||
+ | === Слайд: Схема обработки нажатия клавиши (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;