Синхронизация с правками публикуемого издания (#101)

* СП. Обновление предисловия

* СП. Обновление введения

* СП. Обновление лаб

* СП. Обновление доп материалов

* СП. Введение

* СП. Введение

* СП. ЛР№4, 15

* СП. Базовые конструкции Verilog

* Update Implementation steps.md

* СП. ЛР 4,5,7,8,14

* СП. ЛР№8

* Синхронизация правок

* СП. Финал

* Исправление ссылки на рисунок

* Обновление схемы

* Синхронизация правок

* Добавление белого фона .drawio-изображениям

* ЛР2. Исправление нумерации рисунка
This commit is contained in:
Andrei Solodovnikov
2025-02-12 17:53:52 +03:00
committed by GitHub
parent d251574bbc
commit 9739429d6e
168 changed files with 79781 additions and 961 deletions

View File

@@ -10,46 +10,46 @@
- [Таблицы подстановки (Look-Up Tables, LUTs)](#таблицы-подстановки-look-up-tables-luts)
- [D-триггеры](#d-триггеры)
- [Арифметика](#арифметика)
- [Логическая ячейка](#логическая-ячейка)
- [Логические блоки](#логические-блоки)
- [Сеть межсоединений](#сеть-межсоединений)
- [Итоги главы](#итоги-главы)
- [Список источников](#список-источников)
> Разделы "Цифровые схемы и логические вентили" и "Таблицы подстановки" во многом используют материалы статьи "[How Does an FPGA Work?[1]](https://learn.sparkfun.com/tutorials/how-does-an-fpga-work/all)" за авторством `Alchitry, Ell C`, распространяемой по лицензии [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
> Параграфы "Цифровые схемы и логические вентили" и "Таблицы подстановки" во многом используют материалы статьи "[How Does an FPGA Work?[1]](https://learn.sparkfun.com/tutorials/how-does-an-fpga-work/all)" за авторством `Alchitry, Ell C`, распространяемой по лицензии [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
## История появления ПЛИС
До появления интегральных схем электронные схемы собирались из отдельных элементов, как модель, собранная из кубиков Lego. В случае, если при сборке электронной схемы была допущена ошибка, вы могли исправить её ручной корректировкой соединения элементов подобно исправлению ошибки, допущенной при сборке модели Lego.
До появления интегральных схем электронные устройства строились на базе вакуумных ламп, которые выполняли функции усиления и переключения. Эти лампы были громоздкими, энергозатратными и недолговечными. Затем их заменили на транзисторы, которые стали основой современных электронных схем. Поначалу транзисторы, как и лампы, использовались в виде отдельных компонентов, и схемы собирались из них, как модель из кубиков Lego. В случае ошибки её можно было исправить ручной корректировкой соединений между элементами, подобно исправлению ошибки при сборке модели Lego.
В дальнейшем произошла миниатюризация базовых элементов — транзисторов, из которых состоят электронные схемы, и появилась возможность реализовать соединения между ними непосредственно на кристалле, что привело к появлению интегральных схем — электронных схем, выполненных на полупроводниковой подложке и заключенных в неразборный корпус.
С развитием технологий произошла миниатюризация транзисторов, что позволило разместить их вместе с соединениями на одном кристалле. Так появились интегральные схемы — электронные схемы, выполненные на полупроводниковой подложке и заключённые в неразборный корпус. Этот переход стал революционным шагом в развитии электроники, открыв путь к созданию компактных и производительных устройств.
В большинстве случаев, исправить ошибку, допущенную при разработке и изготовлении интегральной схемы, невозможно. С учетом того, что изготовление прототипа интегральной схемы является долгим и затратным мероприятием (от десятков тысяч до миллионов долларов в зависимости от технологии (или технологического процесса) , по которой изготавливается схема и занимаемой площади), возникла необходимость в гибком, быстром и дешевом в способе проверки схемы до изготовления её прототипа. Так появились **программируемые логические интегральные схемы** (**ПЛИС**). В связи с повсеместным использованием англоязычной литературы, имеет смысл дать и англоязычное название этого класса устройств: **programmable logic devices** (**PLD**).
ПЛИС содержит некоторое конечное множество базовых блоков (примитивов), блоки межсоединений примитивов и блоки ввода-вывода. Подав определенный набор воздействий на ПЛИС (**запрограммировав** её), можно настроить примитивы, их межсоединения между собой и блоками ввода-вывода, чтобы получить определенную цифровую схему. Удобство ПЛИС заключается в том, что в случае обнаружения ошибки на прототипе, исполненном в ПЛИС, вы можете исправить свою цифровую схему, и повторно запрограммировать ПЛИС.
Кроме того, эффективно использовать ПЛИС не как средство дешевого прототипирования, но и как средство реализации конечного продукта в случае малого тиража (дешевле купить и запрограммировать готовую партию ПЛИС, чем изготовить партию собственных микросхем).
В большинстве случаев, исправить ошибку, допущенную при разработке и изготовлении интегральной схемы, невозможно. С учетом того, что изготовление прототипа интегральной схемы является долгим и затратным мероприятием (от десятков тысяч до миллионов долларов), возникла необходимость в гибком, быстром и дешёвом способе изготовления прототипа, и проверки на нём схемы до её изготовления. Так появились **программируемые логические интегральные схемы** (**ПЛИС**). В связи с повсеместным использованием англоязычной литературы, имеет смысл дать и англоязычное название этого класса устройств: **programmable logic devices** (**PLD**).
Стоит оговориться, что в данной книге под термином ПЛИС будет подразумеваться конкретный тип программируемых схем: **FPGA** (**field-programmable gate array**, **программируемая пользователем вентильная матрица**, **ППВМ**).
Давайте разберемся что же это за устройство и как оно работает изнутри, но перед этим необходимо провести ликбез по цифровым схемам и логическим вентилям.
ПЛИС содержит некоторое конечное множество базовых блоков (примитивов), блоки межсоединений примитивов и блоки ввода-вывода. Подав определенный набор воздействий на ПЛИС (**запрограммировав** её), можно настроить примитивы, их межсоединения между собой и блоками ввода-вывода, чтобы получить требуемую цифровую схему. Удобство ПЛИС заключается в том, что в случае обнаружения ошибки на прототипе, исполненном в ПЛИС, вы можете исправить свою цифровую схему и повторно запрограммировать ПЛИС.
Кроме того, эффективно использовать ПЛИС не как средство дешевого прототипирования, но и как средство реализации конечного продукта в случае малого тиража (дешевле купить и запрограммировать готовую партию ПЛИС, чем изготовить партию собственных микросхем).
Давайте разберемся, что же это за устройство и как оно работает изнутри, но перед этим необходимо провести ликбез по цифровым схемам и логическим вентилям.
## Цифровые схемы и логические вентили
### Цифровые схемы
**Цифровая схема** — это **абстрактная модель** вычислений, которая оперирует двумя дискретными состояниями, обычно обозначаемыми как `0` и `1`. Важно понимать, что эти состояния не привязаны к конкретным физическим величинам, таким как напряжение в электрической цепи. Вместо этого они представляют собой обобщенные логические значения, которые могут быть реализованы на любой технологии, способной различать два четких состояния.
**Цифровая схема** — это **абстрактная модель** вычислений, которая оперирует двумя дискретными состояниями, обычно обозначаемыми как `0` и `1`. Важно понимать, что эти состояния не привязаны к конкретным физическим величинам, таким как напряжение в электрической цепи. Вместо этого они представляют собой обобщенные логические значения, которые могут быть реализованы на любой технологии, способной различать два чётких состояния.
Благодаря этой абстракции, цифровые схемы могут быть реализованы не только с помощью традиционных электронных компонентов, но и на совершенно иных платформах, например, на [пневматических системах](https://habr.com/ru/companies/ruvds/articles/692236/), [из картона и шариков](https://habr.com/ru/articles/399391/), [красной пыли](https://minecraft.fandom.com/wiki/Tutorials/Redstone_computers) в игре Майнкрафт или даже с использованием человеческого взаимодействия, подобно тому как это описано в романе Лю Цысиня "Задача трёх тел" (эффективность подобных схем — это уже другой вопрос). Основная идея заключается в том, что цифровая схема отвязывается от физической реализации, фокусируясь лишь на логике взаимодействия состояний `0` и `1`, что делает ее универсальной и независимой от конкретной технологии.
Благодаря этой абстракции цифровые схемы могут быть реализованы не только с помощью традиционных электронных компонентов, но и на совершенно иных платформах, например на [пневматических системах](https://habr.com/ru/companies/ruvds/articles/692236/), [из картона и шариков](https://habr.com/ru/articles/399391/), [красной пыли](https://minecraft.fandom.com/wiki/Tutorials/Redstone_computers) в игре Майнкрафт или даже с использованием человеческого взаимодействия, подобно тому, как это описано в романе Лю Цысиня "Задача трёх тел" (эффективность подобных схем — это уже другой вопрос). Основная идея заключается в том, что цифровая схема отвязывается от физической реализации, фокусируясь лишь на логике взаимодействия состояний `0` и `1`, что делает её универсальной и независимой от конкретной технологии.
Разумеется, при проектировании эффективных цифровых схем, необходимо оглядываться на технологию, по которой эти схемы будут работать.
Разумеется, при проектировании эффективных цифровых схем необходимо оглядываться на технологию, по которой эти схемы будут работать.
В электронике, словом "цифровая" описывают схемы, которые абстрагируются от непрерывных (аналоговых) значений напряжений, вместо этого используется только два дискретных значения: `0` и `1`. На данном уровне абстракции нас не интересуют конкретные значения напряжений и пороги этих значений, что позволяет нам разрабатывать схему в идеальном мире, где у напряжения может быть всего два значения: `0` и `1`. А обеспечением этих условий будут заниматься базовые блоки, из которых мы будем строить цифровые схемы.
В электронике словом "цифровая" описывают схемы, которые абстрагируются от непрерывных (аналоговых) значений напряжений, вместо этого используются только два дискретных значения: `0` и `1`. На данном уровне абстракции нас не интересуют конкретные значения напряжений и пороги этих значений, что позволяет нам разрабатывать схему в идеальном мире, где у напряжения может быть всего два значения: `0` и `1`. А обеспечением этих условий будут заниматься базовые блоки, из которых мы будем строить цифровые схемы.
Эти базовые блоки называются **логическими вентилями**.
### Логические вентили
Существует множество логических вентилей, но чаще всего используется четыре из них: **И**, **ИЛИ**, **Исключающее ИЛИ**, **НЕ**. Каждый из этих элементов принимает на вход **цифровое значение** (см. [**цифровая схема**](#цифровые-схемы)), выполняет определенную **логическую функцию** над входами и подает на выход результат этой функции в виде **цифрового значения**.
Существует множество логических вентилей, мы рассмотрим четыре из них: **И**, **ИЛИ**, **Исключающее ИЛИ**, **НЕ**. Каждый из этих элементов принимает на вход **цифровое значение** (см. [**цифровая схема**](#цифровые-схемы)), выполняет определенную **логическую функцию** над входами и подает на выход результат этой функции в виде **цифрового значения**.
Логические вентили на _рис. 1-4_ иллюстрируются условными графическими обозначениями (**УГО**), взятыми из двух стандартов: **ANSI** и **ГОСТ**. Ввиду повсеместного использования в литературе первого варианта, в дальнейшем в книге будет использован он.
@@ -77,13 +77,13 @@ _Рисунок 3. УГО логического вентиля **Исключа
_Рисунок 4. УГО логического вентиля **НЕ**._
Так же существуют вариации базовых вентилей, такие как **И-НЕ**, **ИЛИ-НЕ**, **Исключающее ИЛИ-НЕ**, отличающиеся от исходных тем, что результат операции инвертирован относительно результата аналогичной операции без **-НЕ**.
Также существуют вариации базовых вентилей, такие как **И-НЕ**, **ИЛИ-НЕ**, **Исключающее ИЛИ-НЕ**, отличающиеся от исходных тем, что результат операции инвертирован относительно результата аналогичной операции без **-НЕ**.
Логические вентили строятся из **транзисторов**. **Транзистор** — это элемент, который может пропускать/блокировать ток в зависимости от поданного напряжения на его управляющий вход.
Особенностью современных интегральных схем является то, что они строятся на основе комплементарной (взаимодополняющей) пары транзисторов **P** и **N**-типа (**Комплементарная Металл-Оксид-Полупроводниковая**, **КМОП** логика). Для данного типа транзисторов оказалось эффективнее реализовать операции **И-НЕ** и **ИЛИ-НЕ**.
С точки зрения построения цифровых схем МОП-транзистор (**P** и **N**-типа) можно воспринимать как выключатель, который замыкает или размыкает связь между двумя выводами. Разница между **P** и **N** типом заключается в состоянии, в котором транзистор "открыт" (вход и выход замкнуты) или "закрыт" (связь разорвана). _Рис. 5_ иллюстрирует данное различие.
С точки зрения построения цифровых схем МОП-транзисторы (**P**- и **N**-типа) можно воспринимать как выключатели, которые замыкают или размыкают связь между двумя выводами. Разница между **P**- и **N** типами заключается в состоянии, в котором транзистор "открыт" (вход и выход замкнуты) или "закрыт" (связь разорвана). _Рис. 5_ иллюстрирует данное различие.
Вход и выход, между которыми образуется связь называются "**сток**" (**drain**, **d**) и "**исток**" (**source**, **s**), а управляющий вход — "**затвор**" (**gate**, **g**). Обратите внимание, что логический вентиль (**logic gate**) и затвор транзистора (просто **gate**) — это разные сущности!
@@ -93,7 +93,7 @@ _Рисунок 5. МОП-транзисторы P и N типа._
На _рис. 6_ показан способ построения логических вентилей **И-НЕ**, **ИЛИ-НЕ** по **КМОП** технологии. Рассмотрим принцип работы вентиля **И-НЕ**.
Подача значения `1` на вход **А** или **B** открывает соответствующий этому входу n-канальный транзистор (обозначен на _рис. 6_ красным цветом), и закрывает дополняющий его (комплементарный ему) p-канальный транзистор (обозначен синим цветом). Подача на оба входа `1` закрывает оба p-канальных транзистора (верхняя часть схемы разомкнута, что для значения на выходе означает что её будто бы и нет) и открывает оба n-канальных транзистора. В результате чего выход замыкается на "землю" (чёрный треугольник внизу схемы) что эквивалентно `0` в контексте цифровых значений.
Подача значения `1` на вход **А** или **B** открывает соответствующий этому входу n-канальный транзистор (обозначен на _рис. 6_ красным цветом) и закрывает дополняющий его (комплементарный ему) p-канальный транзистор (обозначен синим цветом). Подача на оба входа `1` закрывает оба p-канальных транзистора (верхняя часть схемы разомкнута, что для значения на выходе означает, что её будто и нет) и открывает оба n-канальных транзистора. В результате чего выход замыкается на "землю" (чёрный треугольник внизу схемы), что эквивалентно `0` в контексте цифровых значений.
В случае, если хотя бы на одном из входов **А** или **B** будет значение `0`, откроется один из параллельно соединенных p-канальных транзисторов (в то время как соединение с "землей" будет разорвано) и выход будет подключен к питанию (две перпендикулярные линии вверху схемы), что эквивалентно `1` в контексте цифровых значений.
@@ -115,31 +115,31 @@ _Рисунок 7. Схема логического вентиля **НЕ**, п
Используя одни лишь описанные выше логические вентили можно построить **любую(!)** цифровую схему.
Однако, при описании цифровых схем, некоторые цифровые блоки используются настолько часто, что для них ввели отдельные обозначения (**сумматоры**, **умножители**, **мультиплексоры** т.п.), используемые при описании более сложных схем. Мы рассмотрим один из фундаментальных строительных блоков в ПЛИС — **мультиплексор**.
Однако, при описании цифровых схем, некоторые цифровые блоки используются настолько часто, что для них ввели отдельные обозначения (**сумматоры**, **умножители**, **мультиплексоры** т.п.), используемые при описании более сложных схем. Рассмотрим один из фундаментальных строительных блоков в ПЛИС — **мультиплексор**.
### Мультиплексоры
Мультиплексор — это устройство, которое в зависимости от значения **управляющего сигнала** подает на выход значение одного из входных сигналов.
Схематически, мультиплексор обозначается следующим образом:
УГО мультиплексора представлено на _рисунке 8_.
![../.pic/Introduction/How%20FPGA%20works/fig_08.drawio.svg](../.pic/Introduction/How%20FPGA%20works/fig_08.drawio.svg)
_Рисунок 8. Обозначение Мультиплексора._
Символ `/` на линии `sel` используется, чтобы показать, что этот сигнал шириной 6 бит.
Символ `/` на линии `sel` указывает на то, что этот сигнал шириной 6 бит.
Число входов мультиплексора может быть различным, но выход у него всегда один.
**Способ, которым кодируется значение управляющего сигнала может также различаться**. Простейшая цифровая схема мультиплексора получится, если использовать [**унитарное**](https://ru.wikipedia.org/wiki/Унитарный_код) (**one-hot**) кодирование. При таком кодировании, значение **многоразрядного** сигнала **всегда** содержит **ровно одну** `1`. Информация, которую несет закодированный таким образом сигнал содержится в положении этой `1` внутри многоразрядного сигнала.
**Способ, которым кодируется значение управляющего сигнала может также различаться**. Простейшая цифровая схема мультиплексора получится, если использовать [**унитарное**](https://ru.wikipedia.org/wiki/Унитарный_код) (**one-hot**) кодирование. При таком кодировании, значение **многоразрядного** управляющего сигнала **всегда** содержит **ровно одну** `1`. Информация, которую несёт закодированный таким образом сигнал содержится в положении этой `1` внутри управляющего сигнала.
Посмотрим, как можно реализовать мультиплексор с управляющим сигналом, использующим one-hot-кодирование, используя только логические вентили **И**, **ИЛИ**:
Посмотрим, как можно реализовать мультиплексор с управляющим сигналом, использующим one-hot-кодирование, при помощи одних лишь логических вентилей **И**, **ИЛИ**:
![../.pic/Introduction/How%20FPGA%20works/fig_09.drawio.svg](../.pic/Introduction/How%20FPGA%20works/fig_09.drawio.svg)
_Рисунок 9. Реализация мультиплексора, использующего one-hot кодирование._
Если мы выставим значение управляющего сигнала, равное `000010`, означающее что только **первый** бит этого сигнала (**счет ведется с нуля**) будет равен **единице** (`sel[1] = 1`), то увидим, что на один из входов каждого логического вентиля **И** будет подано значение `0`. Исключением будет логический вентиль **И** для входа `b`, на вход которого будет подано значение `1`. Это означает, что все логические вентили **И** (кроме первого, на который подается вход `b`) будут выдавать на выход `0` (см. [Логические вентили](#логические-вентили)) вне зависимости от того, что было подано на входы a,c,d,e и f. Единственным входом, который будет на что-то влиять окажется вход `b`. Когда он равен `1`, на выходе соответствующего логического вентиля **И** окажется значение `1`. Когда он равен `0` на выходе **И** окажется значение `0`. Иными словами, выход **И** будет повторять значение `b`.
Если мы выставим значение управляющего сигнала, равное `000010`, означающее, что только **первый** бит этого сигнала (**счет ведется с нуля**) будет равен **единице** (`sel[1] = 1`), то увидим, что на один из входов каждого логического вентиля **И** будет подано значение `0`. Исключением будет логический вентиль **И** для входа `b`, на вход которого будет подано значение `1`. Это означает, что все логические вентили **И** (кроме первого, на который подается вход `b`) будут выдавать на выход `0` (см. [Логические вентили](#логические-вентили)) вне зависимости от того, что было подано на входы a,c,d,e и f. Единственным входом, который будет влиять на работу схемы, окажется вход `b`. Когда он равен `1`, на выходе соответствующего логического вентиля **И** окажется значение `1`. Когда он равен `0` на выходе **И** окажется значение `0`. Иными словами, выход **И** будет повторять значение `b`.
![../.pic/Introduction/How%20FPGA%20works/fig_10.drawio.svg](../.pic/Introduction/How%20FPGA%20works/fig_10.drawio.svg)
@@ -151,9 +151,9 @@ _Рисунок 10. Реализация мультиплексора, испо
_Рисунок 11. Реализация многоходового логического **ИЛИ**._
**Многовходовой вентиль ИЛИ** ведет себя ровно так же, как двухвходовой: он выдает на выход значение `1` когда хотя бы один из входов равен `1`. В случае, если все входы равны `0`, на выход **ИЛИ** пойдет `0`.
**Многовходовой вентиль ИЛИ** ведет себя ровно так же, как двухвходовой: он выдает на выход значение `1`, когда хотя бы один из входов равен `1`. В случае, если все входы равны `0`, на выход **ИЛИ** пойдет `0`.
Но для нашей схемы мультиплексора гарантируется, что каждый вход **ИЛИ** кроме одного будет равняться `0` (поскольку выход каждого **И** кроме одного будет равен `0`). Это означает, что выход **многовходового ИЛИ** будет зависеть только от **одного** входа (в случае, когда `sel = 000010` — от входа `b`).
Для нашей схемы мультиплексора гарантируется, что каждый вход **ИЛИ** кроме одного будет равняться `0` (поскольку выход каждого **И** кроме одного будет равен `0`). Это означает, что выход **многовходового ИЛИ** будет зависеть только от **одного** входа (в случае, когда `sel = 000010` — от входа `b`).
![../.pic/Introduction/How%20FPGA%20works/fig_12.drawio.svg](../.pic/Introduction/How%20FPGA%20works/fig_12.drawio.svg)
@@ -163,19 +163,19 @@ _Рисунок 12. Реализация мультиплексора, испо
### Программируемая память
Из транзисторов можно построить не только логические элементы, но и элементы памяти. На рис. 13 представлена схема простейшей ячейки статической памяти, состоящей из транзистора и двух инверторов (т.е. суммарно состоящей из 5 транзисторов, поэтому она называется **5T** SRAM). Данная ячейка реализует 1 бит конфигурируемой памяти, являвшейся одним из основных компонентов самой первой ПЛИС.
Из транзисторов можно построить не только логические элементы, но и элементы памяти. На рис. 13 представлена схема простейшей ячейки статической памяти, состоящей из транзистора и двух инверторов (т.е. суммарно состоящей из 5 транзисторов, поэтому она называется **5T** SRAM). Данная ячейка реализует 1 бит программируемой памяти, являвшейся одним из основных компонентов самой первой ПЛИС.
![../.pic/Introduction/Sequential%20logic/fig_06.drawio.svg](../.pic/Introduction/Sequential%20logic/fig_06.drawio.svg)
_Рисунок 13. Конфигурируемая ячейка памяти ПЛИС Xilinx XC2064[[2, стр. 2-63](https://archive.org/details/programmablegate00xili/page/n93/mode/2up)]._
_Рисунок 13. Программируемая ячейка памяти ПЛИС Xilinx XC2064[[2, стр. 2-63](https://archive.org/details/programmablegate00xili/page/n93/mode/2up)]._
Данная память представляет собой **бистабильную ячейку** — петлю из двух инверторов, в которых "заперто" хранимое значение. Дважды инвертированный сигнал совпадает по значению с исходным, при этом проходя через каждый из инверторов, сигнал обновляет свое значение напряжения, что не позволяет ему угаснуть из-за сопротивления цепи.
Данная память представляет собой **бистабильную ячейку** — петлю из двух инверторов, в которых "заперто" хранимое значение. Дважды инвертированный сигнал совпадает по значению с исходным, при этом, проходя через каждый из инверторов, сигнал обновляет свое значение напряжения, что не позволяет ему угаснуть из-за сопротивления цепи.
Для того чтобы поместить в бистабильную ячейку новое значение, к ее входу подключается еще один транзистор, замыкающий или размыкающий ее с напряжением питания/земли.
Для того чтобы поместить в бистабильную ячейку новое значение, к её входу подключается еще один транзистор, замыкающий или размыкающий её с напряжением питания/земли.
## Таблицы подстановки (Look-Up Tables, LUTs)
Представьте мультиплексор с четырьмя входными сигналами, и двухбитным управляющим сигналом (обратите внимание, что в теперь это сигнал не использует one-hot-кодирование). Но теперь, вместо того чтобы выставлять входные сигналы во внешний мир, давайте подключим их к программируемой памяти. Это означает, что мы можем "запрограммировать" каждый из входов на какое-то константное значение. Поместим то, что у нас получилось в отдельный блок и вот, мы получили двухвходовую **Таблицу подстановки** (**Look-Up Tables**, далее **LUT**).
Представьте мультиплексор с четырьмя входными сигналами и двухбитным управляющим сигналом (обратите внимание, что в теперь это сигнал использует обычное двоичное кодирование). Но теперь, вместо того чтобы выставлять входные сигналы во внешний мир, давайте подключим их к программируемой памяти. Это означает, что мы можем "запрограммировать" каждый из входов на какое-то константное значение. Поместим то, что у нас получилось, в отдельный блок и вот, мы получили двухвходовую **Таблицу подстановки** (**Look-Up Tables**, далее **LUT**).
![../.pic/Introduction/How%20FPGA%20works/fig_14.drawio.svg](../.pic/Introduction/How%20FPGA%20works/fig_14.drawio.svg)
@@ -183,24 +183,24 @@ _Рисунок 14. Реализация таблицы подстановки (
Эти два входа **LUT** являются битами управляющего сигнала мультиплексора, спрятанного внутри **LUT**. Программируя входы мультиплексора (точнее, программируя память, к которой подключены входы мультиплексора), мы можем реализовать на базе **LUT** **любую(!)** логическую функцию, принимающую два входа и возвращающую один выход.
Допустим мы хотим получить **логическое И**. Для этого, нам потребуется записать в память следующее содержимое:
Допустим, мы хотим получить **логическое И**. Для этого, нам потребуется записать в память следующее содержимое:
|Адрес (In[1:0])| Значение |
|---------------|----------|
| 00 | 0 |
| 01 | 0 |
| 10 | 0 |
| 11 | 1 |
|Адрес ({x, y}) | Значение (f)|
|---------------|-------------|
| 00 | 0 |
| 01 | 0 |
| 10 | 0 |
| 11 | 1 |
Это простейший пример — обычно **LUT**-ы имеют больше входов, что позволяет им реализовывать более сложную логику.
## D-триггеры
Как вы уже поняли, используя неограниченное количество LUT-ов, вы можете построить цифровую схему, реализующую логическую функцию любой сложности. Однако цифровые схемы не ограничиваются реализацией одних только логических функций (цифровые схемы, реализующие логическую функцию, называются **комбинационными**, поскольку выход зависит только от комбинации входов). Например, так не построить цифровую схему, реализующую процессор. Для таких схем, нужны элементы памяти. Заметим, что речь идет не о программируемой памяти, задавая значения которой мы управляем тем, куда будут направлены сигналы, и какие логические функции будут реализовывать LUT-ы. Речь идет о ячейках памяти, которые будут использоваться логикой самой схемы.
Как вы уже поняли, используя неограниченное количество LUT-ов, вы можете построить цифровую схему, реализующую логическую функцию любой сложности. Однако цифровые схемы не ограничиваются реализацией одних только логических функций (цифровые схемы, реализующие логическую функцию, называются **комбинационными**, поскольку выход зависит только от комбинации входов). Например, так не построить цифровую схему, реализующую процессор. Для таких схем нужны элементы памяти. Заметим, что речь идет не о программируемой памяти, задавая значения которой мы управляем тем, какие логические функции будут реализовывать LUT-ы. Речь идет о ячейках памяти, которые будут использоваться логикой самой схемы.
Такой базовой ячейкой памяти является **D-триггер** (**D flip-flop**), из которых можно собрать другие ячейки памяти, например **регистры** (а из регистров можно собрать **память с произвольным доступом** (**random access memory**, **RAM**)), **сдвиговые регистры** и т.п.
Такой базовой ячейкой памяти является **D-триггер** (**D flip-flop**). Из D-триггеров можно собирать другие ячейки памяти, например **регистры** (а из регистров можно собрать **память с произвольным доступом** (**random access memory**, **RAM**)), **сдвиговые регистры** и т.п.
**D-триггер** — это цифровой элемент, способный хранить один бит информации. В базовом варианте у этого элемента есть два входа и один выход. Один из входов подает значение, которое будет записано в **D-триггер**, второй вход управляет записью (обычно он называется `clk` или `clock` и подключается к тактирующему синхроимпульсу схемы). Когда управляющий сигнал меняет свое значение с `0` на `1` (либо с `1` на `0`, зависит от схемы), в **D-триггер** записывается значение сигнала данных. Обычно, описывая **D-триггер**, говорится, что он строится из двух **триггеров-защелок** (**D latch**), которые в свою очередь строятся из **RS-триггеров**, однако в конечном итоге, все эти элементы могут быть построены на базе логических вентилей **И**/**ИЛИ**, **НЕ**:
**D-триггер** — это цифровой элемент, способный хранить один бит информации. В базовом варианте у этого элемента есть два входа и один выход. Один из входов подает значение, которое будет записано в **D-триггер**, второй вход управляет записью (обычно он называется `clk` или `clock` и подключается к тактирующему синхроимпульсу схемы). Когда управляющий сигнал меняет своё значение с `0` на `1` (либо с `1` на `0`, зависит от схемы), в **D-триггер** записывается значение сигнала данных. Обычно, описывая **D-триггер**, говорится, что он строится из двух **триггеров-защелок** (**D-latch**), которые, в свою очередь, строятся из **RS-триггеров**. Однако в конечном итоге, все эти элементы могут быть построены на базе логических вентилей **И**/**ИЛИ**, **НЕ**:
![../.pic/Introduction/Sequential%20logic/fig_05.drawio.svg](../.pic/Introduction/Sequential%20logic/fig_05.drawio.svg)
@@ -208,7 +208,7 @@ _Рисунок 15. Реализация D-триггера._
## Арифметика
Помимо описанных выше блоков (мультиплексоров и построенных на их основе LUT-ов и регистров) выделяется еще один тип блоков, настолько часто используемый в цифровых схемах, что его заранее размещают в ПЛИС в больших количествах: это арифметические блоки. Эти блоки используются при сложении, вычитании, сравнении чисел, реализации счётчиков. В разных ПЛИС могут быть предустановлены разные блоки: где-то это может быть однобитный сумматор, а где-то блок вычисления ускоренного переноса (`carry-chain`).
Помимо описанных выше блоков (мультиплексоров и построенных на их основе LUT-ов и регистров) выделяется еще один тип блоков, настолько часто используемый в цифровых схемах, что его заранее размещают в ПЛИС в больших количествах: это арифметические блоки. Эти блоки используются при сложении, вычитании, сравнении чисел, реализации счётчиков. В разных ПЛИС могут быть предустановлены разные блоки: где-то это может быть 1-битный сумматор, а где-то блок вычисления ускоренного переноса (`carry-chain`).
Все эти блоки могут быть реализованы через логические вентили, например так можно реализовать сумматор:
@@ -216,51 +216,47 @@ _Рисунок 15. Реализация D-триггера._
_Рисунок 16. Реализация полного однобитного сумматора._
## Логическая ячейка
## Логические блоки
И вот, мы подходим к внутреннему устройству ПЛИС. Мы уже узнали, что в ПЛИС есть матрица программируемых мультиплексоров, направляющих сигналы туда, куда нам нужно.
В предыдущих параграфах, были рассмотрены отдельные виды цифровых блоков: таблицы подстановок, регистры, арифметические блоки. Для удобства структурирования, эти блоки объединены в ПЛИС в виде **логических блоков**. Обычно, логические блоки современных ПЛИС состоят из **логических ячеек** (или **логических элементов**), но для простоты повествования, мы объединим все эти термины.
Вторым важным элементом является **логический блок** (обычно состоящих из **логических ячеек** или **логических элементов**, но для простоты мы отождествим все эти термины).
Логический блок может содержать одну или несколько **LUT**, **арифметический блок**, и один или несколько **D-триггеров**, которые соединены между собой некоторым количеством мультиплексоров. На _рисунке 17_ представлена схема того, как может выглядеть логический блок:
Логический блок содержит одну или несколько **LUT**, **арифметический блок**, и один или несколько **D-триггеров**, которые соединены между собой некоторым количеством мультиплексоров.
На _рис. 17_ представлена схема того, как может выглядеть **логический блок**:
![../.pic/Labs/lab_03_memory/fig_02.png](../.pic/Labs/lab_03_memory/fig_02.png)
_Рисунок 17. Схема логической ячейки[[2]](https://en.wikipedia.org/wiki/Field-programmable_gate_array)._
Всё достаточно просто. Логический блок представляет собой цепочку операций: `логическая функция, реализованная через LUT -> арифметическая операция -> Запись в D-триггер`. Каждый из мультиплексоров определяет то, будет ли пропущен какой-либо из этих этапов.
Логический блок представляет собой цепочку операций: `логическая функция, реализованная через LUT -> арифметическая операция -> Запись в D-триггер`. Каждый из мультиплексоров определяет то, будет ли пропущен какой-либо из этих этапов.
Таким образом, конфигурируя каждый логический блок, можно получить следующие вариации кусочка цифровой схемы:
1. Комбинационная схема (логическая функция, реализованная в LUT)
2. Арифметическая операция
3. Запись данных в D-триггер
4. Комбинационная схема, с записью результата в D-триггер
4. Комбинационная схема с записью результата в D-триггер
5. Арифметическая операция с записью результата в D-триггер
6. Комбинационная схема с последующей арифметической операцией
7. Комбинационная схема с последующей арифметической операцией и записью в D-триггер
А вот реальный пример использования логического блока в ПЛИС `xc7a100tcsg324-1` при реализации Арифметико-логического устройства (АЛУ), подключенного к периферии отладочной платы `Nexys-7`:
На _рисунке 18_ приведён реальный пример использования логического блока в ПЛИС `xc7a100tcsg324-1` при реализации Арифметико-логического устройства (АЛУ), подключенного к периферии отладочной платы `Nexys-7`. На этом рисунке вы можете увидеть использование LUT-ов, арифметического блока (ускоренного расчета переноса), и одного из D-триггеров. D-триггеры, обозначенные серым цветом, не используются.
![../.pic/Introduction/How%20FPGA%20works/fig_18.png](../.pic/Introduction/How%20FPGA%20works/fig_18.png)
_Рисунок 18. Пример использования логической ячейки._
Здесь вы можете увидеть использование LUT-ов, арифметического блока (ускоренного расчета переноса), и одного из D-триггеров. D-триггеры, обозначенные серым цветом, не используются.
Располагая большим наборов таких логических блоков, и имея возможность межсоединять их нужным вам образом, вы получаете широчайшие возможности по реализации практически любой цифровой схемы (ограничением является только ёмкость ПЛИС, т.е. количество подобных логических блоков, входов выходов и т.п.).
Помимо логических блоков, в ПЛИС есть и другие примитивы: **Блочная память**, **блоки умножителей** и т.п.
Помимо логических блоков в ПЛИС есть и другие примитивы: **блочная память**, **блоки умножителей** и т.п.
## Сеть межсоединений
Для того, чтобы разобраться как управлять межсоединением логических блоков, рассмотрим рис. 19, входящий в [патент](https://patents.google.com/patent/US4870302A) на ПЛИС[[4](http://www.righto.com/2020/09/reverse-engineering-first-fpga-chip.html)].
Для того чтобы разобраться, как управлять межсоединением логических блоков, рассмотрим рис. 19, входящий в патент на ПЛИС[[4](https://patents.google.com/patent/US4870302A)].
![../.pic/Introduction/How%20FPGA%20works/fig_19.jpg](../.pic/Introduction/How%20FPGA%20works/fig_19.jpg)
_Рисунок 19. Содержимое ПЛИС в виде межсоединения логических блоков и блоков ввода-вывода._
_Рисунок 19. Содержимое ПЛИС в виде межсоединения логических блоков и блоков ввода-вывода[[5](http://www.righto.com/2020/09/reverse-engineering-first-fpga-chip.html)]._
Синим показано 9 логических блоков, желтым — 12 блоков ввода-вывода. Все эти блоки окружены **сетью межсоединений** (interconnect net), представляющей собой матрицу из горизонтальных и вертикальных соединительных линий — межсоединений общего назначения (general purpose interconnect) [[2, 2-66](https://archive.org/details/programmablegate00xili/page/n97/mode/2up)].
Синим показано 9 логических блоков, желтым — 12 блоков ввода-вывода. Все эти блоки окружены **сетью межсоединений** (interconnect net), представляющей собой решётку из горизонтальных и вертикальных соединительных линий — межсоединений общего назначения (general purpose interconnect) [[2, 2-66](https://archive.org/details/programmablegate00xili/page/n97/mode/2up)].
Косыми чертами в местах пересечения линий обозначены **программируемые точки межсоединений** (**programmable interconnect points**, **PIP**s), представляющие собой транзисторы, затвор которых подключен к программируемой памяти.
@@ -272,13 +268,13 @@ _Рисунок 19. Содержимое ПЛИС в виде межсоедин
1. Используя такие элементы, как **транзисторы**, можно собирать **логические вентили**: элементы **И**, **ИЛИ**, **НЕ** и т.п.
2. Используя **логические вентили**, можно создавать схемы, реализующие как **логические функции** (**комбинационные схемы**), так и сложную логику с памятью (**последовательностные схемы**).
3. Из логических вентилей среди прочего строится и такая важная комбинационная схема, как **мультиплексор**: цифровой блок, в зависимости от управляющего сигнала подающий на выход один из входных сигналов.
4. Кроме того, подключив вход бистабильной ячейки (представляющую собой петлю из двух инверторов) к транзистору, можно получить 1 бит **конфигурируемой памяти**.
5. Подключив входные сигналы мультиплексора к программируемой памяти, можно получить **Таблицу подстановок** (**Look-Up Table**, **LUT**), которая может реализовывать простейшие логические функции. LUT-ы позволяют заменить логические вентили И/ИЛИ/НЕ, и удобны тем, что их можно динамически изменять, логические вентили в свою очередь исполняются на заводе и уже не могут быть изменены после создания.
6. Из логических вентилей так же можно собрать базовую ячейку памяти: **D-триггер**, и такую часто используемую комбинационную схему как **полный однобитный сумматор** (или любой другой часто используемый арифметический блок).
3. Из логических вентилей строится и такая важная комбинационная схема, как **мультиплексор**: цифровой блок, который в зависимости от значения управляющего сигнала подаёт на выход один из входных сигналов.
4. Кроме того, подключив вход бистабильной ячейки (представляющую собой петлю из двух инверторов) к транзистору, можно получить 1 бит **программируемой памяти**.
5. Подключив входные сигналы мультиплексора к программируемой памяти, можно получить **Таблицу подстановок** (**Look-Up Table**, **LUT**), которая может реализовывать простейшие логические функции. LUT-ы позволяют заменить логические вентили И/ИЛИ/НЕ, и удобны тем, что их можно динамически изменять. Логические вентили в свою очередь исполняются на заводе и уже не могут быть изменены после создания.
6. Из логических вентилей также можно собрать базовую ячейку памяти: **D-триггер**, и такую комбинационную схему как **полный 1-битный сумматор** (или любой другой часто используемый арифметический блок).
7. Объединив LUT, арифметический блок и D-триггер получается структура в ПЛИС, которая называется **логический блок**.
8. Логический блок (а также другие **примитивы**, такие как **блочная память** или **умножители**) — это множество блоков, которые заранее физически размещаются в кристалле ПЛИС, их количество строго определено конкретной ПЛИС и не может быть изменено.
9. Подключая такой бит конфигурируемой памяти к транзисторам, расположенных в узлах **сети межсоединений**, можно управлять тем, где в этой сети будут разрывы, а значит можно оставить только маршрут, по которому сигнал пойдет туда, куда нам нужно (**трассировать сигнал**).
9. Подключая программируемую память к транзисторам, расположенных в узлах **сети межсоединений**, можно управлять расположением разрывов в сети, а значит можно оставить только маршрут, по которому сигнал пойдет туда, куда нам нужно (**трассировать сигнал**).
10. **Конфигурируя примитивы** и **трассируя сигнал** между ними (см. п.4), можно получить **практически любую цифровую схему** (с учетом ограничения ёмкости ПЛИС).
## Список источников
@@ -286,4 +282,5 @@ _Рисунок 19. Содержимое ПЛИС в виде межсоедин
1. Alchitry, Ell C / [How Does an FPGA Work?](https://learn.sparkfun.com/tutorials/how-does-an-fpga-work/all)
2. Xilinx / [The Programmable Gate Array Data Book](https://archive.org/details/programmablegate00xili)
3. Wikipedia / [Field-programmable gate array](https://en.wikipedia.org/wiki/Field-programmable_gate_array)
4. Ken Shirriff / [Reverse-engineering the first FPGA chip, the XC2064](http://www.righto.com/2020/09/reverse-engineering-first-fpga-chip.html)
4. Ross H. Freeman / Configurable electrical circuit having configurable logic elements and configurable interconnects / United States Patent
5. Ken Shirriff / [Reverse-engineering the first FPGA chip, the XC2064](http://www.righto.com/2020/09/reverse-engineering-first-fpga-chip.html)

View File

@@ -10,19 +10,19 @@
В русскоязычной литературе не сложилось устоявшихся терминов для этапов 1 и 3, но **elaboration** можно назвать как "**предобработку**" или "**развертывание**", а **implementation** как "**реализацию**" или "**построение**".
Этапы 2 и 4 переводятся дословно: **синтез** и "**генерация двоичного файла конфигурации** (**битстрима**)".
Более того, граница между этапами весьма условна и в зависимости от используемой **системы автоматизированного проектирования** (**САПР**), задачи, выполняемые на различных этапах, могут перетекать из одного в другой. Описание этапов будет даваться для маршрута проектирования под ПЛИС, однако, с некоторыми оговорками, эти же этапы используются и при проектировании сверхбольших интегральных схем (СБИС).
Более того, граница между этапами весьма условна и в зависимости от используемой **системы автоматизированного проектирования** (**САПР**), задачи, выполняемые на различных этапах, могут перетекать из одного в другой. Описание этапов будет даваться для маршрута проектирования под ПЛИС, однако, с некоторыми оговорками, эти же этапы используются и при проектировании ASIC.
Остановимся на каждом шаге подробнее.
## Elaboration
На этапе предобработки, САПР разбирает и анализирует HDL-описание вашего устройства, проверяет его на наличие синтаксических ошибок, производит подстановку значений параметров и блоков `generate`, устанавливает разрядности сигналов и строит иерархию модулей устройства.
На этапе предобработки, САПР разбирает и анализирует HDL-описание вашего устройства, проверяет его на наличие синтаксических ошибок, производит подстановку значений параметров, развёртывает конструкции, использующиеся для повторяющихся или параметризуемых частей кода, устанавливает разрядности сигналов и строит иерархию модулей устройства.
Затем, ставит в соответствие отдельным участкам кода соответствующие абстрактные элементы: логические вентили, мультиплексоры, элементы памяти и т.п. Кроме того, производится анализ и оптимизация схемы, например, если какая-то часть логики в конечном итоге не связана ни с одним из выходных сигналов, эта часть логики будет удалена[[1]](https://support.xilinx.com/s/question/0D52E00006iHshoSAC/what-exactly-is-elaborating-a-design?language=en_US).
Затем, ставит в соответствие отдельным участкам кода соответствующие абстрактные элементы: логические вентили, мультиплексоры, элементы памяти и т.п. Кроме того, производится анализ и оптимизация схемы, например, если какая-то часть логики в конечном итоге не связана ни с одним из выходных сигналов, она будет удалена[[1]](https://support.xilinx.com/s/question/0D52E00006iHshoSAC/what-exactly-is-elaborating-a-design?language=en_US).
Итогом предобработки является так называемая **топология межсоединений** (в быту называемая словом **нетлист**). **Нетлист** — это представление цифровой схемы в виде **графа**, где каждый элемент схемы является вершиной графа, а **цепи**, соединяющие эти элементы являются его ребрами. Нетлист может храниться как в виде каких-то внутренних файлов САПР-а (так хранится нетлист этапа **предобработки**), так и в виде **HDL**-файла, описывающего экземпляры примитивов и связи между ними. Рассмотрим этап предобработки и термин нетлиста на примере.
Допустим, мы хотим реализовать следующую цифровую схему:
Допустим, мы хотим реализовать схему, представленную на _рисунке 1_.
![../.pic/Introduction/Implementation%20steps/fig_01.drawio.svg](../.pic/Introduction/Implementation%20steps/fig_01.drawio.svg)
@@ -36,9 +36,10 @@ module sample(
output logic res
);
logic ab = a & b;
logic xabc = ab ^ c;
logic ab, xabc;
assign ab = a & b;
assign xabc = ab ^ c;
assign res = sel? d : xabc;
endmodule
@@ -60,13 +61,13 @@ _Рисунок 2. Результат этапа предобработки._
## Synthesis
На шаге синтеза, САПР берет сгенерированную ранее цифровую схему и реализует элементы этой схемы через примитивы конкретной ПЛИС — в основном через логические ячейки, содержащие таблицы подстановки, полный однобитный сумматор и `D-триггер` (см. [как работает ПЛИС](../Introduction/How%20FPGA%20works.md)).
На шаге синтеза, САПР берет сгенерированную ранее цифровую схему и реализует элементы этой схемы через примитивы конкретной ПЛИС — в основном через логические ячейки, содержащие таблицы подстановки, полный 1-битный сумматор и `D-триггер` (см. [как работает ПЛИС](../Introduction/How%20FPGA%20works.md)).
Поскольку в примере схема чисто **комбинационная**, результат её работы можно рассчитать и выразить в виде **таблицы истинности**, а значит для её реализации лучше всего подойдут **Таблицы Подстановки** (**LUT**-ы). Более того, в ПЛИС `xc7a100tcsg324-1` есть пятивходовые LUT-ы, а у нашей схемы именно столько входов. Это означает, работу всей этой схемы можно заменить **всего одной таблицей подстановки** внутри ПЛИС.
Итак, продолжим рассматривать наш пример и выполним этап синтеза. Для этого нажмем на кнопку `Run Synthesis`.
После выполнения синтеза у нас появится возможность открыть новый схематик, сделаем это.
После выполнения синтеза у нас появится возможность открыть новую схему, представленную на рисунке I.4-3.
![../.pic/Introduction/Implementation%20steps/fig_03.png](../.pic/Introduction/Implementation%20steps/fig_03.png)
@@ -98,9 +99,9 @@ _Рисунок 3. Результат этапа синтеза._
| 1 | 1 | 1 | 1 | 1 | | 1 |
```
Давайте посмотрим на логику исходной схемы и данную таблицу истинности: когда `sel==1`, на выход идет `d`, это означает, что мы знаем все значения для нижней половины таблицы истинности, в нижней половине таблице истинности самый левый входной сигнал (`sel`) равен только единице, значит результат будет совпадать с сигналом `d`, который непрерывно меняется с `0` на `1` и оканчивается значением `1`. Это означает, что если читать значения результатов снизу-вверх (от старших значений к младшим), то сначала у нас будет 16 цифр, представляющих 8 пар `10`:`101010101010`, что эквивалентно записи `AAAA` в шестнадцатеричной записи.
Давайте посмотрим на логику исходной схемы и данную таблицу истинности: когда `sel==1`, на выход идет `d`, это означает, что мы знаем все значения для нижней половины таблицы истинности, в нижней половине таблице истинности самый левый входной сигнал (`sel`) равен только единице, значит результат будет совпадать с сигналом `d`, который непрерывно меняется с `0` на `1` и оканчивается значением `1`. Это означает, что если читать значения результатов снизу-вверх (от старших значений к младшим), то сначала у нас будет 16 цифр, представляющих 8 пар `10`:`101010101010`, что эквивалентно записи `AAAA` в шестнадцатеричной форме.
Рассчитывать оставшиеся 16 вариантов тоже не обязательно, если посмотреть на схему, то можно заметить, что когда `sel!=1`, ни `sel`, ни `d` больше не участвуют в управлении выходом. Выход будет зависеть от операции xor, которая дает `1` только когда её входы не равны между собой. Верхний вход xor (выход И) , будет равен единице только когда входы `a` и `b` равны единице, причем в данный момент, нас интересуют только ситуации, когда `sel!=1`. Принимая во внимание, что в таблице истинности значения входов записываются чередующимися степенями двойки (единицами, парами, четверками, восьмерками) единиц и нулей, мы понимаем, что интересующая нас часть таблицы истинности будет выглядеть следующим образом:
Рассчитывать оставшиеся 16 вариантов тоже не обязательно, если посмотреть на схему, то можно заметить, что когда `sel!=1`, ни `sel`, ни `d` больше не участвуют в управлении выходом. Выход будет зависеть от операции XOR, которая дает `1` только когда её входы не равны между собой. Верхний вход XOR (выход И) , будет равен единице только когда входы `a` и `b` равны единице, причем в данный момент, нас интересуют только ситуации, когда `sel!=1`. Принимая во внимание, что в таблице истинности значения входов записываются чередующимися степенями двойки (единицами, парами, четверками, восьмерками) единиц и нулей, мы понимаем, что интересующая нас часть таблицы истинности будет выглядеть следующим образом:
```ascii
...
@@ -115,7 +116,7 @@ _Рисунок 3. Результат этапа синтеза._
...
```
Только в этой части таблицы истинности мы получим `1` на выходе **И**, при этом в старшей части, вход `c` так же равен `1`. Это значит, что входы **Исключающего ИЛИ** будут равны и на выходе будет `0`. Значит результат этой таблицы истинности будет равен `0011` или `3` в шестнадцатеричной записи.
Только в этой части таблицы истинности мы получим `1` на выходе **И**, при этом в старшей части, вход `c` также равен `1`. Это значит, что входы **Исключающего ИЛИ** будут равны и на выходе будет `0`. Значит результат этой таблицы истинности будет равен `0011` или `3` в шестнадцатеричной записи.
Ниже данной части таблицы истинности располагается та часть, где `sel==1`, выше та часть, где выход **И** будет равен `0`. Это означает, что оставшаяся младшая часть будет повторять значения `c`, которое сменяется парами нулей и единиц: `00-11-00-11..`. Эта оставшаяся последовательность будет записана в шестнадцатеричном виде как `0xCCC`.
@@ -124,7 +125,7 @@ _Рисунок 3. Результат этапа синтеза._
## Implementation
После получения нетлиста, где в качестве элементов используются ресурсы конкретной ПЛИС, происходит **размещение** этой схемы на элементы заданной ПЛИС: выбираются конкретные логические ячейки. Затем происходит **трассировка** (маршрутизация) связей между ними. Для этих процедур часто используется термин **place & route** (размещение и трассировка). Например, реализация 32-битного сумматора с ускоренным переносом может потребовать 32 LUT-а и 8 примитивов вычисления быстрого переноса (`CARRY4`). Будет неразумно использовать для этого примитивы, разбросанные по всему кристаллу ПЛИС, ведь тогда придётся выполнять сложную трассировку сигнала, да и временные характеристики устройства так же пострадают (сигналу, идущему от предыдущего разряда к следующему, придётся проходить больший путь). Вместо этого, САПР будет пытаться разместить схему таким образом, чтобы использовались близлежащие примитивы ПЛИС, для получения оптимальных характеристик.
После получения нетлиста, где в качестве элементов используются ресурсы конкретной ПЛИС, происходит **размещение** этой схемы на элементы заданной ПЛИС: выбираются конкретные логические ячейки. Затем происходит **трассировка** (маршрутизация) связей между ними. Для этих процедур часто используется термин **place & route** (размещение и трассировка). Например, реализация 32-битного сумматора с ускоренным переносом может потребовать 32 LUT-а и 8 примитивов вычисления быстрого переноса (`CARRY4`). Будет неразумно использовать для этого примитивы, разбросанные по всему кристаллу ПЛИС, ведь тогда придётся выполнять сложную трассировку сигнала, да и временные характеристики устройства также пострадают (сигналу, идущему от предыдущего разряда к следующему, придётся проходить больший путь). Вместо этого, САПР будет пытаться разместить схему таким образом, чтобы использовались близлежащие примитивы ПЛИС, для получения оптимальных характеристик.
Что именно считается "оптимальным" зависит от двух вещей: настроек САПР и **ограничений** (**constraints**), учитываемых при построении итоговой схемы в ПЛИС. Ограничения сужают область возможных решений по размещению примитивов внутри ПЛИС под определенные характеристики (временны́е и физические). Например, можно сказать, внутри ПЛИС схема должна быть размещена таким образом, чтобы время прохождения по **критическому пути** не превышало `20ns`. Это временно́е ограничение. Также нужно сообщить САПР, к какой ножке ПЛИС необходимо подключить входы и выходы нашей схемы — это физическое ограничение.
@@ -182,13 +183,13 @@ set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { resetn
_Рисунок 4. "Адрес" конкретного LUT-а в ПЛИС._
Теперь, мы можем посмотреть на "внутренности" нашей ПЛИС `xc7a100tcsg324-1` и то, как через её примитивы будет реализована наша схема. Для этого необходимо открыть построенную схему: `Implementation -> Open implemented design`. Откроется следующее окно:
Теперь, мы можем посмотреть на "внутренности" нашей ПЛИС `xc7a100tcsg324-1` и то, как через её примитивы будет реализована наша схема. Для этого необходимо открыть построенную схему: `Implementation -> Open implemented design`. Откроется окно, представленное на _рис. 5_.
![../.pic/Introduction/Implementation%20steps/fig_05.png](../.pic/Introduction/Implementation%20steps/fig_05.png)
_Рисунок 5. Окно просмотра реализованного устройства._
Это содержимое ПЛИС. Просто из-за огромного количества содержащихся в ней примитивов, оно показана в таком масштабе, что все сливается в один цветной ковер. Большая часть этого окна неактивна (показана в темно-синих тонах) и это нормально, ведь мы реализовали крошечную цифровую схему, она и не должна занимать значительное количество ресурсов ПЛИС.
Это содержимое ПЛИС. Просто из-за огромного количества содержащихся в ней примитивов, оно показана в таком масштабе, что всё сливается в один цветной ковёр. Большая часть этого окна неактивна (показана в тёмно-синих тонах) и это нормально, ведь мы реализовали крошечную цифровую схему, она и не должна занимать значительное количество ресурсов ПЛИС.
Нас интересует "[бледно-голубая точка](https://ru.wikipedia.org/wiki/Pale_Blue_Dot)", расположенная в нижнем левом углу прямоугольника `X0Y1` (выделено красным). Если отмасштабировать эту зону, мы найдем используемый нами LUT:

View File

@@ -6,7 +6,7 @@
**Комбинационная логика** (или "логика без памяти") — это цифровая логика, выходы которой зависят только от её входов. Один и тот же набор входных воздействий на эту логику всегда будет давать один и тот же результат. Комбинационную логику можно всегда представить в виде таблицы истинности (или логической функции) всех её выходов от её входов.
В противоположность комбинационной, существует также и последовательностная логика, или "логика с памятью" — цифровая логика, выходы которой зависят не только от её входов, но и от её внутреннего состояния.
В противоположность комбинационной, существует также и **последовательностная логика**, или "логика с памятью" — цифровая логика, выходы которой зависят не только от её входов, но и от её внутреннего состояния.
Простейшим примером комбинационной логики может быть любой логический вентиль, например исключающее ИЛИ (_рис. 1 (а)_). Эта комбинационная схема всегда будет давать `0`, если оба её входа равны, в противном случае, она выдаст `1`.
@@ -16,18 +16,21 @@ _Рисунок 1. Пример комбинационной (а), и после
Предположим теперь, что в качестве одного из входов исключающего ИЛИ стоит некая ячейка памяти, которая запоминает предыдущее значение, выданное этим логическим вентилем (_рис. 1 (б)_). Теперь, выходы схемы зависят не только от того, что мы подадим на вход, но и от того, что находится в данной ячейке памяти, а самое главное — теперь, подавая на вход одно и тоже воздействие, мы можем получить разные результаты.
Будем исходить из того, что изначально ячейка памяти проинициализирована нулём. Сперва подадим на вход этой схемы `0`. Поскольку оба входа равны `0`, на выход схемы подаётся `0`, и значение в ячейке памяти остаётся прежним. Затем, подадим на вход `1` — теперь на выход схемы идёт значение `1` и оно же сохраняется в ячейке памяти. После, мы снова подаём на вход `0`, однако, в отличие от первого раза, на выход схемы пойдёт `1`, т.к. входы логического ИЛИ не равны. Выставив на вход `1` ещё раз, мы получим на выходе `0`.
Будем исходить из того, что изначально ячейка памяти проинициализирована нулём. Сперва подадим на вход этой схемы `0`. Поскольку оба входа равны `0`, на выход схемы подаётся `0`, и значение в ячейке памяти остаётся прежним. Затем, подадим на вход `1` — теперь на выход схемы идёт значение `1` и оно же сохраняется в ячейке памяти. После, мы снова подаём на вход `0`, однако, в отличие от первого раза, на выход схемы пойдёт `1`, т.к. входы исключающего ИЛИ не равны. Выставив на вход `1` ещё раз, мы получим на выходе `0`.
Как вы видите, результат последовательностной логики зависит от **последовательности** произведённых входных воздействий, в то время как комбинационная логика зависит от **комбинации** её текущих входных воздействий.
Последовательностная логика делится на **синхронную** и **асинхронную**.
**Синхронной логикой** называется такая логика, обновляет своё состояние (содержимое ячеек памяти) одновременно (**синхронно**) с фронтом тактового сигнала. В свою очередь **асинхронная последовательностная логика** — это логика, которая может обновлять своё состояние **асинхронно** (т.е. без привязки к фронту тактового синхроимпульса). Бывает также и синхронная логика с асинхронными сигналами предустановки/сброса.
**Синхронной логикой** называется такая логика, которая обновляет своё состояние (содержимое ячеек памяти) одновременно (**синхронно**) с фронтом тактового сигнала. В свою очередь **асинхронная последовательностная логика** — это логика, которая может обновлять своё состояние **асинхронно** (т.е. без привязки к фронту тактового синхроимпульса). Бывает также и синхронная логика с асинхронными сигналами предустановки/сброса.
Комбинационная логика по своей природе является асинхронной, поэтому в зависимости от контекста под "асинхронной логикой" может подразумеваться как комбинационная логика, так и последовательностная логика, которая может обновлять значение не по фронту тактового синхроимпульса.
## Бистабильные ячейки
**Статическая память** — это тип памяти, который сохраняет данные в течение неопределённого времени, пока его питание остаётся включённым, без необходимости регенерации (в отличие от **динамической памяти**, которая требует регулярного обновления данных для их сохранения). Основой статической памяти является **бистабильная ячейка** — элемент, способный сохранять одно из двух устойчивых состояний, соответствующих цифровым значениям «0» или «1».
**Бистабильная ячейка** — это элемент статической памяти, способный принимать одно из двух устойчивых состояний, соответствующих цифровым значениям "0" или "1".
**Статическая память** — это тип памяти, который сохраняет данные в течении неопределённого времени, пока его питание остаётся включённым, без необходимости регенерации (в отличие от **динамической памяти**, использующей для хранения конденсаторы, требующие для хранения регулярного обновления данных).
Рассмотрим простейшую ячейку статической памяти, представленную на _рис. 2_, которая способна хранить 1 бит информации.
@@ -37,7 +40,7 @@ _Рисунок 2. Простейшая ячейка статической па
Данная ячейка представляет собой петлю из двух инверторов, в которых "заперто" хранимое значение. Дважды инвертированный сигнал совпадает по значению с исходным, при этом проходя через каждый из инверторов, сигнал обновляет своё значение напряжения, поддерживая тем самым уровни напряжения логических значений. Главной проблемой подобной ячейки является то, что она требует дополнительной аппаратуры для записи в эту ячейку хранимой информации.
Для того, чтобы добавить в эту ячейку входы с возможностью записи данных, проще всего будет поставить перед инверторами логические элементы ИЛИ (которые совместно инверторами образуют элементы ИЛИ-НЕ).
Для того, чтобы добавить в эту ячейку входы с возможностью записи данных, проще всего будет поставить перед инверторами логические элементы ИЛИ (которые совместно с инверторами образуют элементы ИЛИ-НЕ).
В результате получится **RS-триггер** — бистабильная ячейка, представленная на _рис. 3_.
@@ -45,25 +48,25 @@ _Рисунок 2. Простейшая ячейка статической па
![../.pic/Introduction/Sequential%20logic/fig_03.drawio.svg](../.pic/Introduction/Sequential%20logic/fig_03.drawio.svg)
_Рисунок 3. Схема и таблица истинности RS-триггера. Q' означает, что на выход Q пойдет его предыдущее значение._
_Рисунок 3. Схема и таблица истинности RS-триггера. X означает, что в этой строке результат не зависит от хранимого значения._
RS-триггер — это бистабильная ячейка, имеющая два управляющих входа: `R` (reset) и `S` (set), и два выхода: `Q` и `Q̅`. `Q̅` является инверсией `Q`. RS-триггер, построенный на логических элементах ИЛИ-НЕ, работает следующим образом:
1. Если вход `R=1`, а `S=0`, то выход верхнего элемента ИЛИ-НЕ (а значит и выход `Q`) равен `0` вне зависимости от второго его входа. Этот выход поступает вместе с входом `S` на нижний элемент ИЛИ-НЕ, который выдаёт `1` (на выход `Q̅`), поскольку оба его входа равны `0`. Эта единица подаётся на второй вход верхнего элемента ИЛИ-НЕ и теперь, даже если вход `R` станет равным `0`, `1` на втором его входе сможет воспроизвести тоже самое поведение, запирая таким образом внутри триггера стабильное состояние `Q=0`.
2. Если вход `R=0`, а `S=1`, схема работает противоположным образом: поскольку на нижний элемент подаётся `1` с входа `S`, выход `Q̅` равен `0` вне зависимости от второго входа нижнего элемента ИЛИ-НЕ. Этот ноль подаётся на второй вход верхнего элемента ИЛИ-НЕ, и поскольку оба его входа равны `0`, на выходе этого элемента (на выход `Q`) подаётся `1`, которая возвращается обратно на вход нижнего элемента ИЛИ-НЕ, запирая таким образом внутри триггера стабильное состояние `Q=1`.
1. Если вход `R=1`, а `S=0`, то выход верхнего элемента ИЛИ-НЕ (а значит и выход `Q`) равен `0` вне зависимости от второго его входа. Этот выход поступает вместе с входом `S` на нижний элемент ИЛИ-НЕ, который выдаёт `1` (на выход `Q̅`), поскольку оба его входа равны `0`. Эта единица подаётся на второй вход верхнего элемента ИЛИ-НЕ и теперь, даже если вход `R` станет равным `0`, `1` на втором его входе сможет воспроизвести тоже самое поведение, запирая внутри триггера стабильное состояние `Q=0`.
2. Если вход `R=0`, а `S=1`, схема работает противоположным образом: поскольку на нижний элемент подаётся `1` с входа `S`, выход `Q̅` равен `0` вне зависимости от второго входа нижнего элемента ИЛИ-НЕ. Этот ноль подаётся на второй вход верхнего элемента ИЛИ-НЕ, и поскольку оба его входа равны `0`, на выходе этого элемента (на выход `Q`) подаётся `1`, которая возвращается обратно на вход нижнего элемента ИЛИ-НЕ, запирая внутри триггера стабильное состояние `Q=1`.
3. Таким образом, если на оба входа одновременно равны `0`, RS-триггер хранит своё предыдущее значение.
Проблемой данного триггера является то, что он имеет **запрещённую** комбинацию входов. В случае RS-триггера, построенного на элементах ИЛИ-НЕ, таковой комбинацией входов является `R=1` и `S=1`. Даже с точки зрения функционального назначения, данная комбинация не имеет смысла: кому потребуется одновременно и сбрасывать RS-триггер в 0 и устанавливать его в 1? Тем не менее, вот что произойдет, если использовать эту комбинацию:
4. Если оба входа одновременно равны `1`, то оба выхода Q и Q̅ будут равны `0`, что нарушает логику работы триггера, поскольку выход Q̅ должен быть инверсией выхода Q. При этом, если после этого перевести оба входа в `0`, RS-триггер окажется в неустойчивом состоянии (в состоянии гонки), а выходы могут начать неопределённо долго инвертироваться. Пока RS-триггер был в запрещённом состоянии, выходы `Q` и `Q̅`, равные `0`, подавались на входы обоих элементов ИЛИ-НЕ, а если после этого **одновременно** перевести входы `R` и `S` в состояние `0`, то на входах обоих вентилей будут `0`, что побудит их выдать на выходы `1`, которые пойдут обратно на входы этих вентилей, после чего те подадут на выход `0`, и так будет продолжаться до тех пор, пока один из сигналов в петле обратной связи не выиграет гонку, и RS-триггер не окажется в стабильном состоянии `0` либо `1`.
Для того, чтобы избавиться от запрещённого состояния RS-триггера, была придумана D-защёлка (gated D-latch).
Для того чтобы избавиться от запрещённого состояния RS-триггера, была придумана D-защёлка (gated D-latch).
## D-защелка
D-защёлка — это бистабильная ячейка памяти, имеющая входы `D` (Data) и `E` (enable). Иногда вход enable называют clk (clock) или G (gated), что никак не сказывается на его функциональном назначении. Когда сигнал `E` равен `1`, D-защёлка "захватывает" данные с входа `D` (отсюда и её название). Когда сигнал `E` равен `0`, D-защёлка сохраняет уже захваченные данные.
D-защёлка — это бистабильная ячейка памяти, имеющая входы `D` (Data) и `E` (enable). Иногда вход enable называют clk (clock) или G (gated), что никак не сказывается на его функциональном назначении. Когда сигнал `E` равен `1`, D-защёлка "захватывает" данные с входа `D`. Когда сигнал `E` равен `0`, D-защёлка сохраняет уже захваченные данные.
D-защёлка строится на базе RS-триггера, к которому добавляется логика, исключающая возможность появления запрещённого состояния (_рис. 4_).
D-защёлка может быть построена на базе RS-триггера, к которому добавляется логика, исключающая возможность появления запрещённого состояния (_рис. 4_).
![../.pic/Introduction/Sequential%20logic/fig_04.drawio.svg](../.pic/Introduction/Sequential%20logic/fig_04.drawio.svg)
@@ -71,9 +74,7 @@ _Рисунок 4. Схема и таблица истинности D-защё
Логика работы D-защёлки заключается в следующем. Когда сигнал `E` равен `0`, логические вентили И подают на выход `0` вне зависимости от второго входа, и RS-триггер переходит в состояние хранения текущего значения. В такой ситуации говорят, что D-защёлка "закрыта", или "перешла в непрозрачное состояние". Когда сигнал `E` равен `1`, логические элементы И, добавленные перед входами RS-триггера передают на выход значение со второго их входа. При этом на второй вход этих элементов подаются противоположные сигналы: `!D` и `D`, что исключает возможность одновременного появления `1` на входах `R` и `S`. В этом случае в RS-триггер попадает значение с входа `D`, а про D-защёлку говорят, что она "открыта" (перешла в "прозрачное" состояние). Пока защёлка "прозрачна", данные со входа `D` идут напрямую на выход `Q`.
Несмотря на то, что D-защёлка устраняет главный недостаток RS-триггера, она тоже является не самой надёжной бистабильной ячейкой памяти. Дело в том, что D-защёлка пропускает на выход данные со входа `D` всё то время, пока она "прозрачна". Это значит, что она будет пропускать через себя все возможные переходные процессы сигнала `D`. Это значит, что она будет распространять переходные процессы сигналов со входа D, на которые будут реагировать последующие участки цифровой схемы. Таким образом через всю цифровую схему, начиная со входов, будут распространяться переходные процессы. В результате определить моменты времени, в которых на выходе схемы будет корректный результат обработки входного сигнала, станет практически невозможно. Было бы гораздо удобней, если бы могли сохранять данные одномоментно, когда на входе `D` уже находится установившееся значение, отсекая тем самым на каждом элементе памяти переходные процессы всех предыдущих участков цифровой схемы.
Таким элементом памяти, является D-триггер (D flip-flop).
Несмотря на то, что D-защёлка устраняет главный недостаток RS-триггера, она тоже является не самой надёжной бистабильной ячейкой памяти. Дело в том, что D-защёлка пропускает на выход данные со входа `D` всё то время, пока она "прозрачна". Это значит, что она будет пропускать через себя все возможные переходные процессы сигнала `D`. Это значит, что она будет распространять переходные процессы сигналов со входа D, на которые будут реагировать последующие участки цифровой схемы. Из-за этого, через всю цифровую схему, начиная со входов, будут распространяться переходные процессы. В результате определить моменты времени, в которых на выходе схемы будет корректный результат обработки входного сигнала, станет практически невозможно. Было бы гораздо удобней, если бы могли сохранять данные одномоментно, когда на входе `D` уже находится установившееся значение, отсекая тем самым на каждом элементе памяти переходные процессы всех предыдущих участков цифровой схемы. Таким элементом памяти, является D-триггер (D flip-flop).
## D-триггер
@@ -101,7 +102,7 @@ _Рисунок 6. Конфигурируемая ячейка памяти ПЛ
![../.pic/Introduction/Sequential%20logic/fig_07.svg](../.pic/Introduction/Sequential%20logic/fig_07.svg)
_Рисунок 7. Передаточные функции для: а) одиночного КМОП-инвертора; б) пары инверторов, объединённых в бистабильную петлю [2, стр. 497]._
_Рисунок 7. Передаточные функции для: а) одиночного КМОП-инвертора; б) пары инверторов, объединённых в бистабильную петлю [3, стр. 497]._
Как вы можете заметить, таких точек почему-то не две, а три. Две эти точки обозначены как **стабильные** и соответствуют привычным цифровым значениям 1 (для 3В) и 0 (для 0В). Третья точка равновесия обозначена как **метастабильная** и расположена примерно посередине между этими двумя значениями. И действительно, согласно графику, если подать на вход приблизительно 1.5В, на выходе будет точно такое же напряжение, которое затем будет подано на вход второго инвертора и т.д., благодаря чему петля будет находиться в подобном состоянии неопределённый промежуток времени. Подобное состояние называется **метастабильным состоянием** и присуще любой бистабильной ячейке.
@@ -109,7 +110,7 @@ _Рисунок 7. Передаточные функции для: а) один
![../.pic/Introduction/Sequential%20logic/fig_08.svg](../.pic/Introduction/Sequential%20logic/fig_08.svg)
_Рисунок 8. Механическая аналогия явлению метастабильности [2, стр. 498]._
_Рисунок 8. Механическая аналогия явлению метастабильности [3, стр. 498]._
Вернёмся к _рис. 7_ (б). Предположим, что инвертор находится в метастабильном состоянии и в цепи возникла случайная наводка, слегка отклонившая напряжение на входе одного из инверторов. Это отклонение усилится на выходе инвертора и попадёт на вход второго инвертора, усилившись на котором оно вернётся на вход первого инвертора и т.д. пока в конечном итоге не остановится в верхней равновесной точке.
@@ -117,33 +118,34 @@ _Рисунок 8. Механическая аналогия явлению ме
В случае метастабильного состояния — мы не можем предсказать, конкретное значение того, как долго ячейка будет находиться в этом состоянии — это случайная величина, для которой может быть оценено значение вероятности. Например, можно сделать оценку вроде: "вероятность того, что бистабильная ячейка выйдет из метастабильного состояния через 100мс много выше вероятности, что она выйдет из этого состояния через 100 секунд"
Таким образом, метастабильность — это явление, возникающее входе нарушения условий работы цифровых элементов. В обычных случаях это явление является нежелательным (если только вы не планируете использовать свою схему в качестве генератора случайных чисел) и важно знать, как его избежать.
Таким образом, метастабильность — это явление, возникающее в ходе нарушения условий работы цифровых элементов. В обычных случаях это явление является нежелательным (если только вы не планируете использовать свою схему в качестве генератора случайных чисел) и важно знать, как его избежать.
Любые бистабильные ячейки имеют специальные временны́е параметры (ограничения), которые несоблюдение которых может привести к появлению метастабильности. В рамках этого курса, вы будете работать в основном с бистабильными ячейками, представленными в виде D-триггеров. Для D-триггеров таковыми временными параметрами являются:
Любые бистабильные ячейки имеют специальные временны́е параметры (ограничения), несоблюдение которых может привести к появлению метастабильности. В рамках этого курса, вы будете работать в основном с бистабильными ячейками, представленными в виде D-триггеров. Для D-триггеров таковыми временными параметрами являются:
- T<sub>setup</sub> (**setup time**) — **время предустановки**. Это интервал, в течение которого сигнал на входе `D` должен оставаться неизменным перед наступлением фронта тактового сигнала.
- T<sub>hold</sub> (**hold time**) — **время удержания**. Это интервал, в течение которого сигнал на входе `D` должен оставаться стабильным после наступления фронта тактового сигнала.
- T<sub>setup</sub> (**setup time**) — **время предустановки**. Это интервал времени, в течение которого сигнал на входе `D` должен оставаться неизменным перед наступлением фронта тактового сигнала.
- T<sub>hold</sub> (**hold time**) — **время удержания**. Это интервал времени, в течение которого сигнал на входе `D` должен оставаться стабильным после наступления фронта тактового сигнала.
Эти два параметра образуют временное окно вокруг фронта тактового сигнала, в течение которого входной сигнал должен оставаться стабильным. Несоблюдение данных требований приводит к неопределённому поведению триггера (см. _рис. 9_). В простейшем случае он сохранит либо "старое", либо "новое" значение, пришедшее на вход данных D в непосредственной близости от фронта клока, но какое именно — неизвестно. Однако иногда "звёзды сойдутся", и триггер окажется в метастабильном состоянии. Вероятность этого крайне мала (о таком событии можно сказать, что оно "одно на миллиард"), однако не стоит относиться к нему с пренебрежением. Если схема работает на частоте в 1ГГц, триггер будет обновлять своё состояние миллиард раз в секунду, а сама схема может содержать миллионы триггеров. В таком контексте, фраза "одно на миллиард" означает не "ничего страшного, скорее при моей жизни этого не произойдёт", а "чёрт, кажется, что поэтому у меня ничего не работает".
![../.pic/Introduction/Sequential%20logic/fig_09.drawio.svg](../.pic/Introduction/Sequential%20logic/fig_09.drawio.svg)
_Рисунок 9. Пример нарушения временны́х параметров D-триггера [[3](https://habr.com/ru/articles/254869/)]._
_Рисунок 9. Пример нарушения временны́х параметров D-триггера [[4](https://habr.com/ru/articles/254869/)]._
На _рис. 9_ показано три различных исхода нарушения временных ограничений:
1. Выход триггера Q<sub>1</sub> принял новое значение сигнала D, которое было установлено во временном промежутке T<sub>setup</sub>.
2. Выход триггера Q<sub>1</sub> принял старое значение сигнала D, которое было установлено до на входе до начала T<sub>setup</sub>. На следующем положительном фронте clk на входе D находится уже установившееся значение, которое без проблем записывается в триггер.
2. Выход триггера Q<sub>1</sub> принял старое значение сигнала D, которое было установлено на входе до начала T<sub>setup</sub>. На следующем положительном фронте clk на входе D находится уже установившееся значение, которое без проблем записывается в триггер.
3. Перемена в уровне во время T<sub>setup</sub> привело к тому, что на триггер было подано напряжение, равное половине уровня логической единицы, и тот оказался в метастабильном состоянии. Спустя некоторое время, триггер оказался в одном из стабильном состояний, но в каком — никто заранее предсказать не может (заштрихованная область, где триггер принял значение либо 0, либо 1). На следующем положительном фронте clk на входе D находится уже установившееся значение, которое без проблем записывается в триггер.
Нарушение по T<sub>setup</sub> происходит, когда схема работает на частоте, не подходящей для имеющегося у схемы критического пути. Критический путь — это комбинационная часть цифровой схемы с наибольшей задержкой распространения сигнала. Время прохождения сигнала по этому пути характеризует минимально возможный период тактового сигнала и, соответственно, максимальную тактовую частоту работы всей схемы.
Нарушение по T<sub>setup</sub> обычно происходит, когда схема работает на частоте, не подходящей для имеющегося у схемы критического пути. Критический путь — это комбинационная часть цифровой схемы с наибольшей задержкой распространения сигнала. Время прохождения сигнала по этому пути характеризует минимально возможный период тактового сигнала и, соответственно, максимальную тактовую частоту работы всей схемы.
Если подать на схему частоту, превышающую ограничение, определяемое критическим путём, сигнал может не принять установившееся значение на конце критического пути и, если на этом конце находится вход триггера — будут нарушено его ограничение по времени предустановки T<sub>setup</sub>.
Нарушение по T<sub>hold</sub> происходит, когда у схемы есть пути с задержкой распространения сигнала до элементов последовательностной логики, которая меньше минимально допустимой. Данные пути напрямую не влияют на значение максимальной частоты, но требуют добавления элементов задержки на кратчайшие пути. Такие пути, как правило, являются значительно проблемой при проектировании ASIC.
Нарушение по T<sub>hold</sub> происходит, когда у схемы есть пути с задержкой распространения сигнала до элементов последовательностной логики, которая меньше минимально допустимой. Данные пути напрямую не влияют на значение максимальной частоты, но требуют добавления элементов задержки на кратчайшие пути. Такие пути, как правило, являются значительной проблемой при проектировании интегральных схем специального назначения (application-specific integrated circuit, **ASIC**).
Допустим в схеме есть два регистра А и Б, задержка распространения сигнала между которыми меньше допустимой. В этом случае, в момент фронта синхроимпульса с выхода регистра А может начать распространяться изменение в уровне сигнала. Это изменение достигнет входа регистра Б в этом же такте, пока у того не завершилось время удержания T<sub>hold</sub>.
Для того, определить способна ли проектируемая схема работать на целевой частоте, выполняется **статический временной анализ** (**static timing analysis**, **STA**). В процессе STA, САПР рассчитывает задержки всех временных путей схемы и определяет критический путь. Итогом статического временного анализа является оценка запаса по времени (или времени простоя, англ.: slack) для каждого временного пути, когда схема работает на заданной частоте. Если slack положительный — это значит, что задержка критического пути схемы меньше предельно допустимой, и возможно увеличение частоты схемы (например, при небольшом снижении напряжения питания) в пределах данной величины. Если slack отрицательный — это значит, что задержка по критическому пути уже превысила допустимую, и для корректной работы схемы необходимо либо изменить критический путь таким образом, чтобы сократилась его задержка распространения сигнала, либо уменьшить тактовую частоту.
Для того чтобы определить, способна ли проектируемая схема работать на целевой частоте, выполняется **статический временной анализ** (**static timing analysis**, **STA**). В процессе STA, САПР рассчитывает задержки всех временных путей схемы и определяет критический путь. Итогом статического временного анализа является оценка запаса по времени (или времени простоя, англ.: slack) для каждого временного пути, когда схема работает на заданной частоте. Если slack положительный — это значит, что задержка критического пути схемы меньше предельно допустимой, и возможно увеличение частоты схемы (например, при небольшом снижении напряжения питания) в пределах данной величины. Если slack отрицательный — это значит, что задержка по критическому пути уже превысила допустимую, и для корректной работы схемы необходимо либо изменить критический путь таким образом, чтобы сократилась его задержка распространения сигнала, либо уменьшить тактовую частоту.
К сожалению, соблюсти временны́е ограничения триггеров не всегда возможно, поскольку в некоторых случаях, вход данных может по своей природе быть асинхронен (т.е. никаким образом не зависеть от входного тактового сигнала). К примеру, данные на вход триггера подаются со входа цифровой схемы, который подключён к кнопке, нажатие на которую никак не привязано к тактовому синхроимпульсу. В других случаях, необходимо передать данные, синхронизированные с одним тактовым сигналом, в область схемы, работающей от другого тактового сигнала. Подобная ситуация называется **пересечением тактовых доменов**, или **clock domain crossing** (**CDC**). В зависимости от конкретного сценария, существуют различные схемы синхронизации, самой простой из которых является установка дополнительного триггера там, где прогнозируется возникновение метастабильного состояния (рис. 10). В высокой долей вероятности в течении 1-2 тактов на выходе синхронизирующего триггера окажется стабильное состояние, которое подавалось на вход Din. Неопределённость в количестве тактов появляется из-за того, что мы не знаем, в какую сторону "свалится" состояние первого регистра в цепи.

View File

@@ -8,13 +8,13 @@ _Рисунок 1. Цифровая схема процессора Intel 4004
Данная микросхема состоит из 2300 транзисторов[[2]](https://en.wikipedia.org/wiki/Intel_4004).
За прошедшие полсотни лет сложность цифровых схем выросла колоссально. Современные процессоры для настольных компьютеров состоят из десятков миллиардов транзисторов. Диаграмма выше при печати в оригинальном размере займет прямоугольник размером 115х140см с площадью около 1.6м<sup>2</sup>. Предполагая, что площадь печати имеет прямо пропорциональную зависимость от количества транзисторов, получим что распечатка схемы современного процессора из 23 млрд транзисторов заняла бы площадь в 16млн. м<sup>2</sup>, что эквивалентно квадрату со стороной в 4км.
За прошедшие полсотни лет сложность цифровых схем выросла колоссально. Современные процессоры для настольных компьютеров состоят из десятков миллиардов транзисторов. Диаграмма выше при печати в оригинальном размере займет прямоугольник размером 115х140см с площадью около 1.6м<sup>2</sup>. Предполагая, что площадь печати имеет прямо пропорциональную зависимость от количества транзисторов, получим, что распечатка схемы современного процессора из 23 млрд транзисторов заняла бы площадь в 16млнм<sup>2</sup>, что эквивалентно квадрату со стороной в 4км.
<img src="../.pic/Introduction/What%20is%20HDL/ancient_city.png" alt="Старый город" width="400"/>
_Рисунок 2. Масштаб размеров, которых могли бы достигать цифровые схемы современных процессоров, если бы они печатались на бумаге._
Как вы можете догадаться в какой-то момент между 1971-ым и 2022-ым годами инженеры перестали разрабатывать цифровые схемы, рисуя их на бумаге.
Как вы можете догадаться, в какой-то момент между 1971-м и 2024-м годами инженеры перестали разрабатывать цифровые схемы, рисуя их на бумаге.
Разумеется, разрабатывая устройство, не обязательно вырисовывать на схеме каждый транзистор — можно управлять сложностью, переходя с одного уровня абстракции на другой. Например, начинать разработку схемы с уровня функциональных блоков, а затем рисовать схему для каждого отдельного блока.
@@ -30,7 +30,7 @@ _Рисунок 3. Цифровая схема процессора Intel 4004
_Рисунок 4. Цифровая схема блока аппаратного шифрования по алгоритму AES[[4]](https://iis-people.ee.ethz.ch/~kgf/acacia/acacia_thesis.pdf)._
Заметьте, что даже этот блок не представлен на уровне отдельных транзисторов. Каждая операция Исключающего ИЛИ, умножения, мультиплексирования сигнала и таблицы подстановки — это отдельные блоки, функционал которых еще надо реализовать.
Заметьте, что даже этот блок не представлен на уровне отдельных транзисторов. Каждая операция Исключающего ИЛИ, умножения, мультиплексирования сигнала и таблицы подстановки — это отдельные блоки, функционал которых ещё надо реализовать.
В какой-то момент инженеры поняли, что проще описать цифровую схему в текстовом представлении, нежели в графическом.
Как можно описать цифровую схему текстом? Рассмотрим цифровую схему полусумматора:
@@ -70,9 +70,9 @@ endmodule
Важно отметить, что код на языке Verilog описывает устройство целиком, одномоментно. Это **описание схемы** выше, а **не построчное выполнение программы**.
С практикой описание схемы в текстовом виде становится намного проще и не требует графического представления. Для описания достаточно только спецификации: формальной записи того, что должно делать устройство, по которой разрабатывается алгоритм, который затем претворяется в описание на HDL.
С практикой описание схемы в текстовом виде становится намного проще и не требует графического представления. Для описания достаточно только спецификации: формальной записи того, как должно работать устройство. По ней разрабатывается алгоритм, который затем претворяется в описание на HDL.
Занятный факт: ранее было высказано предположение о том, что инженеры перестали разрабатывать устройства, рисуя цифровые схемы в промежуток времени между 1971-ым и 2022-ым годами. Так вот, первая конференция, посвященная языкам описания аппаратуры состоялась в 1973-ем году[[5, стр.8]](https://dl.acm.org/doi/pdf/10.1145/3386337). Таким образом, Intel 4004 можно считать одним из последних цифровых устройств, разработанных без использования языков описания аппаратуры.
Занятный факт: ранее было высказано предположение о том, что инженеры перестали разрабатывать устройства, рисуя цифровые схемы в промежуток времени между 1971-м и 2024-м годами. Так вот, первая конференция, посвящённая языкам описания аппаратуры состоялась в 1973-м году[[5, стр.8]](https://dl.acm.org/doi/pdf/10.1145/3386337). Таким образом, Intel 4004 можно считать одним из последних цифровых устройств, разработанных без использования языков описания аппаратуры.
## Список источников