mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
WIP: APS cumulative update (#98)
* WIP: APS cumulative update * Update How FPGA works.md * Перенос раздела "Последовательностная логика" в отдельный док * Исправление картинки * Исправление оформления индексов * Переработка раздела Vivado Basics * Добавление картинки в руководство по созданию проекта * Исправление ссылок в анализе rtl * Обновление изображения в sequential logic * Исправление ссылок в bug hunting * Исправление ссылок * Рефактор руководства по прошивке ПЛИС * Mass update * Update fig_10 * Restore fig_02
This commit is contained in:
committed by
GitHub
parent
78bb01ef95
commit
a28002e681
@@ -7,21 +7,21 @@
|
||||
|
||||
Давайте разберемся что это за присваивания и почему необходимо руководствоваться этими правилами.
|
||||
|
||||
Начать придется издалека. Несмотря на то, что SystemVerilog является **языком описания аппаратуры**, он так же является и языком для верификации описанной аппаратуры (слово `Verilog` является объединением двух слов: `verification` и `logic`). Для целей верификации в языке выделено целое подмножество конструкций, которые не могут быть использованы для описания аппаратуры — так называемое "_несинтезируемое подмножество языка SystemVerilog_". Разумеется, часть языка, которая может быть использована для описания аппаратуры ("_синтезируемое подмножество языка SystemVerilog_") тоже может использоваться в верификации.
|
||||
Начать придется издалека. Несмотря на то, что SystemVerilog является **языком описания аппаратуры**, он так же является и языком для верификации описанной аппаратуры (слово `Verilog` является объединением двух слов: `verification` и `logic` [2, стр. 24]). Для целей верификации в языке выделено целое подмножество конструкций, которые не могут быть использованы для описания аппаратуры — так называемое "_несинтезируемое подмножество языка SystemVerilog_". Разумеется, часть языка, которая может быть использована для описания аппаратуры ("_синтезируемое подмножество языка SystemVerilog_") тоже может использоваться в верификации.
|
||||
|
||||
Давайте для начала разберемся в том, как будут использоваться операторы присваивания при программном моделировании (так называемой симуляции) — одним из инструментов верификации. Разобравшись в поведении операторов во время симуляции будет куда проще объяснить результат использования операторов при синтезе цифровой схемы.
|
||||
Давайте для начала разберемся в том, как будут использоваться операторы присваивания при программном моделировании (так называемой симуляции) — одним из инструментов верификации. Разобравшись в поведении операторов во время симуляции, будет куда проще объяснить результат использования операторов при синтезе цифровой схемы.
|
||||
|
||||
Введем пару сокращений для удобства дальнейшего повествования:
|
||||
|
||||
- под `LHS` (left hand side) мы будем подразумевать "выражение, **которому** присваивают";
|
||||
- под `RHS` (right hand side) мы будем подразумевать "выражение **которое** присваивают".
|
||||
- под `RHS` (right hand side) мы будем подразумевать "выражение, **которое** присваивают".
|
||||
|
||||
В выражении `a = b+c`, `a` является `LHS`, `b+c` является `RHS`.
|
||||
|
||||
два вида присваиваний: **непрерывное** и **процедурное**.
|
||||
Существует два вида присваиваний: **непрерывное** и **процедурное**.
|
||||
|
||||
```SystemVerilog
|
||||
module assignment_example(
|
||||
```Verilog
|
||||
module example_1(
|
||||
input logic a, b
|
||||
output logic c, d
|
||||
);
|
||||
@@ -49,7 +49,7 @@ _Листинг 1. Пример непрерывного и процедурно
|
||||
|
||||
С точки зрения моделирования (не описания аппаратуры), программный блок — это программа (в привычном вам понимании парадигмы программирования), исполняющаяся в отдельном процессе. Программные блоки исполняются независимо друг от друга по определенным событиям.
|
||||
|
||||
Блоки `initial` (их может быть много) исполняются в момент начала моделирования. Блоки `always` исполняются по событиям указанным в **списке чувствительности**:
|
||||
Блоки `initial` (их может быть много) исполняются в момент начала моделирования. Блоки `always` исполняются по событиям, указанным в **списке чувствительности**:
|
||||
|
||||
- `always @(posedge clk)` будет исполняться каждый раз когда произойдет положительный фронт `clk`;
|
||||
- `always @(a,b,c)` будет исполняться каждый раз, когда изменится значение любого из сигналов `a`,`b`,`c`;
|
||||
@@ -89,11 +89,11 @@ _Рисунок 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/8299595). Выполнение отложенных присваиваний происходит в том же порядке, в котором они шли в программном блоке. Подробнее о том как работает событийная симуляция (event based simulation) в SystemVerilog вы можете прочесть в стандарте [IEEE 1800-2017](https://ieeexplore.ieee.org/document/8299595) (раздел 4). Стандарт доступен бесплатно всем желающим по программе "IEEE GET Program".
|
||||
Так называемое "**потом**" наступает, когда завершается вычисление `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".
|
||||
|
||||
Таким образом, если `LHS` **блокирующего** присваивания используется в качестве операнда `RHS` любого другого последующего присваивания, это выражение будет иметь уже обновленное значение, что очень похоже на "_последовательное вычисление_".
|
||||
|
||||
С другой стороны значение, присвоенное `LHS` значение с помощью **неблокирующего** присваивания не может использоваться в качестве операнда `RHS` последующих присваиваний, что создает иллюзию "_параллельного вычисления_" (см. _рис. 3_).
|
||||
С другой стороны значение, присвоенное `LHS` значение с помощью **неблокирующего** присваивания, не может использоваться в качестве операнда `RHS` последующих присваиваний, что создает иллюзию "_параллельного вычисления_" (см. _рис. 3_).
|
||||
|
||||

|
||||
|
||||
@@ -101,20 +101,20 @@ _Рисунок 3. Иллюстрация блокирующих и неблок
|
||||
|
||||
Теперь, понимая как работают присваивания с точки зрения моделирования, посмотрим на то, во что могут синтезироваться подобные операторы.
|
||||
|
||||
Начнем с непрерывного присваивания. Оно превращается в провод, передающий данные от `RHS` к `LHS`. При этом вы должны контролировать что к чему вы присваиваете (не путайте местами `RHS` и `LHS`).
|
||||
Начнем с непрерывного присваивания. Оно превращается в провод, передающий данные от `RHS` к `LHS`. При этом вы должны следить за тем, **что** и **чему** вы присваиваете (не путайте местами `RHS` и `LHS`).
|
||||
|
||||
То во что синтезируются блокирующие и неблокирующие присваивания зависит от описываемой логики, поэтому давайте разберем несколько примеров.
|
||||
То, во что синтезируются блокирующие и неблокирующие присваивания зависит от описываемой логики, поэтому давайте разберём несколько примеров.
|
||||
|
||||
Начнем с исходного примера c цепочкой блокирующих присваиваний, только теперь перепишем его в синтезируемом виде, сохранив изначальную идею.
|
||||
|
||||
```SystemVerilog
|
||||
module example_1(
|
||||
```Verilog
|
||||
module example_2(
|
||||
input logic clk,
|
||||
input logic [31:0] in,
|
||||
output logic [31:0] out
|
||||
);
|
||||
|
||||
logic [31:0] a,b,c;
|
||||
logic [31:0] a, b, c;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
a = in;
|
||||
@@ -133,7 +133,7 @@ _Листинг 2. Пример описания модуля, использу
|
||||
|
||||
---
|
||||
|
||||
Давайте "прочитаем" эту схему. Мы видим модуль, с входом `in`, выходом `out` и тактирующим синхроимпульсом `clk`. Также мы видим три сигнала `a`,`b`,`c`, которые описываются в блоке `always_ff`, предназначенном для описания регистров. Значение `in` по цепочке этих регистров передается до регистра `c`, выход которого подключен к выходу `out`.
|
||||
Давайте "прочитаем" эту схему. Мы видим модуль, с входом `in`, выходом `out` и тактирующим синхроимпульсом `clk`. Также мы видим три сигнала `a`, `b`, `c`, которые описываются в блоке `always_ff`, предназначенном для описания регистров. Значение `in` по цепочке этих регистров передается до регистра `c`, выход которого подключен к выходу `out`.
|
||||
|
||||
Похоже, что здесь был описан [**сдвиговый регистр**](https://ru.wikipedia.org/wiki/Регистр_(цифровая_техника)#Сдвигающие_(последовательные)_регистры), представленный на _рис. 4_.
|
||||
|
||||
@@ -151,7 +151,7 @@ _Рисунок 5. Схема, сгенерированная Vivado по опи
|
||||
|
||||
Изучим внимательней поведение цепочки блокирующих присваиваний, представленное на _рис. 1_.
|
||||
|
||||
Каждое последующее присваивание ожидало, пока не выполнится предыдущее, таким образом, `RHS` первого присваивания (`5`) сразу же распространился по всем регистрам. Моделируя _Листинг 2_ мы получим **поведение**, когда на вход каждого регистра будет подаваться сигнал `in`.
|
||||
Каждое последующее присваивание ожидало, пока не выполнится предыдущее, таким образом, `RHS` первого присваивания (`5`) сразу же распространился по всем регистрам. Моделируя _Листинг 2_, мы получим **поведение**, когда на вход каждого регистра будет подаваться сигнал `in`.
|
||||
|
||||
Таким образом на самом деле, мы должны были изобразить нашу схему как на _рис. 6_.
|
||||
|
||||
@@ -159,7 +159,7 @@ _Рисунок 5. Схема, сгенерированная Vivado по опи
|
||||
|
||||
_Рисунок 6. Схема, описанная Листингом 2._
|
||||
|
||||
Но почему тогда на схеме Vivado не осталось регистров `a` и `b`? Посмотрим на них внимательней. Их выходы ни на что не влияют, они висят неподключенные. А значит эти регистры не имеют никакого смысла и если их убрать, ничего не изменится.
|
||||
Но почему тогда на схеме Vivado не осталось регистров `a` и `b`? Посмотрим на них внимательней. Их выходы ни на что не влияют, они ни к чему не подключены. А значит эти регистры не имеют никакого смысла и, если их убрать, ничего не изменится.
|
||||
|
||||
При генерации схемы, Vivado вывел в `Tcl Console` следующие предупреждения:
|
||||
|
||||
@@ -178,8 +178,8 @@ _Рисунок 7. Пример вызова линтера._
|
||||
|
||||
Давайте заменим в _Листинге 2_ блокирующие присваивания на неблокирующие. Напоминаем, что оператор неблокирующего присваивания записывается как `<=`.
|
||||
|
||||
```SystemVerilog
|
||||
module example_2(
|
||||
```Verilog
|
||||
module example_3(
|
||||
input logic clk,
|
||||
input logic [31:0] in,
|
||||
output logic [31:0] out
|
||||
@@ -214,8 +214,8 @@ _Рисунок 8. Схема, сгенерированная Vivado по опи
|
||||
|
||||
Можно ли реализовать сдвиговый регистр, используя блокирующие присваивания? Конечно. Например, можно поменять порядок присваиваний как в _Листинге 4_.
|
||||
|
||||
```SystemVerilog
|
||||
module example_3(
|
||||
```Verilog
|
||||
module example_4(
|
||||
input logic clk,
|
||||
input logic [31:0] in,
|
||||
output logic [31:0] out
|
||||
@@ -244,8 +244,8 @@ _Листинг 4. Цепочка блокирующих присваивани
|
||||
|
||||
Давайте разнесем логику работы каждого регистра по отдельным блокам `always`.
|
||||
|
||||
```SystemVerilog
|
||||
module example_4(
|
||||
```Verilog
|
||||
module example_5(
|
||||
input logic clk,
|
||||
input logic [31:0] in,
|
||||
output logic [31:0] out
|
||||
@@ -292,14 +292,14 @@ _Рисунок 9. Симуляция модуля, описанного Лис
|
||||
|
||||
_Рисунок 10. Моделирование поведения сдвигового регистра._
|
||||
|
||||
Однако, как уже объяснялось ранее, вы не можете рассчитывать на такой результат. Сегодня симулятор смоделировал поведение одним образом — завтра он смоделирует этот же код (в котором не изменилась ни одна строка) по-другому, и будет по прежнему работать в соответствии со стандартом.
|
||||
Однако, как уже объяснялось ранее, вы не можете рассчитывать на такой результат. Сегодня симулятор смоделировал поведение одним образом — завтра он смоделирует этот же код (в котором не изменилась ни одна строка) по-другому, и будет по-прежнему работать в соответствии со стандартом.
|
||||
|
||||
Для того, чтобы получить детерминированный результат, вам необходимо снова воспользоваться неблокирующим присваиванием, поскольку и в этом случае порядок исполнения блоков `always` не влияет на результат присваиваний — сначала вычисляются значения `RHS` всех неблокирующих присваиваний всех программных блоков, и только потом происходит присваивание этих значений `LHS`.
|
||||
|
||||
Рассмотрим еще один пример того, как различие в присваиваниях приведет к описанию двух различных схем:
|
||||
|
||||
```SystemVerilog
|
||||
module example_5(
|
||||
```Verilog
|
||||
module example_6(
|
||||
input logic clk,
|
||||
input logic a, b, c,
|
||||
output logic d
|
||||
@@ -349,8 +349,8 @@ _Рисунок 12. Схема, сгенерированная Vivado по оп
|
||||
|
||||
Рассмотрим зависимость от типа присваивания в комбинационных схемах. Для этого возьмем предыдущий пример, и уберем тактирующий синхроимпульс.
|
||||
|
||||
```SystemVerilog
|
||||
module example_6(
|
||||
```Verilog
|
||||
module example_7(
|
||||
input logic a, b, c,
|
||||
output logic d
|
||||
);
|
||||
@@ -413,12 +413,14 @@ _Рисунок 14. Моделирование цепочки присваива
|
||||
|
||||
Обратите внимание, поведение схем описанных при разных типах присваивания слегка различаются. При блокирующем присваивании все сигналы приняли установившиеся значения за один проход блока `always`, при неблокирующем потребовалось несколько проходов. Однако с точки зрения пользователя, читающего временную диаграмму, в обоих ситуациях сигналы изменили свое значение мгновенно.
|
||||
|
||||
Поэтому не смотря на различия в типах присваиваний схемы получились одинаковыми.
|
||||
Поэтому несмотря на различия в типах присваиваний схемы получились одинаковыми.
|
||||
|
||||
> Получается что для комбинационной логики нет разницы между блокирующим и неблокирующим присваиванием, после переходных процессов результат будет одинаковым?
|
||||
|
||||
И да и нет. С точки зрения синтеза схемы так и есть. Однако есть нюанс в случае моделирования схемы. Поведение комбинационной логики лучше моделирует блокирующее присваивание[[1, стр. 14]](http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf).
|
||||
|
||||
## Итоги главы
|
||||
|
||||
Подведем итоги прочитанному:
|
||||
|
||||
- Блокирующее присваивание блокирует выполнение остальных операций до завершения текущего присваивания. Оно подобно обычному присваиванию в парадигме программирования.
|
||||
@@ -435,7 +437,7 @@ _Рисунок 14. Моделирование цепочки присваива
|
||||
- _Не смешивайте в одном блоке блокирующие и неблокирующие присваивания_ — стандарт допускает подобное описание, но оно затрудняет его чтение. Представьте, что читая описание схемы, вам бы постоянно приходилось держать в голове какие присваивания уже произошли, а какие только произойдут, чтобы понять как эта схема работает.
|
||||
- _Не смешивайте блокирующие и неблокирующие присваивания для одного и того же сигнала_ — стандарт это запрещает (для блоков `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)
|
||||
|
Reference in New Issue
Block a user