vhdl
D-Flip-Flops (DFF) и защелки
Поиск…
замечания
D-Flip-Flops (DFF) и защелки - это элементы памяти. DFF сэмплирует свой вход на одном или другом краю своих часов (не оба), в то время как защелка прозрачна на одном уровне ее включения и запоминания на другом. На следующем рисунке показана разница:
Моделирование DFF или защелок в VHDL очень просто, но есть несколько важных аспектов, которые необходимо учитывать:
Различия между моделями VHDL DFF и защелками.
Как описать края сигнала.
Как описать синхронный или асинхронный набор или сброс.
D-Flip-Flops (DFF)
Во всех примерах:
-
clk
- часы, -
d
- вход, -
q
- выход, -
srst
- активный активный синхронный сброс, -
srstn
- активный низкий синхронный сброс, -
arst
- активный высокий асинхронный сброс, -
arstn
- активный низкий асинхронный сброс, -
sset
- активный активный синхронный набор, -
ssetn
- активный низкий синхронный набор, -
aset
- активныйaset
набор, -
asetn
- активный низкий асинхронный набор
Все сигналы имеют тип ieee.std_logic_1164.std_ulogic
. Используемый синтаксис - это тот, который приводит к правильным результатам синтеза со всеми логическими синтезаторами. Пожалуйста, см. Пример обнаружения края часов для обсуждения альтернативного синтаксиса.
Восходящие фронтовые часы
process(clk)
begin
if rising_edge(clk) then
q <= d;
end if;
end process;
Падающие фронтовые часы
process(clk)
begin
if falling_edge(clk) then
q <= d;
end if;
end process;
Восходящие фронтовые часы, синхронный активный высокий сброс
process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Восходящие фронтовые часы, асинхронный активный высокий сброс
process(clk, arst)
begin
if arst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Падающие фронтовые часы, асинхронный активный низкий сброс, синхронный активный высокий набор
process(clk, arstn)
begin
if arstn = '0' then
q <= '0';
elsif falling_edge(clk) then
if sset = '1' then
q <= '1';
else
q <= d;
end if;
end if;
end process;
Rising edge clock, асинхронный активный высокий сброс, асинхронный активный низкий набор
Примечание: установка имеет более высокий приоритет, чем сброс
process(clk, arst, asetn)
begin
if asetn = '0' then
q <= '1';
elsif arst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Задвижки
Во всех примерах:
-
en
- сигнал разрешения, -
d
- вход, -
q
- выход, -
srst
- активный активный синхронный сброс, -
srstn
- активный низкий синхронный сброс, -
arst
- активный высокий асинхронный сброс, -
arstn
- активный низкий асинхронный сброс, -
sset
- активный активный синхронный набор, -
ssetn
- активный низкий синхронный набор, -
aset
- активныйaset
набор, -
asetn
- активный низкий асинхронный набор
Все сигналы имеют тип ieee.std_logic_1164.std_ulogic
. Используемый синтаксис - это тот, который приводит к правильным результатам синтеза со всеми логическими синтезаторами. Пожалуйста, см. Пример обнаружения края часов для обсуждения альтернативного синтаксиса.
Активное высокое разрешение
process(en, d)
begin
if en = '1' then
q <= d;
end if;
end process;
Активное низкое разрешение
process(en, d)
begin
if en = '0' then
q <= d;
end if;
end process;
Активный высокий разрешающий, синхронный активный высокий сброс
process(en, d)
begin
if en = '1' then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Активное высокое разрешение, асинхронный активный высокий сброс
process(en, d, arst)
begin
if arst = '1' then
q <= '0';
elsif en = '1' then
q <= d;
end if;
end process;
Активное низкое разрешение, асинхронный активный низкий сброс, синхронный активный высокий набор
process(en, d, arstn)
begin
if arstn = '0' then
q <= '0';
elsif en = '0' then
if sset = '1' then
q <= '1';
else
q <= d;
end if;
end if;
end process;
Active high enable, асинхронный активный высокий сброс, асинхронный активный низкий набор
Примечание: установка имеет более высокий приоритет, чем сброс
process(en, d, arst, asetn)
begin
if asetn = '0' then
q <= '1';
elsif arst = '1' then
q <= '0';
elsif en = '1' then
q <= d;
end if;
end process;
Обнаружение краев часов
Рассказ
Whith VHDL 2008 и если тип часов bit
, boolean
, ieee.std_logic_1164.std_ulogic
или ieee.std_logic_1164.std_logic
, обнаружение краев часов может быть закодировано для нарастающего фронта
-
if rising_edge(clock) then
-
if clock'event and clock = '1' then -- type bit, std_ulogic or std_logic
-
if clock'event and clock then -- type boolean
и для падения
-
if falling_edge(clock) then
-
if clock'event and clock = '0' then -- type bit, std_ulogic or std_logic
-
if clock'event and not clock then -- type boolean
Это будет вести себя так, как ожидалось, как для моделирования, так и для синтеза.
Примечание: определение нарастающего фронта по сигналу типа
std_ulogic
немного сложнее, чем простой,if clock'event and clock = '1' then
. Например, стандартная функцияrising_edge
имеет другое определение. Даже если это, вероятно, не будет иметь никакого значения для синтеза, это может сделать одно для моделирования.
Использование rising_edge
и falling_edge
стандартных функций настоятельно рекомендуется. В предыдущих версиях VHDL для использования этих функций может потребоваться явно объявить использование стандартных пакетов (например, ieee.numeric_bit
для типа bit
) или даже определить их в пользовательском пакете.
Примечание: не используйте
rising_edge
иfalling_edge
стандартных функций для обнаружения краев без тактовых сигналов. Некоторые синтезаторы могли заключить, что сигнал - это часы. Подсказка: обнаружение края на нечасовом сигнале часто может выполняться путем выборки сигнала в сдвиговом регистре и сравнения выборочных значений на разных этапах сдвигового регистра.
Длинная история
Правильное описание обнаружения краев тактового сигнала имеет важное значение при моделировании D-Flip-Flops (DFF). Край, по определению, является переходом от одного конкретного значения к другому. Например, мы можем определить нарастающий фронт сигнала типа bit
(стандартный VHDL-перечисляемый тип, который принимает два значения: '0'
и '1'
) как переход от '0'
к '1'
. Для типа boolean
мы можем определить его как переход от false
к true
.
Часто используются более сложные типы. ieee.std_logic_1164.std_ulogic
тип ieee.std_logic_1164.std_ulogic
также является перечисленным типом, как bit
или boolean
, но имеет 9 значений вместо 2:
Значение | Имея в виду |
---|---|
'U' | Uninitialized |
'X' | Принуждение неизвестно |
'0' | Принуждение к низкому уровню |
'1' | Принуждение высокого уровня |
'Z' | Высокий импеданс |
'W' | Слабый неизвестный |
'L' | Слабый низкий уровень |
'H' | Слабый высокий уровень |
'-' | Не волнует |
Определение нарастающего фронта для такого типа немного сложнее, чем для bit
или boolean
. Мы можем, например, решить, что это переход от '0'
до '1'
. Но мы также можем решить, что это переход от '0'
или 'L'
к '1'
или 'H'
.
Примечание: это второе определение, которое стандарт использует для функции
rising_edge(signal s: std_ulogic)
определенной вieee.std_logic_1164
.
При обсуждении различных способов обнаружения ребер важно учитывать тип сигнала. Также важно учитывать цель моделирования: только симуляция или логический синтез? Проиллюстрируем это на нескольких примерах:
Восходящий фронт DFF с битом типа
signal clock, d, q: bit;
...
P1: process(clock)
begin
if clock = '1' then
q <= d;
end if;
end process P1;
Технически, с точки зрения чистой семантики моделирования, процесс P1
моделирует DFF с нарастающим фронтом. Действительно, назначение q <= d
выполняется тогда и только тогда, когда:
-
clock
изменились (это то, что выражает список чувствительности) и - текущее значение
clock
равно'1'
.
Поскольку clock
имеют тип бит, а бит типа имеет только значения '0'
и '1'
, это именно то, что мы определили как нарастающий фронт сигнала типа бит. Любой симулятор будет обрабатывать эту модель, как мы ожидаем.
Примечание. Для логических синтезаторов вещи немного сложнее, как мы увидим позже.
Увеличение DFF с асинхронным активным высоким сбросом и бит типа
Чтобы добавить асинхронный активный высокий сброс в наш DFF, можно попробовать что-то вроде:
signal clock, reset, d, q: bit;
...
P2_BOGUS: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif clock = '1' then
q <= d;
end if;
end process P2_BOGUS;
Но это не работает . Условием выполнения задания q <= d
должно быть: нарастающий фронт clock
при reset = '0'
. Но мы моделировали:
-
clock
илиreset
или оба изменены и -
reset = '0'
и -
clock = '1'
Это не одно и то же: если reset
изменяется от '1'
до '0'
а « clock = '1'
назначение будет выполняться, пока оно не является нарастающим фронтом clock
.
На самом деле, невозможно моделировать это в VHDL без помощи атрибута сигнала:
P2_OK: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif clock = '1' and clock'event then
q <= d;
end if;
end process P2_OK;
clock'event
- это event
атрибута сигнала, применяемое к сигнальным clock
. Он оценивается как boolean
и это true
тогда и только тогда, когда сигнальная clock
изменилась во время фазы обновления сигнала, которая только что предшествовала текущей фазе выполнения. Благодаря этому процесс P2_OK
теперь отлично моделирует то, что мы хотим в симуляции (и синтезе).
Синтез семантики
Многие логические синтезаторы идентифицируют обнаружение краев сигнала на основе синтаксических шаблонов, а не семантику модели VHDL. Другими словами, они считают, что выглядит код VHDL, а не то, какое поведение он моделирует. Один из шаблонов, которые все они распознают:
if clock = '1' and clock'event then
Итак, даже в примере процесса P1
мы должны использовать его, если хотим, чтобы наша модель была синтезирована всеми логическими синтезаторами:
signal clock, d, q: bit;
...
P1_OK: process(clock)
begin
if clock = '1' and clock'event then
q <= d;
end if;
end process P1_OK;
and clock'event
часть состояния полностью and clock'event
из списка чувствительности, но, как это and clock'event
некоторые синтезаторы, ...
Rising edge DFF с асинхронным активным высоким сбросом и тип std_ulogic
В этом случае выражение возрастающего фронта часов и условия сброса может усложниться. Если мы сохраним определение возрастающего фронта, которое мы предложили выше, и если мы считаем, что сброс активен, если он равен '1'
или 'H'
, модель становится:
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4: process(clock, reset)
begin
if reset = '1' or reset = 'H' then
q <= '0';
elsif clock'event and
(clock'last_value = '0' or clock'last_value = 'L') and
(clock = '1' or clock = 'H') then
q <= d;
end if;
end process P4;
Примечание:
'last_value
- это еще один атрибут сигнала, который возвращает значение,'last_value
перед последним изменением значения.
Вспомогательные функции
Стандарт VHDL 2008 предлагает несколько вспомогательных функций для упрощения обнаружения краев сигнала, особенно с многозначными перечисленными типами, такими как std_ulogic
. std.standard
пакет определяет rising_edge
и falling_edge
функции по типам bit
и boolean
и ieee.std_logic_1164
пакет определяет их по типам std_ulogic
и std_logic
.
Примечание: при использовании предыдущих версий VHDL для использования этих функций может потребоваться явно объявить использование стандартных пакетов (например, ieee.numeric_bit для типа бит) или даже определить их в пользовательском пакете.
Перейдем к рассмотрению предыдущих примеров и воспользуемся вспомогательными функциями:
signal clock, d, q: bit;
...
P1_OK_NEW: process(clock)
begin
if rising_edge(clock) then
q <= d;
end if;
end process P1_OK_NEW;
signal clock, d, q: bit;
...
P2_OK_NEW: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clock) then
q <= d;
end if;
end process P2_OK_NEW;
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4_NEW: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clock) then
q <= d;
end if;
end process P4_NEW;
Примечание: в этом последнем примере мы также упростили тест на сброс. Плавающие, высокие импедансы, сбрасывания довольно редки, и в большинстве случаев эта упрощенная версия работает для моделирования и синтеза.