# Список типичных ошибок в 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`, мы увидим, что он почему-то 1-битный. Более того, если раскомментировать строчку с объявлением сигнала `ab`, результат никак не изменится.

Подобное поведение в точности воспроизводит требование стандарта SystemVerilog [1, стр. 108]:

> - Если идентификатор использовался списке сигналов, подключаемых к модулю, и этот идентификатор не был объявлен в области видимости, которая доступна при этом подключении, то неявно подразумевается 1-битный провод.
> - Если идентификатор встречается по левую сторону от оператора непрерывного присваивания, и этот идентификатор не был объявлен в той области видимости, которая доступна оператору, то неявно подразумевается 1-битный провод.

Иными словами, если вы присваиваете значение необъявленному сигналу, или пытаетесь подключить необъявленный сигнал к модулю, неявно создается 1-битный сигнал с тем же именем (попробуйте удалить объявление сигналов `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`).

## 