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
@@ -1,4 +1,4 @@
|
||||
# Лабораторная работа 1 "Сумматор"
|
||||
# Лабораторная работа №1 "Сумматор"
|
||||
|
||||
## Цель
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
Итогом лабораторной работы будет создание устройства, способного складывать два числа. Но перед тем, как учиться создавать подобное устройство, необходимо немного освоиться в самом процессе складывания чисел.
|
||||
|
||||
Давайте начнем с примера и сложим в столбик произвольную пару чисел, например 42 и 79:
|
||||
Давайте начнём с примера и сложим в столбик произвольную пару чисел, например 42 и 79:
|
||||
|
||||

|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
|
||||
_Таблица истинности одноразрядного сложения._
|
||||
|
||||
`S` — это младший разряд суммы, записываемый в столбце сложения под слагаемыми `a` и `b`. `C` (_carry_, перенос) — это старший разряд суммы, записываемый левее, если произошел перенос разряда. Как мы видим, перенос разряда происходит только в случае, когда оба числа одновременно равны единице. При этом значение `S` обращается в `0`, и результат записывается как `10`, что в двоичной системе означает `2`. Кроме того, значение `S` равно `0` и в случае, когда оба операнда одновременно равны нулю. Вы можете заметить, что `S` равно нулю в тех случаях, когда `а` и `b` равны, и не равно нулю в противоположном случае. Подобным свойством обладает логическая операция **Исключающее ИЛИ** (**eXclusive OR**, **XOR**):
|
||||
`S` — это младший разряд 2-битного результата суммы, записываемый в столбце сложения под слагаемыми `a` и `b`. `C` (_carry_, перенос) — это старший разряд суммы, записываемый левее, если произошёл перенос разряда. Как мы видим, перенос разряда происходит только в случае, когда оба числа одновременно равны единице. При этом значение `S` обращается в `0`, и результат записывается как `10`, что в двоичной системе означает `2`. Кроме того, значение `S` равно `0` и в случае, когда оба операнда одновременно равны нулю. Вы можете заметить, что `S` равно нулю в тех случаях, когда `а` и `b` равны, и не равно нулю в противоположном случае. Подобным свойством обладает логическая операция **Исключающее ИЛИ** (**eXclusive OR**, **XOR**):
|
||||
|
||||

|
||||
|
||||
_Таблица истинности операции Исключающее ИЛИ (XOR)._
|
||||
|
||||
Для бита переноса всё ещё проще — он описывается операцией логическое И:
|
||||
Для бита переноса всё ещё проще — он описывается операцией **логическое И**:
|
||||
|
||||

|
||||
|
||||
@@ -81,7 +81,7 @@ _Таблица истинности операции И._
|
||||
|
||||
_Рисунок 1. Цифровая схема устройства, складывающего два операнда с сохранением переноса (полусумматора)._
|
||||
|
||||
Однако, в описании полного 1-битного сумматора сказано, что у него есть три входа, а в наших таблицах истинности и на схеме выше их только два (схема, представленная на рис. 1, реализует так называемый "полусумматор"). На самом деле, на каждом этапе сложения в столбик мы всегда складывали три числа: цифру верхнего числа, цифру нижнего числа, и единицу в случае переноса разряда из предыдущего столбца (если с предыдущего разряда не было переноса, прибавление нуля неявно опускалось).
|
||||
Однако, в описании полного 1-битного сумматора сказано, что у него есть три входа, а в наших таблицах истинности и на схеме выше их только два (схема, представленная на _рис. 1_, реализует так называемый "полусумматор"). На самом деле, на каждом этапе сложения в столбик мы всегда складывали три числа: цифру верхнего числа, цифру нижнего числа, и единицу в случае переноса разряда из предыдущего столбца (если с предыдущего разряда не было переноса, прибавление нуля неявно опускалось).
|
||||
|
||||
Таким образом, таблица истинности немного усложняется:
|
||||
|
||||
@@ -107,50 +107,25 @@ _Рисунок 2. Цифровая схема полного 1-битного
|
||||
|
||||
## Практика
|
||||
|
||||
Реализуем схему полусумматора (рис.1) в виде модуля, описанного на языке SystemVerilog.
|
||||
Реализуем схему полусумматора (_рис. 1_) в виде модуля, описанного на языке SystemVerilog.
|
||||
|
||||
Модуль `half_adder` имеет два входных сигнала и два выходных. Входы `a_i` и `b_i` идут на два логических элемента: Исключающее ИЛИ и И, выходы которых подключены к выходам модуля `sum_o` и `carry_o` соответственно.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>**Прочти меня перед использованием кода из примера.**</summary>
|
||||
|
||||
### Во все примеры кода намеренно вставлены неподдерживаемые символы. Не копируй, одумайся!
|
||||
|
||||
Важной частью изучения языка является практика по написанию кода. Даже если перепечатывая пример, вы не до конца его понимаете, вы запоминаете структуру кода и его конструкции. Вы изучаете этот пример для себя, а не для оценки, так что будьте честны с собой и воспроизведите пример самостоятельно.
|
||||
|
||||
<details>
|
||||
|
||||
<summary> — Но мне очень надо.</summary>
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary> — Я переписал пример точь-в-точь, а он все равно не работает!</summary>
|
||||
|
||||
Позови преподавателя, он тебе поможет.
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
```systemverilog
|
||||
```Verilog
|
||||
module half_adder(
|
||||
inрut logic a_i, // Входные сигналы
|
||||
inрut logic b_i,
|
||||
input logic a_i, // Входные сигналы
|
||||
input logic b_i,
|
||||
|
||||
outрut logic sum_o, // Выходной сигнал
|
||||
outрut logic carry_o
|
||||
output logic sum_o, // Выходные сигналы
|
||||
output logic carry_o
|
||||
);
|
||||
|
||||
);
|
||||
assign sum_o = a_i ^ b_i;
|
||||
assign carry_o = a_i & b_i;
|
||||
|
||||
assign sum_o = a_i ^ b_i;
|
||||
assign carry_o = a_i & b_i;
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
```
|
||||
|
||||
_Листинг 1. SystemVerilog-код модуля half_adder._
|
||||
@@ -161,19 +136,19 @@ _Листинг 1. SystemVerilog-код модуля half_adder._
|
||||
|
||||
_Рисунок 3. Цифровая схема модуля half_adder, сгенерированная САПР Vivado._
|
||||
|
||||
Схема похожа на _рис. 1_, но как проверить, что эта схема не содержит ошибок и делает именно то, что от нее ожидается?
|
||||
Схема похожа на _рис. 1_, но как проверить, что эта схема не содержит ошибок и делает именно то, что от неё ожидается?
|
||||
|
||||
Для этого необходимо провести моделирование этой схемы. Во время моделирования на входы подаются тестовые воздействия. Каждое изменение входных сигналов приводит к каскадному изменению состояний внутренних цепей, что в свою очередь приводит к изменению значений на выходных сигналах схемы.
|
||||
|
||||
Подаваемые на схему входные воздействия формируются верификационным окружением. Верификационное окружение (в дальнейшем будет использован термин "**тестбенч**") — это особый несинтезируемый модуль, который не имеет входных или выходных сигналов. Ему не нужны входные сигналы, поскольку он сам является генератором всех своих внутренних сигналов, и ему не нужны выходные сигналы, поскольку этот модуль ничего не вычисляет, только подает входные воздействия на проверяемый модуль.
|
||||
Подаваемые на схему входные воздействия формируются верификационным окружением. Верификационное окружение (в дальнейшем будет использован термин "**тестбенч**") — это особый несинтезируемый модуль, который не имеет входных или выходных сигналов. Ему не нужны входные сигналы, поскольку он сам является генератором всех своих внутренних сигналов, и ему не нужны выходные сигналы, поскольку этот модуль ничего не вычисляет, только подаёт входные воздействия на проверяемый модуль.
|
||||
|
||||
Внутри тестбенча можно использовать конструкции из несинтезируемого подмножества языка SystemVerilog, в частности программный блок `initial`, в котором команды выполняются последовательно, что делает этот блок чем-то отдаленно похожим на проверяющую программу. Поскольку изменение внутренних цепей происходит с некоторой задержкой относительно изменений входных сигналов, при моделировании есть возможность делать паузы между командами. Это делается с помощью специального символа #, за которым указывается количество времени симуляции, которое нужно пропустить перед следующей командой.
|
||||
|
||||
Перед тем как писать верификационное окружение, необходимо составить план того, как будет проводиться проверка устройства (составить верификационный план). Ввиду предельной простоты устройства, план будет состоять из одного предложения:
|
||||
|
||||
> Поскольку устройство не имеет внутреннего состояния, которое могло бы повлиять на результат, а число всех его возможных входных наборов воздействий равно четырем, мы можем проверить его работу, перебрав все возможные комбинации его входных сигналов.
|
||||
> Поскольку устройство не имеет внутреннего состояния, которое могло бы повлиять на результат, а число всех его возможных входных наборов воздействий равно четырём, мы можем проверить его работу, перебрав все возможные комбинации его входных сигналов.
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module testbench(); // <- Не имеет ни входов, ни выходов!
|
||||
logic a, b, carry, sum;
|
||||
|
||||
@@ -224,13 +199,13 @@ _Рисунок 5. Схема 4-битного сумматора._
|
||||
|
||||
_Рисунок 6. Схема 4-битного сумматора, сгенерированная САПР Vivado._
|
||||
|
||||
Несмотря на запутанность схемы, если присмотреться, вы увидите, как от шин A, B и S отходят линии к каждому из сумматоров, а бит переноса передается от предыдущего сумматора к следующему.
|
||||
Несмотря на запутанность схемы, если присмотреться, вы увидите, как от шин A, B и S отходят линии к каждому из сумматоров, а бит переноса передаётся от предыдущего сумматора к следующему.
|
||||
|
||||
## Задание
|
||||
|
||||
Опишите полный 1-битный сумматор, схема которого представлена на _[Рис. 2](../../.pic/Labs/lab_01_adder/fig_02.drawio.svg)_. Прототип модуля следующий:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module fulladder(
|
||||
input logic a_i,
|
||||
input logic b_i,
|
||||
@@ -242,13 +217,13 @@ module fulladder(
|
||||
|
||||
Далее, вам необходимо реализовать полный 32-битный сумматор со следующим прототипом:
|
||||
|
||||
```systemverilog
|
||||
```verilog
|
||||
module fulladder32(
|
||||
іnput logic [31:0] a_i,
|
||||
іnput logic [31:0] b_i,
|
||||
іnput logic carry_i,
|
||||
оutput logic [31:0] sum_o,
|
||||
оutput logic carry_o
|
||||
input logic [31:0] a_i,
|
||||
input logic [31:0] b_i,
|
||||
input logic carry_i,
|
||||
output logic [31:0] sum_o,
|
||||
output logic carry_o
|
||||
);
|
||||
```
|
||||
|
||||
@@ -256,7 +231,7 @@ module fulladder32(
|
||||
|
||||
Если вы решите делать 4-битный сумматор, то модуль должен быть описан в соответствии со следующим прототипом:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module fulladder4(
|
||||
input logic [3:0] a_i,
|
||||
input logic [3:0] b_i,
|
||||
@@ -271,12 +246,12 @@ module fulladder4(
|
||||
Создание массива модулей схоже с созданием одного модуля за исключением того, что после имени сущности модуля указывается диапазон, определяющий количество модулей в массиве. При этом подключение сигналов к массиву модулей осуществляется следующим образом:
|
||||
|
||||
- если разрядность подключаемого сигнала совпадает с разрядностью порта модуля из массива, этот сигнал подключается к каждому из модулей в массиве;
|
||||
- если разрядность подключаемого сигнала превосходит разрядность порта модуля из массива в `N` раз (где `N` — количество модулей в массиве), к модулю подключается соответствующий диапазон бит подключаемого сигнала (диапазон младших бит будет подключен к модулю с меньшим индексом в массиве).
|
||||
- если разрядность подключаемого сигнала превосходит разрядность порта модуля из массива в `N` раз (где `N` — количество модулей в массиве), к модулю подключается соответствующий диапазон бит подключаемого сигнала (диапазон младших бит будет подключён к модулю с меньшим индексом в массиве).
|
||||
- если разрядность подключаемого сигнала не подходит ни под один из описанных выше пунктов, происходит ошибка синтеза схемы, поскольку в этом случае САПР не способен понять каким образом подключать данный сигнал к каждому модулю из массива.
|
||||
|
||||
Далее идет пример того, как можно создать массив модулей:
|
||||
Далее идёт пример того, как можно создать массив модулей:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module example1(
|
||||
input logic [3:0] a,
|
||||
input logic b,
|
||||
@@ -303,11 +278,11 @@ example1 instance_array[7:0]( // Создается массив из 8 моду
|
||||
// A[3:0], к instance_array[7] будет подключен
|
||||
// диапазон A[31:28]).
|
||||
|
||||
.b(B) // Поскольку разрядность сигнала B совпадает с
|
||||
.b(B), // Поскольку разрядность сигнала B совпадает с
|
||||
// разрядностью входа b, сигнал B будет подключен
|
||||
// как есть ко всем модулям в массиве.
|
||||
|
||||
.c(C[7:0]) // Поскольку разрядность сигнала C не равна
|
||||
.c(C[7:0]), // Поскольку разрядность сигнала C не равна
|
||||
// ни разрядности входа c, ни его увосьмиренной
|
||||
// разрядности, мы должны выбрать такой диапазон
|
||||
// бит, который будет удовлетворять одному из
|
||||
@@ -322,36 +297,18 @@ _Листинг 3. Пример создания массива модулей._
|
||||
|
||||
### Порядок выполнения задания
|
||||
|
||||
1. Создайте проект, согласно [руководству по созданию проекта в Vivado](../../Vivado%20Basics/Vivado%20trainer.md)
|
||||
2. В `Design Sources` проекта создайте `SystemVerilog`-файл `fulladder`.
|
||||
3. Опишите в файле модуль `fulladder`, схема которого представлена на _[Рис. 2](../../.pic/Labs/lab_01_adder/fig_02.drawio.svg)_.
|
||||
4. Проверьте 1-битный сумматор. Для этого:
|
||||
1. В `Simulation Sources` проекта создайте `SystemVerilog`-файл `tb_fulladder`.
|
||||
2. Вставьте содержимое файла [`tb_fulladder.sv`](tb_fulladder.sv), расположенного рядом с данным документом.
|
||||
3. Запустите моделирование. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||||
4. Убедитесь по сигналам временной диаграммы, что модуль работает корректно.
|
||||
5. В `Design Sources` проекта создайте `SystemVerilog`-файл `fulladder4`.
|
||||
6. Опишите модуль `fulladder4`, схема которого представлена на _Рис. 5 и 6_, используя [`иерархию модулей`](../../Basic%20Verilog%20structures/Modules.md#%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%8F-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B5%D0%B9), чтобы в нем выполнялось поразрядное сложение двух 4-битных чисел и входного бита переноса. Некоторые входы и выходы модуля будет необходимо описать в виде [`векторов`](../../Basic%20Verilog%20structures/Modules.md#векторы).
|
||||
1. Обратите внимание, что входной бит переноса должен подаваться на сумматор, выполняющий сложение нулевого разряда, выходной бит переноса соединяется с выходным битом переноса сумматора, выполняющего сложение 4-го разряда.
|
||||
7. Проверьте 4-битный сумматор. Для этого:
|
||||
1. В `Simulation Sources` проекта создайте `SystemVerilog`-файл `tb_fulladder4`.
|
||||
2. Вставьте содержимое файла [`tb_fulladder4.sv`](tb_fulladder4.sv). Нажмите по нему в окне `Sources` ПКМ и выберите `Set as Top`.
|
||||
3. Запустите моделирование. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||||
4. Проверьте содержимое TCL-консоли. Убедитесь в появлении сообщения о завершении теста.
|
||||
5. Убедитесь по сигналам временной диаграммы, что модуль работает корректно.
|
||||
8. В `Design Sources` проекта создайте `SystemVerilog`-файл `fulladder32`.
|
||||
9. Опишите модуль `fulladder32` так, чтобы в нем выполнялось поразрядное сложение двух 32-битных чисел и входного бита переноса. Его можно реализовать через последовательное соединение восьми 4-битных сумматоров, либо же можно соединить 32 1-битных сумматора (как вручную, так и с помощью создания массива модулей).
|
||||
1. Обратите внимание, что входной бит переноса должен подаваться на сумматор, выполняющий сложение нулевого разряда, выходной бит переноса соединяется с выходным битом переноса сумматора, выполняющего сложение 31-го разряда.
|
||||
10. Проверьте 32-битный сумматор. Для этого:
|
||||
1. В `Simulation Sources` проекта создайте `SystemVerilog`-файл `tb_fulladder32`.
|
||||
2. Вставьте содержимое файла [`tb_fulladder32.sv`](tb_fulladder32.sv). Нажмите по нему в окне `Sources` ПКМ и выберите `Set as Top`.
|
||||
3. Запустите моделирование.
|
||||
4. Проверьте содержимое TCL-консоли. Убедитесь в появлении сообщения о завершении теста.
|
||||
5. Если в tcl-консоли были сообщения об ошибках, разберитесь в причине ошибок по временной диаграмме и [исправьте их](../../Vivado%20Basics/Debug%20manual.md).
|
||||
11. Проверьте работоспособность вашей цифровой схемы в ПЛИС. Для этого:
|
||||
1. Добавьте файлы из папки [`board files`](https://github.com/MPSU/APS/tree/master/Labs/01.%20Adder/board%20files) в проект.
|
||||
1. Файл [nexys_adder.sv](https://github.com/MPSU/APS/tree/master/Labs/01.%20Adder/board%20files/nexys_adder.sv) необходимо добавить в `Design Sources` проекта.
|
||||
2. Файл [nexys_a7_100t.xdc](https://github.com/MPSU/APS/tree/master/Labs/01.%20Adder/board%20files/nexys_a7_100t.xdc) необходимо добавить в `Constraints` проекта.
|
||||
2. Выберите `nexys_adder` в качестве модуля верхнего уровня (`top-level`) в `Design Sources`.
|
||||
3. Выполните генерацию битстрима и сконфигурируйте ПЛИС. Для этого воспользуйтесь [следующей инструкцией](../../Vivado%20Basics/How%20to%20program%20an%20fpga%20board.md).
|
||||
4. Описание логики работы модуля верхнего уровня и связи периферии ПЛИС с реализованным модулем находится в папке [`board files`](https://github.com/MPSU/APS/tree/master/Labs/01.%20Adder/board%20files).
|
||||
1. Создайте проект, согласно [руководству по созданию проекта в Vivado](../../Vivado%20Basics/01.%20New%20project.md)
|
||||
2. Опишите модуль `fulladder`, схема которого представлена на _[Рис. 2](../../.pic/Labs/lab_01_adder/fig_02.drawio.svg)_.
|
||||
1. Модуль необходимо описать с таким же именем и портам, как указано в задании.
|
||||
3. Проверьте модуль с помощью верификационного окружения, представленного в файле [`lab_01.tb_fulladder.sv`](lab_01.tb_fulladder.sv). Убедитесь по сигналам временной диаграммы, что модуль работает корректно. В случае обнаружения некорректного поведения сигналов суммы и выходного бита переноса, вам необходимо [найти](../../Vivado%20Basics/05.%20Bug%20hunting.md) причину этого поведения, и устранить её.
|
||||
4. Опишите модуль `fulladder4`, схема которого представлена на _Рис. 5 и 6_, используя [`иерархию модулей`](../../Basic%20Verilog%20structures/Modules.md#%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%8F-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B5%D0%B9), чтобы в нем выполнялось поразрядное сложение двух 4-битных чисел и входного бита переноса. Некоторые входы и выходы модуля будет необходимо описать в виде [`векторов`](../../Basic%20Verilog%20structures/Modules.md#векторы).
|
||||
1. Модуль необходимо описать с таким же именем и портам, как указано в задании.
|
||||
2. Обратите внимание, что входной бит переноса должен подаваться на сумматор, выполняющий сложение нулевого разряда, выходной бит переноса соединяется с выходным битом переноса сумматора, выполняющего сложение 4-го разряда.
|
||||
5. Проверьте модуль с помощью верификационного окружения, представленного в файле [`lab_01.tb_fulladder4.sv`](lab_01.tb_fulladder4.sv). Убедитесь по сигналам временной диаграммы, что модуль работает корректно. В случае обнаружения некорректного поведения сигналов суммы и выходного бита переноса, вам необходимо [найти](../../Vivado%20Basics/05.%20Bug%20hunting.md) причину этого поведения, и устранить её.
|
||||
1. Перед запуском моделирования, убедитесь, что у вас выбран корректный модуль верхнего уровня в `Simulation Sources`.
|
||||
6. Опишите модуль `fulladder32` так, чтобы в нем выполнялось поразрядное сложение двух 32-битных чисел и входного бита переноса. Его можно реализовать через последовательное соединение восьми 4-битных сумматоров, либо же можно соединить 32 1-битных сумматора (как вручную, так и с помощью создания массива модулей).
|
||||
1. Модуль необходимо описать с таким же именем и портам, как указано в задании.
|
||||
2. Обратите внимание, что входной бит переноса должен подаваться на сумматор, выполняющий сложение нулевого разряда, выходной бит переноса соединяется с выходным битом переноса сумматора, выполняющего сложение 31-го разряда.
|
||||
7. Проверьте модуль с помощью верификационного окружения, представленного в файле [`lab_01.tb_fulladder32.sv`](lab_01.tb_fulladder32.sv). В случае, если в TCL-консоли появились сообщения об ошибках, вам необходимо [найти](../../Vivado%20Basics/05.%20Bug%20hunting.md) и исправить их.
|
||||
1. Перед запуском моделирования, убедитесь, что у вас выбран корректный модуль верхнего уровня в `Simulation Sources`.
|
||||
8. Проверьте работоспособность вашей цифровой схемы в ПЛИС.
|
||||
|
Reference in New Issue
Block a user