Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Узагальнена структурна схема кінцевого автомата...doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
337.41 Кб
Скачать

Кінцевий автомат Милі

Модуль Mealy_1 ілюструє використання таблиці істинності для опису автомата Милі, граф переходів якого наведений на рис. 3.

SUBDESIGN MEALY_1

(

START, ABAR, CLK : INPUT;

WORK, END_WORK : OUTPUT;

)

VARIABLE

FSM : MACHINE WITH STATES

(INIT, WORK, WAIT, FINISH, RESUME);

BEGIN

FSM.CLK = CLK;

FSM.RESET = ABAR;

TABLE

--поточний вхідний вихідний наступний

--стан сигнал сигнал стан

FSM, START => WORK, END_WORK, FSM;

INIT, 0 => 0, 0, INIT;

INIT, 1 => 1, 0, WORK;

WORK, 0 => 1, 1, WAIT;

WORK, 1 => 1, 0, WORK;

WAIT, 0 => 0, 1, FINISH;

WAIT, 1 => 0, 0, RESUME;

RESUME, 0 => 1, 1, WAIT;

RESUME, 1 => 1, 0, WORK;

FINISH, B"x" => 0, 0, INIT;

END TABLE;

END;

Порівняння модулів MOORE_1 і Mealy_1 показує, що опис автоматів Мура й Милі збігаються з точністю до принципу формування вихідного сигналу.

Той же самий автомат Милі може бути описаний і за допомогою операторів CASE і IF THEN:

SUBDESIGN MEALY_2

(

START, ABAR, CLK : INPUT;

WORKING, END_WORKING : OUTPUT;

)

VARIABLE

FSM : MACHINE WITH STATES

(INIT, WORK, WAIT, FINISH, RESUME);

BEGIN

FSM.(CLK,RESET) = (CLK,ABAR);

CASE FSM IS

WHEN INIT =>

IF START == 1

THEN

FSM = WORK;

WORKING = VCC;

ELSE

FSM = INIT;

END IF;

WHEN WORK =>

WORKING = VCC;

IF START == 1

THEN

FSM = WORK;

WORKING = VCC;

ELSE

FSM = WAIT;

WORKING = VCC;

END_WORKING = VCC;

END IF;

WHEN WAIT =>

IF START ==1

THEN

FSM = RESUME;

WORKING = GND;

END_WORKING = GND;

ELSE

FSM = FINISH;

WORKING = GND;

END_WORKING = VCC;

END IF;

WHEN FINISH =>

END_WORKING = GND;

WORKING = GND;

FSM = UNIT;

WHEN RESUME =>

IF START ==1

THEN

FSM = WORK;

WORKING = VCC;

END_WORKING = GND;

ELSE

FSM = WAIT;

WORKING = VCC;

END_WORKING = VCC;

END IF;

END CASE;

END;

Результати моделювання автомата Милі наведені на рис. 5.

Рис. 5. 1

Лічильники

Лічильник - послідовністний пристрій, призначений для реєстрації числа імпульсів, що надійшли на його тактовий вхід і реєстрації їхнього числа в якому-небудь двійковому коді. Мовою AHDL лічильник може бути описаний:

■ на поведінковому рівні. При цьому використаються високорівневі конструкції мови, а також арифметичні оператори додавання й вирахування;

■ у вигляді кінцевого автомата;

■ на вентильному рівні.

Поведінковий опис

Опис на поведінковому рівні - це найпростіший і найбільш загальний спосіб задання алгоритму роботи лічильника. Проілюструємо його на прикладах.

Розглянемо параметризований опис двійкового WIDTH-розрядного підсумовуючого лічильника.

Виводи лічильника:

  • Clk — тактовий вхід;

  • Set — вхід асинхронної установки лічильника в одиницю;

  • Reset — вхід асинхронного скидання лічильника в нуль;

  • Dout[WIDTH..l] — WIDTH-розрядний вихід лічильника

PARAMETERS (WIDTH=7);

ASSERT (WIDTH>0)

REPORT "Значення параметра WIDNH повинне бути більше % " WIDTH

SEVERITY ERROR;

SUBDESIGN COUNT_1

(

CLK, RESET, SET : INPUT = VCC;

Q[WIDTH..0] : OUTPUT;

)

VARIABLE

RR[WIDTH..0] : DFF;

BEGIN

RR[].(CLK, CLRN, PRN) = (CLK, RESET,SET);

RR[].D = RR[].Q+1;

Q[] = RR[].Q;

END;

У програмі для перевірки значення параметра WIDTH використаний оператор ASSERT (WIDTH>0), що має рівень строгості ERROR. Тому при невиконанні заданої умови компілятор видати повідомлення про помилку.

При описі змінних використане визначення їхнє значення за замовчуванням. Якщо при подальшому використанні значення змінних CLK, RESET, SET не задані, то їм автоматично присвоюється значення логічної одиниці.

Відповідно до наведеного опису компілятор пакета синтезує WIDTH-розрядний накопичуючий суматор, на інформаційний вхід якого надходить константна одиниця. Структурна схема, що відповідає даному пристрою, показана рис. 6.

З появою на вході Сlk фронту тактового сигналу до поточного значення накопичуючого суматора додається одиниця. Підсумовування одиниці із числом 2WIDTH-1 (у всіх WIDTH розрядах накопичуючого суматора логічні одиниці) приведе до переповнення суматора, що приводить до появи у всіх його розрядах сигналу логічного нуля.

Результати моделювання лічильника COUNT_1 при WIDTH=7 наведені на рис. 7. На наведених часових діаграмах вихідний сигнал лічильника показаний двічі: перший раз у вигляді вихідних сигналів окремих розрядів тригерів лічильника Qi; другий раз – у вигляді числа Q[7..1], представленого в десятковій системі числення.

Рис. 6.

За аналогією можна описати й параметризированний WIDTH-розрядний лічильник, що віднімає. Цей лічильник має ті ж виводи.

Рис. 7.

PARAMETERS (WIDTH=7);

ASSERT (WIDTH>0)

REPORT "Значення параметра WIDNH повинне бути більше % " WIDTH

SEVERITY ERROR;

SUBDESIGN COUNT_2

(

CLK, RESET, SET : INPUT = VCC;

Q[WIDTH..0] : OUTPUT;

)

VARIABLE

RR[WIDTH..0]: DFF;

BEGIN

RR[].(CLK, CLRN, PRN) = (CLK, RESET, SET);

RR[].D = RR[].Q-1;

Q[] = RR[].Q;

END;

Результати моделювання віднімаючого лічильника, наведені на рис 8.

Рис. 8.

Розглянемо опис параметризованого реверсивного лічильника, додатково поставленим входом дозволу роботи. Якщо вхідній змінній IN/DEC присвоєне значення одиниці – лічильник виконує операцію інкремента (підсумовуючий лічильник), у протилежному випадку (IN/DEC == 0) - лічильник виконує мікрооперацію декремента.

PARAMETERS (WIDTH=7);

ASSERT (WIDTH>0)

REPORT "Значення параметра WIDNH повинно бути більше за % " WIDTH

SEVERITY ERROR;

SUBDESIGN COUNT_3

(

CLK, RESET, SET : INPUT = VCC;

ENABLE : INPUT = VCC;

Q[WIDTH..0] : OUTPUT;

)

VARIABLE

RR[WIDTH..0] : DFFE;

BEGIN

RR[].(CLK, CLRN, PRN, ENA) = (CLK, RESET, SET, ENABLE);

IF IN/DEC==1 THEN

RR[].D = RR[].Q+1;

ELSE

RR[].D = RR[].Q-1;

END IF;

Q[] = RR[].Q;

END;

Наведена програма фактично описує пристрій аналогічний, наведеному на рис. 6. Відмінність є лише в заміні схеми додавання універсальним суматором, що залежно від величини керуючого сигналу виконує або операцію додавання (ADD), або віднімання (SUB). Структурна схема такого пристрою наведена на рис. 9. Відмітимо, що для реалізації можливості керування роботою пристрою, його регістр додатково має вхід дозволу роботи (Enable).

Рис. 9.

Часові діаграми, що пояснюють роботу цього лічильника, наведені на рис. 10. З них випливає, що сигнали RESET і SET мають більш високий пріоритет, ніж сигнал ENABLE. Подача активного логічного рівня (сигнал нуля) на вхід ENABLE приводить до зупинки роботи лічильника, і він переходить у режим зберігання раніше записаної інформації. Цікаво відзначити, що, оскільки сигнал CLK є, як правило, глобальним, а сигнал ENABLE формується логічним елементом макроосередку (логічного блоку) ПЛІС, то при збігу фронтів зміни сигналів CLK і ENABLE (див. рис. 3.40) тригер устигає перемкнутися до появи на його інформаційному вході сигналу ENABLE.

Аналогічне зауваження справедливо й для сигналу IN/DEC (див. рис. 10).

Рис. 10.

Розглянемо опис параметризованого, реверсивного лічильника, що використовує режим паралельного завантаження інформації. Для цього в програму необхідно ввести вхід для задання керуючого сигналу, відповідальний за режим паралельного завантаження (LOAD) і входи для подачі записуваної інформації (DATA[WIDTH..0]). Очевидно, що розрядність слова даних вхідної інформації повинна збігатися з розрядністю лічильника, тобто бути параметризований.

--Реверсний лічильник з паралельним завантаженням

PARAMETERS (WIDTH=7);

ASSERT (WIDTH>0)

REPORT "Значення параметра WIDNH повинно бути більше за% " WIDTH

SEVERITY ERROR;

SUBDESIGN COUNT_4

(

CLK, RESET, SET : INPUT = VCC;

ENABLE, IN/DEC : INPUT = VCC;

LOAD, DATA[WIDTH..0] : INPUT;

Q[WIDTH..0] : OUTPUT;

)

VARIABLE

RR[WIDTH..0] : DFFE;

BEGIN

RR[].(CLK, CLRN, PRN, ENA) = (CLK, RESET, SET, ENABLE);

IF LOAD THEN -- Load=1 Режим синхронного паралельного завантаження

RR[].D = DATA[];

ELSE -- Load=0 Режим лічби

IF IN/DEC==1 THEN -- Визначення напрямку лічби

RR[].D = RR[].Q+1; -- Виконання операції інкремента

ELSE

RR[].D = RR[].Q-1; -- Виконання операції декремента

END IF;

END IF;

Q[] = RR[].Q; -- Присвоєння вихідного сигналу

END;

Наведений текст програми доповнений додатковими коментарями, що пояснюють виконувані програмою дії.

На рис. 11 показані результати роботи розглянутої програми.

Рис. 11.

З наведених часових діаграм треба, що пріоритет керуючого сигналу LOAD нижче, ніж сигналу ENABLE. Заслуговує на увагу момент формування фронту сигналу ENABLE. Фронт глобального тактового сигналу надходить на вхід тригерів раніше, ніж вихідний сигнал логічного елемента знімає активний рівень сигналу ENABLE. У результаті перемикання тригера не відбувається й на виході лічильника зберігається нульовий код.

Очевидно, що в наведеній програмі сигнали LOAD і DATA[WIDTH..0] можуть використатися тільки спільно. Тому в програму логічно ввести модуль перевірки, що контролює правильність вихідного задання цих сигналів. Таку перевірку легко виконати з використанням оператора ASSERT і функції USED. Нижче наведений текст програми, який пояснює виконання такої перевірки.

--Реверсний лічильник з паралельним завантаженням, що використає перевірку

--одночасної наявності сигналів LOAD і DATA

PARAMETERS (WIDTH=7);

ASSERT (WIDTH>0)

REPORT "Value of WIDTH mast be greater than % " WIDTH

SEVERITY ERROR;

SUBDESIGN COUNT_4A

(

CLK, RESET, SET : INPUT = VCC;

ENABLE, IN/DEC : INPUT = VCC;

LOAD, DATA[WIDTH..0] : INPUT;

Q[WIDTH..0] : OUTPUT;

)

VARIABLE

RR[WIDTH..0] : DFFE;

BEGIN

ASSERT USED(LOAD) !$ USED(DATA)--Перевірка одночасної присутності

--сигналів LOAD і DATA

REPORT "Inputs LOAD and DATA[] mast be used together"

SEVERITY ERROR;

RR[].(CLK, CLRN, PRN, ENA) = (CLK, RESET, SET, ENABLE);

IF USED (LOAD) GENERATE --Визначення алгоритму роботи у

--випадку використання

IF LOAD THEN --сигналу LOAD

RR[].D = DATA[];

ELSE

IF IN/DEC==1 THEN

RR[].D = RR[].Q+1;

ELSE

RR[].D = RR[].Q-1;

END IF;

END IF;

ELSE GENERATE --Опис алгоритму роботи у випадку

--не використання сигналу LOAD

IF IN/DEC==1 THEN

RR[].D = RR[].Q+1;

ELSE

RR[].D = RR[].Q-1;

END IF;

END GENERATE;

Q[] = RR[].Q; --Формування значення

--вихідного сигналу

END;

У наведеної тексті програми для перевірки спільного використання сигналів LOAD і DATA застосована логічна операція що виключає АБО, результат виконання якої дорівнює одиниці у випадку, якщо обоє операнда рівні. Якщо задана умова не виконується, компіляція проекту переривається й процесор повідомлень пакета формує повідомлення про помилку (рівень строгість виконання умови ERROR).

Помітимо, що в даному текстовому описі фактично описано два різних пристрої:

  • якщо входи LOAD і DATA не використаються, то програмою синтезується лічильник, що відповідає рис. 9;

  • якщо входи LOAD і DATA використаються, то програмою синтезується лічильник, що відповідає рис. 12.

Остання структура відрізняється від наведеної на рис. 9 використанням додаткового мультиплексора, що забезпечує підключення, залежно від значення сигналу LOAD, входу регістра або до виходу суматора, або до входу, на який подаються паралельно записувані дані (DATA[]).

Рис.12.

У всіх розглянуті вище програмах для паралельного запису інформації в лічильник використалися інформаційні входи його тригер. Тому паралельний запис здійснювався синхронно. Однак для цієї мети можна використати й входи асинхронної установки й скидання тригерів. У цьому випадку паралельний запис інформації буде виконуватися асинхронно, тобто в момент появи сигналу LOAD. Варіант опису такого лічильника наведений нижче.

--Реверсний лічильник з паралельним завантаженням, що використовує перевірку

--одночасної наявності сигналів LOAD і DATA і наявність сигналу CLK.

--Паралельне завантаження виконується асинхронно.

PARAMETERS (WIDTH=7);

ASSERT (WIDTH>0)

REPORT "Value of WIDTH mast be greater than % " WIDTH

SEVERITY ERROR;

SUBDESIGN COUNT_4ac

(

CLK, RESET, SET : INPUT = VCC;

ENABLE, IN/DEC : INPUT = VCC;

LOAD, DATA[WIDTH..0] : INPUT;

Q[WIDTH..0] : OUTPUT;

)

VARIABLE

RR[WIDTH..0] : DFFE;

BEGIN

ASSERT USED(CLK)

REPORT "Inputs CLK must be used"

SEVERITY ERROR;

ASSERT USED(LOAD) !$ USED(DATA)

REPORT "Inputs LOAD and DATA[] must be used together"

SEVERITY ERROR;

RR[].(CLK, ENA) = (CLK, ENABLE);

IF USED (LOAD) GENERATE

IF LOAD THEN

FOR i IN 0 TO WIDTH GENERATE

IF DATA[i] == 1 THEN

RR[i].CLRN = VCC;

RR[i].PRN = GND;

ELSE

RR[i].CLRN = GND;

RR[i].PRN = VCC;

END IF;

END GENERATE;

ELSE

RR[].(CLRN, PRN) = (RESET, SET);

IF IN/DEC==1 THEN

RR[].D = RR[].Q+1;

ELSE

RR[].D = RR[].Q-1;

END IF;

END IF;

ELSE GENERATE

RR[].(CLRN, PRN) = (RESET, SET);

IF IN/DEC==1 THEN

RR[].D = RR[].Q+1;

ELSE

RR[].D = RR[].Q-1;

END IF;

END GENERATE;

Q[] = RR[].Q;

END;

У наведеному описі для асинхронного запису в лічильник інформації використаний оператор «FOR i IN 0 TO WIDTH GENERATE», що здійснює порозрядну запис даних. Здійснити опис асинхронного запису даних можна й більше простим способом, використаю, наприклад, присвоєння відповідним входам змінної RR[] значень одномірної групи DATA[].

IF LOAD THEN

RR[].CLRN = DATA[];

RR[].PRN = !DATA[];

ELSE

Наведена програма додатково містить перевірку використання сигналу синхронізації CLK. Якщо цей сигнал не використовується, компілятор програми видає повідомлення про помилку й припиняє роботу.

Результати моделювання описаного лічильника наведені на рис. 13.

Рис. 13.

Всі розглянуті раніше лічильники були двійковими, тобто мали модуль лічби рівний М=2n , де n – ціле число. На практиці, часто необхідно мати лічильник з довільним модулем лічби. Розглянемо, для початку, варіант опису двійково-десяткового реверсного лічильника з можливістю паралельного запису інформації.

--Двійково-десятковий Реверсний лічильник з паралельним завантаженням

SUBDESIGN COUNT_2_10

(

CLK, RESET : INPUT = VCC;

ENABLE, IN/DEC : INPUT = VCC;

LOAD, DATA[3..0] : INPUT;

Q[3..0] : OUTPUT;

)

VARIABLE

RR[3..0] : DFFE;

BEGIN

RR[].(CLK, CLRN, ENA) = (CLK, RESET, ENABLE);

IF LOAD THEN --Паралельна синхронна

--завантаження за умови

--LOAD = VCC.

IF DATA[]>=B"1001" THEN

RR[].D = B"1001";

ELSE

RR[].D = DATA[];

END IF;

END IF;

IF (!LOAD & IN/DEC) THEN --Виконання операції інкремента

--у випадку LOAD=GND і IN/DEC=VCC.

IF RR[].Q >=B"1001" THEN

RR[].D=B"0000";

ELSE

RR[].D= RR[].Q+1;

END IF;

END IF;

IF (!LOAD & !IN/DEC) THEN --Виконання операції декремента

--у випадку LOAD=GND і IN/DEC=GND.

IF RR[].Q ==B"0000" THEN

RR[].D = B"1001";

ELSE

RR[].D= RR[].Q-1;

END IF;

END IF;

Q[] = RR[].Q;

END;

Особливістю наведеної вище програми є використання для перевірки значень керуючих сигналів оператора «IF (логічна умова) THEN» Якщо умова, описана в цьому операторі, виконується, то виконуються наступні за ним оператори. У протилежнму випадку, дії, що слідують за оператором, ігноруються й перевіряються наступні умови. Таким чином, у програмі перебираються всі можливі комбінації керуючих сигналів, і вибирається потрібний алгоритм роботи лічильника.

На рис. 14. наведені часові діаграми, що ілюструють роботу лічильника.

Рис. 14.

При описі лічильника використане синхронне паралельне завантаження даних. Тому число 15 не записується в лічильник на інтервалі першого активного рівня сигналу LOAD. (У момент першого фронту сигналу CLK, що відповідає сигналу LOAD=1, ще діє сигнал ENABLE = 0. У момент дії наступного фронту сигналу CLK, сигнал LOAD=0).

Розглянемо тепер більше загальний випадок і приведемо варіант опису лічильника, що має параметризированный модуль лічби.

--Реверсний лічильник з параметризированным модулем лічби

--й формуванням сигналів переносу й запозичання

PARAMETERS (MODULE=10);

ASSERT (MODULE>1)

REPORT "Value of Module must be greater then %"MODULE

SEVERITY ERROR;

CONSTANT WIDTH = CEIL (LOG2(MODULE));

CONSTANT DATA=MODULE-1;

SUBDESIGN COUNT_NOT_2N

(

IN/DEC, CLK, RESET, ENABLE : INPUT;

Q[WIDTH..0], TRANSFER, BORROW : OUTPUT;

)

VARIABLE

FF[WIDTH..0] : DFFE;

BEGIN

FF[].(CLK,CLRN, ENA) = (CLK, RESET, ENABLE);

IF IN/DEC THEN

IF FF[].Q == DATA THEN

FF[].D = 0;

TRANSFER = VCC;

ELSE

FF[].D = FF[].Q + 1;

END IF;

ELSE

IF FF[].Q == 0 THEN

FF[].D = DATA;

BORROW = VCC;

ELSE

FF[].D = FF[].Q - 1;

END IF;

END IF;

Q[]=FF[].Q;

END;

Тому що розрядність вихідного коду лічильника визначається його модулем лічби, то в програмі, як параметр, використовується модуль лічби. Для визначення розрядності вихідного лічби лічильника використовується арифметичне вираження «WIDTH = CEIL (LOG2(MODULE))», а значення розрядності вихідного коду і його максимальне значення задаються у вигляді констант, що залежать від модуля лічби.

Сигнали переповнення й запозичання рівні одиниці формуються на відповідних виходах лічильника (TRANSFER, BORROW) при досягненні максимально (операція інкрементая) або нульового (операція декремента) значень вихідного коду лічильника.

Часові діаграми, що пояснюють роботу лічильника з модулем лічби 12, ілюструють часові діаграми рис. 15. Значення модуля рахунки було задано в меню Assign, підміню Global Project Parameters (Рис. 16.)

Відзначимо, що формування вхідного сигналу RESET, що скидає лічильник, супроводжується формуванням сигналу BORROW тільки в режимі декремента (IN/DEC = 0).

Рис. 15

Розглянемо тепер найбільш універсальний варіант опису лічильника з довільним модулем лічби, для керування яким використаються сигнали паралельного запису інформації (LOAD), зміни напрямку лічби (IN/DEC) і синхронного скидання (sRESET).

Рис. 16.

-- Універсальний лічильник з параметризированим модулем лічби

-- й формуванням сигналів переповнення (запозичання).

-- Залежно від комбінації вхідних сигналів sRESET (синхронне скидання),

-- LOAD(паралельне завантаження) і IN/DEC (інкремент/декремент) формуючий

-- реалізацію восьми різних режимів роботи:

-- 000 - підсумовуючий лічильник;

-- 001 - Реверсний лічильник;

-- 010 - підсумовуючий лічильник з паралельним завантаженням інформації;

-- 011 - Реверсний лічильник з паралельним завантаженням інформації;

-- 100 - підсумовуючий лічильник із синхронним скиданням;

-- 101 - Реверсний лічильник із синхронним скиданням;

-- 110 - підсумовуючий лічильник з паралельним завантаженням інформації й ----- синхронним

-- скиданням;

-- 111 - Реверсний лічильник з паралельним завантаженням інформації й синх----- роннним

-- скиданням.

-- Крім цього кожний режим роботи додатково забезпечує асинхронне скидання й

-- використання сигналу дозволу роботи.

PARAMETERS (MODULE=10);

ASSERT (MODULE>1)

REPORT "Value of Module must be greater then %"MODULE

SEVERITY ERROR;

CONSTANT WIDTH = CEIL (LOG2(MODULE));

CONSTANT DATA=MODULE-1;

SUBDESIGN COUNT2_UNIVERSAL

(

CLK, sRESET : INPUT;

RESET, ENABLE, IN/DEC, LOAD : INPUT = VCC;

DATA_IN[WIDTH..0] : INPUT;

Q[WIDTH..0], TRANSFER, BORROW : OUTPUT;

)

VARIABLE

FF[WIDTH..0] : DFFE;

BEGIN

ASSERT USED (CLK)

REPORT "Input CLK must be used"

SEVERITY ERROR;

ASSERT USED (LOAD) !$ USED (DATA_IN)

REPORT "Inputs LOAD and DATA_IN must be used together"

SEVERITY ERROR;

FF[].(CLK, CLRN, ENA) = (CLK, RESET, ENABLE);

IF USED (sRESET) GENERATE -- Перевірка використання сигналу

-- синхронного скидання (sRESET).

IF sRESET THEN -- Сигнал синхронного скидання

-- використовується й він активний

-- (sRESET=0).

FF[].D = 0; -- Обнуляються сигнали на D входах

-- всіх тригерів лічильника.

ELSE -- Сигнал синхронного скидання

-- використовується але він пасивний

-- (sRESET=1).

IF USED (LOAD) GENERATE -- Перевірка використання сигналу

-- паралельного завантаження LOAD.

-- Сигнал LOAD використовується.

IF LOAD THEN -- Перевірка сигналу LOAD.

-- Сигнал LOAD активний. Режим

-- паралельного завантаження.

IF DATA_IN[] >=DATA THEN -- Перевірка значення коду

-- на вході паралельної

--завантаження. Якщо вхідний

FF[].D = DATA; -- код більше максимально

-- припустимого для

-- використовуваного модуля

-- лічби, то виконується

-- запис максимального

-- вихідного коду.

ELSE -- в протилежному випадку -- виконується

--паралельне завантаження

-- вхідного коду.

FF[].D = DATA_IN[];

END IF;

ELSE -- Сигнал LOAD пасивний.

-- Режим лічби.

IF USED (IN/DEC) GENERATE

-- Перевірка використання

-- сигналу IN/DEC.

-- Сигнал використовується.

IF IN/DEC THEN -- Якщо IN/DEC активний -- виконується операція

-- інкремента.

IF FF[].Q >= DATA THEN -- Порівняння

-- вихідного коду з

-- максимально припустимим для

-- використовуваного

-- модуля лічби.

FF[].D = 0; -- Обнуління

-- лічильника й

TRANSFER = VCC;-- формування

-- сигналу переносу

-- у випадку рівності кодів.

ELSE -- Виконання інкремента при не

FF[].D = FF[].Q + 1;-- рівності

-- кодів.

END IF; -- Кінець циклу порівняння.

ELSE -- Якщо IN/DEC пасивний виконується

-- операція декремента.

IF FF[].Q == 0 THEN -- Порівняння

-- вихідного коду з

-- нульовим.

FF[].D = DATA; -- Запис

-- максимально

-- припустимого

BORROW = VCC;-- вихідного коду й

-- формування

-- сигналу позичання.

ELSE -- Виконання інкремента

-- при не рівності

FF[].D = FF[].Q - 1;-- кодів.

END IF;-- Кінець циклу порівняння.

END IF;-- Кінець циклу порівняння активності

-- сигналу IN/DEC.

ELSE GENERATE -- Сигнал IN/DEC не використовується.

-- Режим підсумовуючого лічильника.

IF FF[].Q >= DATA[] THEN -- Порівняння

-- вихідного коду з

-- максимально припустимим для

-- використовуваного

-- модуля лічби.

FF[].D = 0; -- Обнуління

-- лічильника й

TRANSFER = VCC; -- формування

-- сигналу переносу

-- у випадку рівності кодів.

ELSE -- Виконання інкремента при не

F[].D = DD[].Q + 1;-- рівності кодів. END IF; -- Кінець циклу порівняння.

END GENERATE;-- Кінець перевірки використання

-- сигналу IN/DEC.

END IF; -- Кінець режиму перевірки сигналу LOAD.

ELSE GENERATE -- Сигнал LOAD не використовується.

IF USED (IN/DEC) GENERATE -- Перевірка використання

-- сигналу IN/DEC.

-- Сигнал використовується.

IF IN/DEC THEN -- Якщо IN/DEC активний

-- виконується

-- операція інкремента.

IF FF[].Q >= DATA[] THEN -- Порівняння

-- вихідного коду з максимально припустимим для

-- використовуваного

-- модуля лічби.

FF[].D = 0; -- Обнуління

-- лічильника й

TRANSFER = VCC; -- формування

-- сигналу переносу

-- у випадку рівності кодів.

ELSE -- Виконання інкремента при не

F[].D = DD[].Q + 1;-- рівності кодів. END IF; -- Кінець циклу порівняння.

ELSE -- Якщо IN/DEC пасивний виконується

-- операція декремента.

IF FF[].Q == 0 THEN-- Порівняння вихідного -- коду з нульовим.

FF[].D = DATA[];-- Запис максимально

-- припустимого

BORROW = VCC; -- вихідного коду й

-- формування сигналу запозичання.

ELSE -- Виконання інкремента при не

FF[].D = FF[].Q - 1;-- рівності кодів.

END IF; -- Кінець циклу порівняння.

END IF;-- Кінець циклу порівняння активності

-- сигналу IN/DEC.

ELSE GENERATE-- Сигнал IN/DEC не використовується.

-- Режим підсумовуючого лічильника.

IF FF[].Q >= DATA[] THEN-- Порівняння вихідного -- коду з максимально припустимим для

-- використовуваного модуля лічби.

FF[].D = 0; -- Обнуління лічильника й

TRANSFER = VCC; -- формування сигналу

-- переносу у випадку рівності кодів.

ELSE -- Виконання інкрементая при не

F[].D = DD[].Q + 1; -- рівності кодів. END IF; -- Кінець циклу порівняння.

END GENERATE; -- Кінець перевірки використання

-- сигналу IN/DEC.

END GENERATE; -- Кінець циклу перевірки

-- використання сигналу LOAD.

END IF; -- Кінець перевірки активності сигналу sRESET.

ELSE GENERATE -- Сигнал sRESET не використовується.

IF USED (LOAD) GENERATE -- Перевірка використання сигналу

-- паралельного завантаження LOAD.

-- Сигнал LOAD використовується.

IF LOAD THEN -- Перевірка сигналу LOAD.

-- Сигнал LOAD активний. Режим паралельного завантаження.

IF DATA_IN >=DATA THEN -- Перевірка значення коду на вході

-- паралельного завантаження. Якщо

FF[].D = DATA;-- вхідний код більше максимально

-- припустимого для використовуваного

-- модуля лічби, то виконується

-- запис максимального вихідного коду.

ELSE -- в протилежнму випадку виконується

-- паралельне завантаження вхідного коду.

FF[].D = DATA_IN[];

END IF; -- Кінець циклу перевірки коду на

-- вході паралельного завантаження.

ELSE -- Сигнал LOAD пасивний. Режим лічби.

IF USED (IN/DEC) GENERATE-- Перевірка використання

-- сигналу IN/DEC.

-- Сигнал використовується.

IF IN/DEC THEN -- Якщо IN/DEC активний

-- виконується операція інкремента.

IF FF[].Q >= DATA THEN -- Порівняння

-- вихідного коду з максимально припустимим для

-- використовуваного модуля лічби.

FF[].D = 0; -- Обнуління лічильника й

TRANSFER = VCC;-- формування сигналу -- переносу у випадку рівності кодів.

ELSE -- Виконання інкремента при не

FF[].D = FF[].Q + 1;-- рівності кодів.

END IF; -- Кінець циклу порівняння.

ELSE -- Якщо IN/DEC пасивний виконується

-- операція декремента.

IF FF[].Q == 0 THEN -- Порівняння вихідного

-- коду з нульовим

FF[].D = DATA;-- Запис максимально

-- припустимого вихідного коду

BORROW = VCC;-- й формування сигналу

-- запозичання.

ELSE -- Виконання інкрементая при не

FF[].D = FF[].Q - 1;-- рівності кодів.

END IF; -- Кінець циклу порівняння. END IF;-- Кінець циклу порівняння активності

-- сигналу IN/DEC.

ELSE GENERATE-- Сигнал IN/DEC не використовується.

-- Режим підсумовуючого лічильника.

IF FF[].Q >= DATA[] THEN-- Порівняння вихідного

-- коду з максимально припустимим для

-- використовуваного модуля лічби.

FF[].D = 0; -- Обнуління лічильника й

TRANSFER = VCC; -- формування сигналу

-- переносу у випадку рівності кодів.

ELSE -- Виконання інкремента при не

F[].D = DD[].Q + 1;-- рівності кодів.

END IF; -- Кінець циклу порівняння.

END GENERATE; -- Кінець перевірки використання

-- сигналу IN/DEC.

END IF; -- Кінець режиму перевірки сигналу LOAD.

ELSE GENERATE -- Сигнал LOAD не використовується.

IF USED (IN/DEC) GENERATE-- Перевірка використання сигналу

-- IN/DEC. Сигнал використовується.

IF IN/DEC THEN -- Якщо IN/DEC активний виконується

-- операція інкремента.

IF FF[].Q >= DATA[] THEN-- Порівняння вихідного -- коду з максимально

-- припустимим для використовуваного модуля лічби.

FF[].D = 0; -- Обнуління лічильника й

TRANSFER = VCC; -- формування сигналу

-- переносу у випадку рівності кодів. ELSE -- Виконання інкремента при не

F[].D = DD[].Q + 1;-- рівності кодів.

END IF; -- Кінець циклу порівняння. ELSE -- Якщо IN/DEC пасивний виконується

-- операція декремента.

IF FF[].Q == 0 THEN-- Порівняння вихідного коду з

-- нульовим.

FF[].D = DATA[]; -- Запис максимально

-- припустимого вихідного

BORROW = VCC; -- кода й формування

-- сигналу запозичання.

ELSE -- Виконання інкрементая при не

FF[].D = FF[].Q - 1;-- рівності кодів.

END IF; -- Кінець циклу порівняння.

END IF; -- Кінець циклу порівняння активності

-- сигналу IN/DEC.

ELSE GENERATE -- Сигнал IN/DEC не використовується.

-- Режим підсумовуючого лічильника.

IF FF[].Q >= DATA[] THEN -- Порівняння вихідного коду з

-- максимально припустимим для

-- використовуваного модуля лічби.

FF[].D = 0; -- Обнуління лічильника й

TRANSFER = VCC; -- формування сигналу

-- переносу у випадку рівності кодів.

ELSE -- Виконання інкремента при не

F[].D = DD[].Q + 1; -- рівності кодів.

END IF; -- Кінець циклу порівняння.

END GENERATE; -- Кінець перевірки використання

-- сигналу IN/DEC.

END GENERATE; -- Кінець циклу перевірки

-- використання сигналу LOAD.

END GENERATE; -- Кінець циклу перевірки

-- використання сигналу sRESET.

Q[] = FF[].Q; -- Присвоєння вихідному сигналу

-- вихідного коду уведеної змінної

END;

Відмітимо, що в даному текстовому описі фактично задано вісім різних схем лічильників. Вибір конкретної схеми при синтезі визначається використанням конкретних керуючих сигналів. Тому місце, займане розроблювальною схемою на кристалі ПЛИС, буде визначатися необхідним алгоритмом роботи. Компілятор автоматично включить у проект необхідні частини програми.

Результати моделювання даного лічильника при модулі лічби рівному 10 наведені на рис. 17.

Рис. 17.