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:
Andrei Solodovnikov
2024-09-02 10:20:08 +03:00
committed by GitHub
parent 78bb01ef95
commit a28002e681
195 changed files with 3640 additions and 2664 deletions

View File

@@ -0,0 +1,104 @@
# Список типичных ошибок в SystemVerilog
- [Список типичных ошибок в SystemVerilog](#список-типичных-ошибок-в-systemverilog)
- [имя сигнала is not a type](#имя-сигнала-is-not-a-type)
- [cannot find port on this module](#cannot-find-port-on-this-module)
- [Использование сигнала без его объявления (или до его объявления)](#использование-сигнала-без-его-объявления-или-до-его-объявления)
- [Объявление выхода модуля его входом](#объявление-выхода-модуля-его-входом)
- [](#)
## имя сигнала is not a type
Скорее всего, компилятор не распознал присваивание, поскольку оно было записано с ошибками. Вне блоков `always` и `initial` можно выполнять только непрерывное присваивание (через `assign`).
```Verilog
module half_adder(input logic a, input logic b, output logic c);
c = a ^ b; // ошибка, для непрерывного присваивания
// необходимо ключевое слово assign
endmodule
```
_Листинг 1. Пример ошибочного присваивания._
## cannot find port on this module
Имя порта, указанного при подключении модуля (после точки) не соответствует ни одному имени сигналов подключаемого модуля
```Verilog
module half_adder(input logic a, input logic b, output logic c);
assign c = a ^ b;
endmodule
module testbench();
logic A, B, C;
adder DUT(
.A(A), // <- здесь будет ошибка,
// т.к. в модуле half_adder нет порта 'A'
.b(B),
.c(C)
);
endmodule
```
_Листинг 2. Пример создание экземпляра модуля с ошибкой в описании его входных портов._
## Использование сигнала без его объявления (или до его объявления)
Достаточно частая ошибка, когда сигнал забывают объявить, либо объявляют, но потом добавляют код с использованием этого сигнала выше его объявления. Не смотря на то, что в SystemVerilog не важно, в каком порядке были описаны блоки кода, это не касается объявления сигналов — они должны выполняться до их использования. Рассмотрим следующий пример, приведенный в _листинге 3_.
```Verilog
module example(
input logic [1:0] a,
input logic [1:0] b,
output logic [1:0] c
);
assign ab = a | b;
// logic [1:0] ab;
assign c = ab;
endmodule
module tb_example();
logic [1:0] a, b, c;
logic [3:0] i = 0;
example DUT(.a(a),.b(b),.c(c));
assign {a, b} = i;
initial repeat(15) begin
#5;
i++;
end
endmodule
```
_Литсинг 3. Пример присваивания значения сигналу без его объявления._
Результат моделирования _листинга 3_ приведён на _рисунке 1_.
![../.pic/Basic%20Verilog%20structures/common%20mistakes/figure_01.png](../.pic/Basic%20Verilog%20structures/common%20mistakes/figure_01.png)
Как вы можете увидеть, код был успешно собрался и был промоделирован, но значения в выделенных синим прямоугольниках не те, что должны были быть. Можно заметить также и то, что значение выхода `c` никогда не превышает единицу.
Если мы начнем разбираться, и решим вытащить на временную диаграмму внутренний сигнал модуля `ab`, мы увидим, что он почему-то однобитный. Более того, если раскомментировать строчку с объявлением сигнала `ab`, результат никак не изменится.
Подобное поведение в точности воспроизводит требование стандарта SystemVerilog [1, стр. 108]:
> - Если идентификатор использовался списке сигналов, подключаемых к модулю, и этот идентификатор не был объявлен в области видимости, которая доступна при этом подключении, то неявно подразумевается однобитный провод.
> - Если идентификатор встречается по левую сторону от оператора непрерывного присваивания, и этот идентификатор не был объявлен в той области видимости, которая доступна оператору, то неявно подразумевается однобитный провод.
Иными словами, если вы присваиваете значение необъявленному сигналу, или пытаетесь подключить необъявленный сигнал к модулю, неявно создается однобитный сигнал с тем же именем (попробуйте удалить объявление сигналов `a`, `b`, `c` в тестбенче _листинга 3_ и посмотрите, как изменится разрядность сигналов тестбенча на временной диаграмме).
Даже если объявите сигнал с правильной разрядностью после его использования — это уже ничему не поможет, поскольку повторные объявления уже объявленных проводов и регистров стандартом запрещены [1, стр. 91] и в зависимости от САПР будут либо проигнорированы, либо вызовут ошибку.
Подобная ошибка легко обнаруживается линтером (появился в Vivado начиная с версии 2023.1). Кроме того, при попытке открыть схематик описанной схемы, в TCL-консоли появится сообщение об использовании необъявленного идентификатора:
```text
INFO: [Synth 8-11241] undeclared symbol 'ab', assumed default net type 'wire'
```
## Объявление выхода модуля его входом
Очень часто в попытке сэкономить себе немного времени студенты выполняют операцию копирования. В частности, копирования строк вида `input logic [7:0]` в процессе описания портов модуля. В случае, если по итогу подобного копирования, выход модуля будет объявлен как его вход (т.е. с помощью ключевого слова `input` вместо `output`).
##