mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 09:10:10 +00:00
Синхронизация с правками публикуемого издания (#101)
* СП. Обновление предисловия * СП. Обновление введения * СП. Обновление лаб * СП. Обновление доп материалов * СП. Введение * СП. Введение * СП. ЛР№4, 15 * СП. Базовые конструкции Verilog * Update Implementation steps.md * СП. ЛР 4,5,7,8,14 * СП. ЛР№8 * Синхронизация правок * СП. Финал * Исправление ссылки на рисунок * Обновление схемы * Синхронизация правок * Добавление белого фона .drawio-изображениям * ЛР2. Исправление нумерации рисунка
This commit is contained in:
committed by
GitHub
parent
d251574bbc
commit
9739429d6e
@@ -7,7 +7,7 @@
|
||||
|
||||
Давайте разберемся что это за присваивания и почему необходимо руководствоваться этими правилами.
|
||||
|
||||
Начать придется издалека. Несмотря на то, что SystemVerilog является **языком описания аппаратуры**, он так же является и языком для верификации описанной аппаратуры (слово `Verilog` является объединением двух слов: `verification` и `logic` [2, стр. 24]). Для целей верификации в языке выделено целое подмножество конструкций, которые не могут быть использованы для описания аппаратуры — так называемое "_несинтезируемое подмножество языка SystemVerilog_". Разумеется, часть языка, которая может быть использована для описания аппаратуры ("_синтезируемое подмножество языка SystemVerilog_") тоже может использоваться в верификации.
|
||||
Начать придется издалека. Несмотря на то, что SystemVerilog является **языком описания аппаратуры**, он так же является и языком для верификации описанной аппаратуры (слово `Verilog` является объединением двух слов: `verification` и `logic` [[2](http://archive.computerhistory.org/resources/access/text/2013/11/102746653-05-01-acc.pdf), стр. 24]). Для целей верификации в языке выделено целое подмножество конструкций, которые не могут быть использованы для описания аппаратуры — так называемое "_несинтезируемое подмножество языка SystemVerilog_". Разумеется, часть языка, которая может быть использована для описания аппаратуры ("_синтезируемое подмножество языка SystemVerilog_") тоже может использоваться в верификации.
|
||||
|
||||
Давайте для начала разберемся в том, как будут использоваться операторы присваивания при программном моделировании (так называемой симуляции) — одним из инструментов верификации. Разобравшись в поведении операторов во время симуляции, будет куда проще объяснить результат использования операторов при синтезе цифровой схемы.
|
||||
|
||||
@@ -43,7 +43,7 @@ _Листинг 1. Пример непрерывного и процедурно
|
||||
|
||||
**Непрерывное присваивание может быть использовано только вне программных блоков.**
|
||||
|
||||
Под "программными блоками" подразумеваются блоки `always` (всех типов) и `initial`. Есть и другие программные блоки, но в рамках данного курса лабораторных работ вы с ними не столкнетесь. Вообще говоря, синтаксис языка SystemVerilog допускает использование оператора `assign` внутри программного блока (так называемое "**процедурное непрерывное присваивание**")[[2, стр. 232]](https://ieeexplore.ieee.org/document/8299595), однако в рамках данного курса не существует ни одной ситуации, когда это может потребоваться и со 100% вероятностью будет ошибочно.
|
||||
Под "программными блоками" подразумеваются блоки `always` (всех типов) и `initial`. Есть и другие программные блоки, но в рамках данного курса лабораторных работ вы с ними не столкнетесь. Вообще говоря, синтаксис языка SystemVerilog допускает использование оператора `assign` внутри программного блока (так называемое "**процедурное непрерывное присваивание**") [[2, стр. 256]](https://ieeexplore.ieee.org/document/10458102), однако в рамках данного курса не существует ни одной ситуации, когда это может потребоваться и со 100% вероятностью будет ошибочно.
|
||||
|
||||
В отличие от непрерывного присваивания, **процедурное присваивание может быть использовано только в программных блоках**.
|
||||
|
||||
@@ -89,7 +89,7 @@ _Рисунок 2. Пример цепочки неблокирующих при
|
||||
2. Затем вычисляется значение `RHS` второго присваивания. Поскольку `a` еще не присвоили значение `5`, результатом `RHS` становится текущее значение `a` — 3. Присваивание этого значения сигналу `b` **откладывается** на потом.
|
||||
3. Аналогичным образом вычисляется `RHS` третьего присваивания (`2`). Присваивание этого значения также **откладывается** на потом.
|
||||
|
||||
Так называемое "**потом**" наступает, когда завершается вычисление `RHS` всех неблокирующих присваиваний и завершение присвоений всех блокирующих присваиваний (однако "потом" все равно происходит в тот же момент времени, обратите внимание на значение времени на _рис. 2_). В стандарте SystemVerilog этот момент называется `NBA-region` (сокр. от "Non-Blocking Assignment region") [[2, стр. 61]](https://ieeexplore.ieee.org/document/10458102). Выполнение отложенных присваиваний происходит в том же порядке, в котором они шли в программном блоке. Подробнее о том как, работает событийная симуляция (event based simulation) в SystemVerilog, вы можете прочесть в стандарте [IEEE 1800-2023](https://ieeexplore.ieee.org/document/10458102) (раздел 4). Стандарт доступен бесплатно всем желающим по программе "IEEE GET Program".
|
||||
Так называемое "**потом**" наступает, когда завершается вычисление `RHS` всех неблокирующих присваиваний и завершение присвоений всех блокирующих присваиваний (однако "потом" все равно происходит в тот же момент времени, обратите внимание на значение времени на _рис. 2_). В стандарте SystemVerilog этот момент называется `NBA-region` (сокр. от "Non-Blocking Assignment region") [[2, стр. 64]](https://ieeexplore.ieee.org/document/10458102). Выполнение отложенных присваиваний происходит в том же порядке, в котором они шли в программном блоке. Подробнее о том как, работает событийная симуляция (event based simulation) в SystemVerilog, вы можете прочесть в стандарте [IEEE 1800-2023](https://ieeexplore.ieee.org/document/10458102) (раздел 4). Стандарт доступен бесплатно всем желающим по программе "IEEE GET Program".
|
||||
|
||||
Таким образом, если `LHS` **блокирующего** присваивания используется в качестве операнда `RHS` любого другого последующего присваивания, это выражение будет иметь уже обновленное значение, что очень похоже на "_последовательное вычисление_".
|
||||
|
||||
@@ -280,7 +280,7 @@ _Рисунок 9. Симуляция модуля, описанного Лис
|
||||
|
||||
Выглядит как-то не по "сдвигово-регистерски". В чем же дело?
|
||||
|
||||
Как уже упоминалось ранее, программные блоки (коими являются блоки `always`) исполняются во время моделирования независимо друг от друга в недетерминированном стандартом порядке. На практике это означает то, что сперва может исполниться второй блок, потом третий, а потом первый — либо в любом другом порядке. Разработчик не может (и не должен) рассчитывать на порядок блоков `always` при описании схемы.
|
||||
Как уже упоминалось ранее, программные блоки (коими являются блоки `always`) исполняются во время моделирования независимо друг от друга в недетерминированном стандартом порядке. На практике это означает, что сперва может исполниться второй блок, потом третий, а потом первый — либо в любом другом порядке. Разработчик не может (и не должен) рассчитывать на порядок блоков `always` при описании схемы.
|
||||
|
||||
Конкретно в данной ситуации, симулятор воспроизвел блоки ровно в том порядке, в котором они были описаны. Сперва `a` получил значение `in`, потом `b` получил обновленное значение `a`, затем `c` получил обновленное значение `b`.
|
||||
|
||||
@@ -337,7 +337,7 @@ _Рисунок 11. Схема, сгенерированная Vivado по оп
|
||||
|
||||
_Рисунок 12. Схема, сгенерированная Vivado по описанию из Листинга 6 после замены блокирующих присваиваний на неблокирующие._
|
||||
|
||||
Из прочтенного может сложиться впечатление, будто бы автор хочет показать, что блокирующее присваивание — это плохо, а неблокирующее — хорошо, однако это не так. Это просто два похожих инструмента, работающих разными способами, о которых должен знать профессионал, использующий эти инструменты.
|
||||
Из прочтённого может сложиться впечатление, будто бы авторы хотят показать, что блокирующее присваивание — это плохо, а неблокирующее — хорошо, однако это не так. Это просто два похожих инструмента, работающих разными способами, о которых должен знать профессионал, использующий эти инструменты.
|
||||
|
||||
Одно и тоже описание, использующее разные типы присваиваний может привести к синтезу разных схем.
|
||||
|
||||
@@ -417,7 +417,7 @@ _Рисунок 14. Моделирование цепочки присваива
|
||||
|
||||
> Получается что для комбинационной логики нет разницы между блокирующим и неблокирующим присваиванием, после переходных процессов результат будет одинаковым?
|
||||
|
||||
И да и нет. С точки зрения синтеза схемы так и есть. Однако есть нюанс в случае моделирования схемы. Поведение комбинационной логики лучше моделирует блокирующее присваивание[[1, стр. 14]](http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf).
|
||||
И да, и нет. С точки зрения синтеза схемы так и есть. Однако есть нюанс в случае моделирования схемы. Поведение комбинационной логики лучше моделирует блокирующее присваивание[[1, стр. 14]](http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf).
|
||||
|
||||
## Итоги главы
|
||||
|
||||
@@ -434,10 +434,10 @@ _Рисунок 14. Моделирование цепочки присваива
|
||||
Кроме того, существуют следующие рекомендации и требования[[1, стр. 5]](http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf):
|
||||
|
||||
- _При описании как последовательностной логики, так и комбинационной в одном блоке `always` используйте неблокирующее присваивание._
|
||||
- _Не смешивайте в одном блоке блокирующие и неблокирующие присваивания_ — стандарт допускает подобное описание, но оно затрудняет его чтение. Представьте, что читая описание схемы, вам бы постоянно приходилось держать в голове какие присваивания уже произошли, а какие только произойдут, чтобы понять как эта схема работает.
|
||||
- _Не смешивайте в одном блоке блокирующие и неблокирующие присваивания_ — стандарт допускает подобное описание, но оно затрудняет его чтение. Представьте, что, читая описание схемы, вам бы постоянно приходилось держать в голове, какие присваивания уже произошли, а какие только произойдут, чтобы понять как эта схема работает.
|
||||
- _Не смешивайте блокирующие и неблокирующие присваивания для одного и того же сигнала_ — стандарт это запрещает (для блоков `always_ff`, `always_comb`, `always_latch`).
|
||||
|
||||
## Список источников
|
||||
|
||||
1. [Clifford E. Cummings / Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill](http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf)
|
||||
2. [1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language](https://ieeexplore.ieee.org/document/8299595)
|
||||
2. [1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language](https://ieeexplore.ieee.org/document/10458102)
|
||||
|
@@ -80,14 +80,14 @@ _Литсинг 3. Пример присваивания значения сиг
|
||||
|
||||
Как вы можете увидеть, код был успешно собрался и был промоделирован, но значения в выделенных синим прямоугольниках не те, что должны были быть. Можно заметить также и то, что значение выхода `c` никогда не превышает единицу.
|
||||
|
||||
Если мы начнем разбираться, и решим вытащить на временную диаграмму внутренний сигнал модуля `ab`, мы увидим, что он почему-то однобитный. Более того, если раскомментировать строчку с объявлением сигнала `ab`, результат никак не изменится.
|
||||
Если мы начнем разбираться, и решим вытащить на временную диаграмму внутренний сигнал модуля `ab`, мы увидим, что он почему-то 1-битный. Более того, если раскомментировать строчку с объявлением сигнала `ab`, результат никак не изменится.
|
||||
|
||||
Подобное поведение в точности воспроизводит требование стандарта SystemVerilog [1, стр. 108]:
|
||||
|
||||
> - Если идентификатор использовался списке сигналов, подключаемых к модулю, и этот идентификатор не был объявлен в области видимости, которая доступна при этом подключении, то неявно подразумевается однобитный провод.
|
||||
> - Если идентификатор встречается по левую сторону от оператора непрерывного присваивания, и этот идентификатор не был объявлен в той области видимости, которая доступна оператору, то неявно подразумевается однобитный провод.
|
||||
> - Если идентификатор использовался списке сигналов, подключаемых к модулю, и этот идентификатор не был объявлен в области видимости, которая доступна при этом подключении, то неявно подразумевается 1-битный провод.
|
||||
> - Если идентификатор встречается по левую сторону от оператора непрерывного присваивания, и этот идентификатор не был объявлен в той области видимости, которая доступна оператору, то неявно подразумевается 1-битный провод.
|
||||
|
||||
Иными словами, если вы присваиваете значение необъявленному сигналу, или пытаетесь подключить необъявленный сигнал к модулю, неявно создается однобитный сигнал с тем же именем (попробуйте удалить объявление сигналов `a`, `b`, `c` в тестбенче _листинга 3_ и посмотрите, как изменится разрядность сигналов тестбенча на временной диаграмме).
|
||||
Иными словами, если вы присваиваете значение необъявленному сигналу, или пытаетесь подключить необъявленный сигнал к модулю, неявно создается 1-битный сигнал с тем же именем (попробуйте удалить объявление сигналов `a`, `b`, `c` в тестбенче _листинга 3_ и посмотрите, как изменится разрядность сигналов тестбенча на временной диаграмме).
|
||||
|
||||
Даже если объявите сигнал с правильной разрядностью после его использования — это уже ничему не поможет, поскольку повторные объявления уже объявленных проводов и регистров стандартом запрещены [1, стр. 91] и в зависимости от САПР будут либо проигнорированы, либо вызовут ошибку.
|
||||
|
||||
|
@@ -58,7 +58,7 @@ assign e = {a, b, c[4:3], d};
|
||||
|
||||
Кроме того, возможна и обратная ситуация. Предположим, мы хотим подать отдельные биты сигнала `e` на различные провода:
|
||||
|
||||

|
||||

|
||||
|
||||
```Verilog
|
||||
logic a;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
# Защелка
|
||||
|
||||
Очень важно при описании мультиплексора с помощью блока `case` описывать оставшиеся комбинации управляющего сигнала с помощью `default` (а при использовании блока `if` — описывать блок `else`) — в противном случае в вашей схеме может появиться [защелка](https://www.build-electronic-circuits.com/d-latch/) (даже несмотря на то, что для описания защелок в SytemVerilog есть отдельный блок `always`: `always_latch`).
|
||||
Очень важно при описании мультиплексора с помощью блока `case` описывать оставшиеся комбинации управляющего сигнала с помощью `default` (а при использовании блока `if` — описывать блок `else`) — в противном случае в вашей схеме может появиться [защелка](https://www.build-electronic-circuits.com/d-latch/) — даже несмотря на то, что для описания защелок в SytemVerilog есть отдельный блок `always`: `always_latch`.
|
||||
|
||||
Защелка представляет из себя элемент памяти, причем данные в нее записываются не по тактовому синхроимпульсу, а на протяжении относительно длинного промежутка времени, когда управляющий сигнал "открывает" защелку (в этом случае говорят, что защелка становится "прозрачной"). Из-за этого она не является ни комбинационной, ни синхронной схемой.
|
||||
|
||||
Защелка — это всего лишь элемент цифровой схемы и будет неправильно говорить о нем в терминах "плохой" или "хороший". Защелка имеет свои плюсы для [ASIC](https://ru.wikipedia.org/wiki/Интегральная_схема_специального_назначения)-проектирования. Однако защелка совершенно не подходит при проектировании устройств под ПЛИС.
|
||||
Защелка — это всего лишь элемент цифровой схемы и будет неправильно говорить о нём в терминах "плохой" или "хороший". Защелка имеет свои плюсы для [ASIC](https://ru.wikipedia.org/wiki/Интегральная_схема_специального_назначения)-проектирования. Однако защелка совершенно не подходит при проектировании устройств под ПЛИС.
|
||||
|
||||
Обычно появление защелки в цифровой схеме говорит об ошибке разработки: в случае, если планировалась комбинационная логика, добавление защелки приведет к непредвиденному удержанию предыдущих значений (поскольку защелка сохраняет предыдущее значение до прихода очередной комбинации управляющего сигнала, описанной в блоке `case`). Это особенно плохо, если сигнал, перед которым появилась защелка, чем-то управляет. Представьте, что он управляет сейфом, который должен открываться если ввели правильный пароль:
|
||||
|
||||
@@ -75,6 +75,6 @@ _Рисунок 1. Пример генерации защелки у непол
|
||||
|
||||
_Рисунок 2. Пример удержания предыдущих значений защелкой._
|
||||
|
||||
Кроме того, защелка усложняет временной анализ и ухудшает временные характеристики, из-за чего схема может работать на меньших частотах, чем могла бы.
|
||||
Кроме того, защелка усложняет временной анализ и может ухудшить временные характеристики, из-за чего схема может работать на меньших частотах, чем могла бы.
|
||||
|
||||
Таким образом, во избежание появления защелки, необходимо описывать все возможные комбинации в блоке `case` (при необходимости покрывая множество оставшихся комбинаций с помощью `default`) и для каждого блока `if` описывать блоки `else`. В случае, если подобная комбинация не планируется к использованию, можно присвоить сигналу значение ноль. Конечно, в этом случае будет создана избыточная логика для присваивания ненужного значения, которое никогда не должно произойти (и существуют способы описания аппаратуры, позволяющие этого избежать), но в данном случае это самый простой способ.
|
||||
|
@@ -64,7 +64,7 @@ endmodule
|
||||
|
||||
Для объявления провода `c` использовалось ключевое слово (тип) `logic`. Этот тип может в конечном итоге привести к созданию как ячеек памяти (регистров), так и проводов, в зависимости от того, как было описано присваивание объекту этого типа (подобно тому как стволовые клетки организма могут дифференцироваться в специализированные клетки в зависимости от ситуации). Поэтому в примере выше говорить о том, что был создан провод не совсем корректно, объект схемы `c` станет проводом, когда будет произведено подключение к этому объекту, соответствующее подключению провода.
|
||||
|
||||
Подключим провод `c` ко входу `a`. Для этого используется конструкция `assign c = a;`. Такая конструкция называется **непрерывным присваиванием**. Если очень сильно упростить, то непрерывное присваивание схоже со спайкой двух проводов. После подобного присваивания, провод `c` всегда будет иметь то же значение, что и `a` — как только входной сигнал `a` изменит свое значение, внутренний провод `c` также изменит свое значение (проводу `c` будет **непрерывно присваиваться** значение входа `a`).
|
||||
Подключим провод `c` ко входу `a`. Для этого используется конструкция `assign c = a;`. Такая конструкция называется **непрерывным присваиванием**. Если очень сильно упростить, то непрерывное присваивание схоже со спайкой двух проводов. После подобного присваивания, провод `c` всегда будет иметь то же значение, что и `a` — как только входной сигнал `a` изменит своё значение, внутренний провод `c` также изменит своё значение (проводу `c` будет **непрерывно присваиваться** значение входа `a`).
|
||||
|
||||

|
||||
|
||||
@@ -110,7 +110,7 @@ module box(
|
||||
endmodule
|
||||
```
|
||||
|
||||
Пусть в схеме имеется ещё один логический вентиль - Исключающее ИЛИ. На него подаётся результат операции `a ИЛИ b`, то есть `c`, а также входной сигнал `b`. Результат операции `c ИСКЛЮЧАЮЩЕЕ ИЛИ b` подаётся на выход `q` нашего модуля.
|
||||
Пусть в схеме имеется ещё один логический вентиль - Исключающее ИЛИ. На него подаётся результат операции `a ИЛИ b`, то есть `c`, а также входной сигнал `b`. Результат операции `c Исключающее ИЛИ b` подаётся на выход `q` нашего модуля.
|
||||
|
||||

|
||||
|
||||
@@ -227,7 +227,7 @@ endmodule
|
||||
|
||||
Обратите внимание на то, как подключаются сигналы к вложенному модулю: при подключении после `.` пишется имя сигнала подключаемого модуля, затем в скобках пишется имя сигнала подключающего модуля. Для лучшего понимания, посмотрите внимательно на схеме на провод `c` и выход `d` модуля `inv`, а также на SystemVerilog-описание этой схемы.
|
||||
|
||||
Мы можем подключить сколько угодно экземпляров одного модуля, поэтому у каждого из экземпляра должно быть свое уникальное имя. Пусть `c` подаётся на логический вентиль И вместе со входом `b`. Результат операции И тоже пойдет на инвертор, а затем на выход `q` модуля top.
|
||||
Мы можем подключить сколько угодно экземпляров одного модуля, поэтому у каждого из экземпляра должно быть своё уникальное имя. Пусть `c` подаётся на логический вентиль И вместе со входом `b`. Результат операции И тоже пойдет на инвертор, а затем на выход `q` модуля top.
|
||||
|
||||

|
||||
|
||||
@@ -287,6 +287,6 @@ ___
|
||||
|
||||
Как, по-вашему, описать нижеприведенную схему на языке описания аппаратуры SystemVerilog?
|
||||
|
||||
Обратите внимание, что вход `a` модуля `top` является двухразрядным: нулевой его бит идет на вход `a` модуля `or`, первый бит идет на вход `b` модуля `or`.
|
||||
Обратите внимание, что вход `a` модуля `top` является двухразрядным: нулевой его бит идёт на вход `a` модуля `or`, первый бит идёт на вход `b` модуля `or`.
|
||||
|
||||

|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
- унарный (с одним операндом), пример: `-a`;
|
||||
- бинарный (с двумя операндами), пример: `a+b`;
|
||||
- тернарный (с тремя операндами), пример: `cond ? if_true : false`;
|
||||
- тернарный (с тремя операндами), пример: `cond ? if_true : if_false`;
|
||||
- и др.
|
||||
|
||||
Несмотря на то, что тернарным оператором может быть любой оператор, принимающий три операнда, обычно под ним подразумевается **тернарный условный оператор**, работающий следующим образом:
|
||||
@@ -129,7 +129,7 @@ end
|
||||
|
||||
Мультиплексор также можно описать с использованием **конструкции case**. Блок `case` лучше подходит для описания мультиплексора, когда у того более двух входов (ведь в случае конструкции `if-else` пришлось бы делать вложенное ветвление).
|
||||
|
||||
Конструкция `case` представляет собой инструмент множественного ветвления, который сравнивает значение заданного выражения с множеством вариантов, и, в случае первого совпадения, использует соответствующую ветвь. На случай, если ни один из вариантов не совпадет с заданным выражением, конструкция `case` поддерживает вариант `default`. Данная конструкция визуально похожа на оператор `switch-case` в Си, однако вы должны понимать, что используется она не для написания программы, а описания аппаратуры, в частности **мультиплексоров**/**демультиплексоров** и **дешифраторов**.
|
||||
Конструкция `case` представляет собой инструмент множественного ветвления, который сравнивает значение заданного выражения с множеством вариантов, и, в случае первого совпадения, использует соответствующую ветвь. Как и блок `if-else`, блок `case` должен описывать все возможные комбинации управляющего сигнала.На случай, если ни один из вариантов не совпадет с заданным выражением, конструкция `case` поддерживает вариант `default`. Данная конструкция визуально похожа на оператор `switch-case` в Си, однако вы должны понимать, что используется она не для написания программы, а описания аппаратуры, в частности **мультиплексоров**/**демультиплексоров** и **дешифраторов**.
|
||||
|
||||
**Конструкция `case`, наряду с `if-else`, может быть описана только в блоке `always`**.
|
||||
|
||||
@@ -150,7 +150,7 @@ end // (так же как каждый begin должен ок
|
||||
|
||||

|
||||
|
||||
Здесь уже используется мультиплексор 8в1. Управляющий сигнал `S` в данном случае трёхбитный. В блоке `case` мы перечисляем всевозможные варианты значений `S` и описываем выход мультиплексора.
|
||||
Здесь уже используется мультиплексор 8в1. Управляющий сигнал `S` в данном случае 3-битный. В блоке `case` мы перечисляем все возможные варианты значений `S` и описываем выход мультиплексора.
|
||||
|
||||
```Verilog
|
||||
module case_mux_ex(
|
||||
@@ -211,7 +211,7 @@ assign one_bit_result = bus1024[select];
|
||||
2. использование конструкции [`if-else`](#блок-if-else) внутри блока [`always`](#блок-always);
|
||||
3. использование конструкции [`case`](#case-блок) внутри блока [`always`](#блок-always);
|
||||
4. использование [оператора '[]'](#оператор-адресации).
|
||||
3. Во избежание появления [защелок](Latches.md) при описании мультиплексора, необходимо убедиться что у блоков `if` есть соответствующие им блоки `else`, а у мультиплексоров описаны все комбинации управляющего сигнала (при необходимости, множество оставшихся комбинаций можно покрыть с помощью комбинации `default`). Появление непреднамеренной защелки в дизайне ведет к ухудшению временных характеристик, избыточному использованию ресурсов, а также непредсказуемому поведению схемы из-за возможного удержания сигнала.
|
||||
3. Во избежание появления [защелок](Latches.md) при описании мультиплексора, необходимо убедиться что у блоков `if` есть соответствующие им блоки `else`, а в блоке `case` описаны все комбинации управляющего сигнала (при необходимости, множество оставшихся комбинаций можно покрыть с помощью комбинации `default`). Появление непреднамеренной защелки в дизайне ведет к ухудшению временных характеристик, избыточному использованию ресурсов, а также непредсказуемому поведению схемы из-за возможного удержания сигнала.
|
||||
4. Важно отметить, что блоки `if-else` и `case` могут использоваться не только для описания мультиплексоров.
|
||||
5. Конструкции `if-else` и `case` в рамках данных лабораторных работ можно описывать только внутри блока [`always`](#блок-always). При работе с этим блоком необходимо помнить следующие особенности:
|
||||
1. Существует несколько типов блока `always`: `always_comb`, `always_ff`, `always_latch`, определяющих то, к чему будет подключена описанная в этом блоке логика: проводу, регистру или защелке соответственно. В данных лабораторных работах вам нужно будет пользоваться блоками `always_ff` и `always_comb`, причем:
|
||||
@@ -226,3 +226,7 @@ assign one_bit_result = bus1024[select];
|
||||
Как описать на языке SystemVerilog следующую схему?
|
||||
|
||||

|
||||
|
||||
## Список источников
|
||||
|
||||
1. [Мультиплексор (электроника)](https://ru.wikipedia.org/wiki/Мультиплексор_(электроника)).
|
@@ -1,6 +1,6 @@
|
||||
# Описание регистров в SystemVerilog
|
||||
|
||||
Перед тем, как описывать память, необходимо научиться описывать отдельные регистры. [Регистр](https://ru.wikipedia.org/wiki/Регистр_(цифровая_техника)) — это базовая ячейка памяти, позволяющая хранить состояние, пока на схему подается питание. В современной электронике, регистр чаще всего строится на D-триггерах. В лабораторной работе по АЛУ уже вскользь упоминалось, что как для описания проводов, так и для описания регистров, используется тип `logic`.
|
||||
Перед тем, как описывать память, необходимо научиться описывать отдельные регистры. **Регистр** — устройство для записи, хранения и считывания n-разрядных двоичных данных и выполнения других операций над ними [1, стр. 32]. В современной электронике, регистр чаще всего строится на D-триггерах. В лабораторной работе по АЛУ уже вскользь упоминалось, что как для описания проводов, так и для описания регистров, используется тип `logic`.
|
||||
|
||||
```Verilog
|
||||
logic reg_name;
|
||||
@@ -47,18 +47,19 @@ endmodule
|
||||
Описание регистра, а также указание фронта и тактирующего сигнала происходит в конструкции `always_ff`:
|
||||
|
||||
```Verilog
|
||||
always @(posedge clk)
|
||||
always_ff @(posedge clk)
|
||||
```
|
||||
|
||||
Далее, внутри данной конструкции необходимо указать, что происходит с содержимым регистра. В нашем случае, происходит запись с входного сигнала `data`
|
||||
|
||||
```Verilog
|
||||
always @(posedge clk) begin
|
||||
always_ff @(posedge clk) begin
|
||||
reg_name <= data;
|
||||
end
|
||||
```
|
||||
|
||||
Обратите внимание на оператор `<=`. В данном случае, это не знак "меньше либо равно", а оператор **неблокирующего присваивания**. Существует оператор **блокирующего присваивания** (`=`), который меняет способ построения схемы для такого же выражения справа от оператора, однако в данный момент этот оператор останется за рамками курса. Хоть это и плохая практика в обучении, но пока вам надо просто запомнить, что **при описании записи в регистр всегда используйте оператор неблокирующего присваивания `<=`**.
|
||||
> [!IMPORTANT]
|
||||
> Обратите внимание на оператор `<=`. В данном случае, это не знак "меньше либо равно", а оператор **неблокирующего присваивания**. Существует оператор **блокирующего присваивания** (`=`), который может поменять способ построения схемы для такого же выражения справа от оператора. Хоть это и плохая практика в обучении, но пока вам надо просто запомнить: **при описании записи в регистр всегда используйте оператор неблокирующего присваивания `<=`**. Подробнее о рассказано в документе "[О различиях между блокирующими и неблокирующими присваиваниями](./Assignments.md)".
|
||||
|
||||
Помимо прочего, нам необходимо связать выход схемы с выходом регистра. Это можно сделать уже известным вам оператором **непрерывного присваивания** `assign`.
|
||||
|
||||
@@ -73,7 +74,7 @@ module reg_example(
|
||||
|
||||
logic reg_name;
|
||||
|
||||
always @(posedge clk) begin
|
||||
always_ff @(posedge clk) begin
|
||||
reg_name <= data;
|
||||
end
|
||||
|
||||
@@ -110,7 +111,7 @@ endmodule
|
||||
```
|
||||
|
||||
Обратите внимание на очередность условий. В первую очередь, мы проверяем условие **сброса**, и только после этого условие **разрешения на запись**.
|
||||
Если сперва проверить разрешение на запись, а затем в блоке `else` описать логику сброса, то регистр не будет сбрасываться в случае, если `enable` будет равен `1` (запись в регистр будет приоритетней его сброса). Если сброс описать не в блоке `else`, а в отдельном блоке `if`, то может возникнуть неопределенное состояние: нельзя однозначно сказать в какой момент придет сигнал `reset` относительно сигнала `enable` и что в итоге запишется в регистр. Поэтому при наличии сигнала сброса, остальная логика по записи в регистр должна размещаться в блоке `else`.
|
||||
Если сперва проверить разрешение на запись, а затем в блоке `else` описать логику сброса, то регистр не будет сбрасываться в случае, если `enable` будет равен `1` (запись в регистр будет приоритетней его сброса). Если сброс описать не в блоке `else`, а в отдельном блоке `if`, то может возникнуть неопределенное поведение: нельзя однозначно сказать, что запишется в регистр, если одновременно придут сигналы `reset` и `enable`. Поэтому при наличии сигнала сброса, остальная логика по записи в регистр должна размещаться в блоке `else`.
|
||||
|
||||
Кроме того, САПР-ы смотрят на паттерн описания элемента схемы, и когда распознают его, реализуют элемент так как задумывал разработчик. Поэтому при описании регистра всегда сперва описывается сигнал сброса (если он используется) и только затем в блоке `else` описывается вся остальная часть логики записи.
|
||||
|
||||
@@ -194,7 +195,7 @@ endmodule
|
||||
|
||||
Более того, с точки зрения синтезатора данное описание проще для синтеза, т.к. ему не разделять из одного `always` блока комбинационную и синхронные части.
|
||||
|
||||
Вообще говоря, регистр в общем смысле этого слова представляет собой многоразрядную конструкцию (в рассмотренном ранее примере, однобитный регистр мог представлять из себя простой D-триггер).
|
||||
Вообще говоря, регистр в общем смысле этого слова представляет собой многоразрядную конструкцию (в рассмотренном ранее примере, 1-битный регистр мог представлять из себя простой D-триггер).
|
||||
Создание многоразрядного регистра мало отличается от создания многоразрядного провода, а описание логики записи в многоразрядный регистр ничем не отличается от логики записи в одноразрядный регистр:
|
||||
|
||||
```Verilog
|
||||
@@ -229,3 +230,7 @@ endmodule
|
||||
Как, по-вашему, описать на языке SystemVerilog схему, приведённую ниже?
|
||||
|
||||

|
||||
|
||||
## Список источников
|
||||
|
||||
1. Ш. Габриелян, Е. Вахтина / Электротехника и электроника. Методические рекомендации. — Ставрополь: Аргус, 2013
|
||||
|
Reference in New Issue
Block a user