mirror of
https://github.com/MPSU/APS.git
synced 2026-06-10 11:13:33 +00:00
English version draft
Assisted-by: Claude:claude-4.6-sonnet
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Описание регистров в SystemVerilog
|
||||
# Describing Registers in SystemVerilog
|
||||
|
||||
Перед тем, как описывать память, необходимо научиться описывать отдельные регистры. **Регистр** — устройство для записи, хранения и считывания n-разрядных двоичных данных и выполнения других операций над ними [1, стр. 32]. В современной электронике, регистр чаще всего строится на D-триггерах. В лабораторной работе по АЛУ уже вскользь упоминалось, что как для описания проводов, так и для описания регистров, используется тип `logic`.
|
||||
Before describing memory, you need to learn how to describe individual registers. A **register** is a device for writing, storing, and reading n-bit binary data and performing other operations on it [1, p. 32]. In modern electronics, a register is most commonly built from D flip-flops. The ALU lab briefly mentioned that both wires and registers are declared using the `logic` type.
|
||||
|
||||
```Verilog
|
||||
logic reg_name;
|
||||
@@ -8,23 +8,23 @@ logic reg_name;
|
||||
|
||||

|
||||
|
||||
У регистра может быть несколько входов и один выход. Основных входов, без которых не может существовать регистр два: вход данных и вход тактирующего синхроимпульса. На рисунке они обозначены как `D` и `clk`. Опциональный вход сигнала сброса (`rst`) позволяет обнулять содержимое регистра вне зависимости от входных данных и может работать как с тактовым синхроимпульсом (синхронный сброс), так и без него (асинхронный сброс).
|
||||
A register can have multiple inputs and one output. There are two essential inputs without which a register cannot exist: a data input and a clock input. In the figure, these are labeled `D` and `clk`. The optional reset input (`rst`) allows the register contents to be cleared regardless of the data input, and it can operate either synchronously with the clock signal (synchronous reset) or independently of it (asynchronous reset).
|
||||
|
||||
Помимо прочего у регистра также может быть входной сигнал разрешения записи (`enable`), который определяет будут ли записаны данные с входного сигнала данных в регистр или нет, опциональный вход установки (`set`), позволяющий принудительно выставить значение регистра в единицу.
|
||||
In addition, a register may have a write enable input (`enable`), which determines whether the data from the data input will be written to the register, and an optional set input (`set`), which forces the register value to logic one.
|
||||
|
||||
Выход у регистра один. На рисунке выше он обозначен как `Q`.
|
||||
A register has a single output. In the figure above, it is labeled `Q`.
|
||||
|
||||
Важно понимать, что названия приведенных портов не являются чем-то высеченным на камне, они просто описывают функциональное назначение. В процессе описания работы регистра вы будете оперировать только над именем регистра, и сигналами, которые подводите к нему.
|
||||
It is important to understand that the port names given here are not set in stone — they simply describe the functional purpose. When describing the behavior of a register, you will only operate on the register's name and the signals connected to it.
|
||||
|
||||
Поскольку все сигналы в цифровой схеме передаются по цепям, удобно представлять, что к выходу регистра всегда неявно подключен провод, с именем, совпадающим с именем регистра, поэтому вы можете использовать имя регистра в дальнейшей цифровой логике:
|
||||
Since all signals in a digital circuit are carried over nets, it is convenient to think of a wire with the same name as the register as being implicitly connected to the register's output. This means you can use the register's name in subsequent digital logic:
|
||||
|
||||

|
||||
|
||||
Итак, мы добавили регистр на холст схемы, но как соединить его с какой-то логикой? Предположим, у нас есть сигнал тактового синхроимпульса и данные, которые мы хотим записать:
|
||||
So, we have placed a register on the schematic canvas — but how do we connect it to some logic? Suppose we have a clock signal and data we want to write:
|
||||
|
||||

|
||||
|
||||
Данной схеме соответствует код:
|
||||
This schematic corresponds to the following code:
|
||||
|
||||
```Verilog
|
||||
module reg_example(
|
||||
@@ -38,19 +38,19 @@ module reg_example(
|
||||
endmodule
|
||||
```
|
||||
|
||||
Очевидно, мы хотим подключить сигнал `clk` ко входу тактирующего сигнала регистра, вход `data` ко входу данных, а выход регистра к выходу `reg_data`:
|
||||
Clearly, we want to connect the `clk` signal to the register's clock input, `data` to the data input, and the register's output to the `reg_data` output:
|
||||
|
||||

|
||||
|
||||
Запись в регистр возможна только по фронту тактирующего синхроимпульса. **Фронт** — это переход сигнала из нуля в единицу (**положительный фронт**), либо из единицы в ноль (**отрицательный фронт**).
|
||||
Writing to a register is only possible on the edge of the clock signal. An **edge** is a transition of the signal from zero to one (**rising edge**) or from one to zero (**falling edge**).
|
||||
|
||||
Описание регистра, а также указание фронта и тактирующего сигнала происходит в конструкции `always_ff`:
|
||||
The register description, along with the specification of the edge and clock signal, is done using the `always_ff` construct:
|
||||
|
||||
```Verilog
|
||||
always_ff @(posedge clk)
|
||||
```
|
||||
|
||||
Далее, внутри данной конструкции необходимо указать, что происходит с содержимым регистра. В нашем случае, происходит запись с входного сигнала `data`
|
||||
Inside this construct, you specify what happens to the register contents. In our case, the data from the `data` input is written:
|
||||
|
||||
```Verilog
|
||||
always_ff @(posedge clk) begin
|
||||
@@ -59,11 +59,11 @@ end
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Обратите внимание на оператор `<=`. В данном случае, это не знак "меньше либо равно", а оператор **неблокирующего присваивания**. Существует оператор **блокирующего присваивания** (`=`), который может поменять способ построения схемы для такого же выражения справа от оператора. Хоть это и плохая практика в обучении, но пока вам надо просто запомнить: **при описании записи в регистр всегда используйте оператор неблокирующего присваивания `<=`**. Подробнее рассказано в документе "[О различиях между блокирующими и неблокирующими присваиваниями](./Assignments.md)".
|
||||
> Note the `<=` operator. In this context, it is not the "less than or equal to" sign — it is the **non-blocking assignment** operator. There is also a **blocking assignment** operator (`=`), which can alter how the circuit is constructed for the same right-hand-side expression. While it may be considered poor educational practice, for now you simply need to remember: **always use the non-blocking assignment operator `<=` when describing writes to a register**. More details are provided in the document "[On the Differences Between Blocking and Non-Blocking Assignments](./Assignments.md)".
|
||||
|
||||
Помимо прочего, нам необходимо связать выход схемы с выходом регистра. Это можно сделать уже известным вам оператором **непрерывного присваивания** `assign`.
|
||||
In addition, we need to connect the module's output to the register's output. This can be done using the **continuous assignment** operator `assign`, which you are already familiar with.
|
||||
|
||||
Таким образом, итоговый код описания данной схемы примет вид:
|
||||
The complete code describing this schematic is as follows:
|
||||
|
||||
```Verilog
|
||||
module reg_example(
|
||||
@@ -83,7 +83,7 @@ module reg_example(
|
||||
endmodule
|
||||
```
|
||||
|
||||
Предположим, мы хотим добавить управление записью в регистр через сигналы `enable` и `reset`. Это, например, можно сделать следующим образом:
|
||||
Suppose we want to add write control via `enable` and `reset` signals. This can be done as follows:
|
||||
|
||||
```Verilog
|
||||
module reg_example(
|
||||
@@ -110,26 +110,26 @@ module reg_example(
|
||||
endmodule
|
||||
```
|
||||
|
||||
Обратите внимание на очередность условий. В первую очередь, мы проверяем условие **сброса**, и только после этого условие **разрешения на запись**.
|
||||
Если сперва проверить разрешение на запись, а затем в блоке `else` описать логику сброса, то регистр не будет сбрасываться в случае, если `enable` будет равен `1` (запись в регистр будет приоритетней его сброса). Если сброс описать не в блоке `else`, а в отдельном блоке `if`, то может возникнуть неопределенное поведение: нельзя однозначно сказать, что запишется в регистр, если одновременно придут сигналы `reset` и `enable`. Поэтому при наличии сигнала сброса, остальная логика по записи в регистр должна размещаться в блоке `else`.
|
||||
Pay attention to the order of conditions. We first check the **reset** condition, and only then the **write enable** condition.
|
||||
If the write enable condition is checked first and the reset logic is placed in the `else` block, the register will not be reset when `enable` is asserted (the write operation takes priority over the reset). If the reset is described in a separate `if` block rather than in an `else` block, undefined behavior may occur: it becomes impossible to determine what will be written to the register if both `reset` and `enable` arrive simultaneously. Therefore, when a reset signal is present, all other write logic must be placed inside the `else` block.
|
||||
|
||||
Кроме того, САПР смотрят на паттерн описания элемента схемы и, когда распознают его, реализуют элемент так, как задумывал разработчик. Поэтому при описании регистра всегда сперва описывается сигнал сброса (если он используется) и только затем в блоке `else` описывается вся остальная часть логики записи.
|
||||
Furthermore, EDA tools recognize the pattern used to describe a circuit element and, once recognized, implement it as the designer intended. For this reason, when describing a register, the reset signal (if used) must always be described first, followed by all other write logic in the `else` block.
|
||||
|
||||
Итоговая схема регистра со сбросом и сигналом разрешения записи:
|
||||
The resulting schematic of a register with reset and write enable:
|
||||
|
||||

|
||||
|
||||
Помимо прочего есть еще одно важное правило, которое необходимо знать при описании регистра:
|
||||
There is one more important rule to know when describing a register:
|
||||
|
||||
**Присваивание регистру может выполняться только в одном блоке `always`**
|
||||
**Assignment to a register may only occur within a single `always` block.**
|
||||
|
||||
Даже если вдруг САПР не выдаст сразу сообщение об ошибке, в конечном итоге, на этапе синтеза схемы она рано или поздно появится в виде сообщения связанного с **"multiple drivers"**.
|
||||
Even if the EDA tool does not immediately report an error, it will eventually appear during synthesis as a message related to **"multiple drivers"**.
|
||||
|
||||
В блоке присваивания регистру можно описывать и комбинационную логику, стоящую перед ним, например схему:
|
||||
Combinational logic that precedes the register can also be described inside the register's assignment block. For example, the following schematic:
|
||||
|
||||

|
||||
|
||||
можно описать как
|
||||
can be described as:
|
||||
|
||||
```Verilog
|
||||
module reg_example(
|
||||
@@ -157,7 +157,7 @@ module reg_example(
|
||||
endmodule
|
||||
```
|
||||
|
||||
Однако это всего лишь упрощение. Если вы умеете описывать регистр с подключением к нему всего одного провода на входе данных, вы все равно сможете описать эту схему:
|
||||
However, this is merely a shorthand. If you know how to describe a register with a single wire connected to its data input, you can still describe this schematic:
|
||||
|
||||
```Verilog
|
||||
module reg_example(
|
||||
@@ -169,11 +169,11 @@ module reg_example(
|
||||
output logic reg_data
|
||||
);
|
||||
|
||||
logic reg_name; // Обратите внимание, что несмотря на то, что
|
||||
logic ab; // и reg_name и ab объявлены типом logic,
|
||||
// ab станет проводом, а reg_name - регистром
|
||||
// (из-за непрерывного присваивания на ab, и блока
|
||||
// always_ff для reg_name)
|
||||
logic reg_name; // Note that even though both
|
||||
logic ab; // reg_name and ab are declared as logic,
|
||||
// ab will become a wire and reg_name a register
|
||||
// (due to the continuous assignment for ab and the
|
||||
// always_ff block for reg_name)
|
||||
|
||||
assign ab = A & B;
|
||||
|
||||
@@ -191,12 +191,12 @@ module reg_example(
|
||||
endmodule
|
||||
```
|
||||
|
||||
Поэтому так важно разобраться в базовом способе описания регистра.
|
||||
This is why it is so important to understand the fundamental way of describing a register.
|
||||
|
||||
Более того, с точки зрения синтезатора данное описание проще для синтеза, т.к. ему не надо разделять из одного `always` блока комбинационную и синхронные части.
|
||||
Moreover, from the synthesizer's perspective, this description is easier to synthesize because it does not need to separate the combinational and synchronous parts from within a single `always` block.
|
||||
|
||||
Вообще говоря, регистр в общем смысле этого слова представляет собой многоразрядную конструкцию (в рассмотренном ранее примере, 1-битный регистр мог представлять из себя простой D-триггер).
|
||||
Создание многоразрядного регистра мало отличается от создания многоразрядного провода, а описание логики записи в многоразрядный регистр ничем не отличается от логики записи в одноразрядный регистр:
|
||||
In general, a register is a multi-bit construct (in the earlier example, a 1-bit register could be represented as a simple D flip-flop).
|
||||
Creating a multi-bit register differs little from creating a multi-bit wire, and the write logic for a multi-bit register is identical to that of a 1-bit register:
|
||||
|
||||
```Verilog
|
||||
module reg_example(
|
||||
@@ -216,21 +216,21 @@ module reg_example(
|
||||
endmodule
|
||||
```
|
||||
|
||||
## Итоги главы
|
||||
## Chapter Summary
|
||||
|
||||
1. [Регистр](https://ru.wikipedia.org/wiki/Регистр_(цифровая_техника)) — это базовая ячейка памяти, позволяющая хранить состояние, пока на схему подается питание.
|
||||
2. Для объявления регистра используется тип `logic`, при необходимости после типа указывается разрядность будущего регистра.
|
||||
3. Для описания логики записи в регистр используется блок `always_ff`, в круглых скобках которого указывается тактирующий сигнал и фронт, по которому будет вестись запись, а также (в случае асинхронного сброса), сигнал сброса.
|
||||
4. Регистр может иметь различные управляющие сигналы: установки/сброса/разрешения на запись. Логика этих управляющих сигналов является частью логики записи в этот регистр и так же описывается в блоке `always_ff`.
|
||||
5. При описании логики записи в регистр, необходимо пользоваться оператором **неблокирующего присваивания** `<=`.
|
||||
6. Нельзя описывать логику записи в регистр более чем в одном блоке `always` (иными словами, операция присваивания для каждого регистра может находиться только в одном блоке always).
|
||||
1. A [register](https://en.wikipedia.org/wiki/Hardware_register) is a basic storage element that retains its state as long as the circuit is powered.
|
||||
2. A register is declared using the `logic` type; if needed, the bit width is specified after the type.
|
||||
3. The write logic for a register is described using the `always_ff` block, whose parentheses specify the clock signal and the edge on which writing occurs, as well as the reset signal (in the case of an asynchronous reset).
|
||||
4. A register can have various control signals: set, reset, and write enable. The logic for these control signals is part of the register's write logic and is also described inside the `always_ff` block.
|
||||
5. When describing register write logic, the **non-blocking assignment** operator `<=` must be used.
|
||||
6. Write logic for a register must not be described in more than one `always` block (in other words, the assignment operation for each register may only appear in a single `always` block).
|
||||
|
||||
## Проверь себя
|
||||
## Test Yourself
|
||||
|
||||
Как, по-вашему, описать на языке SystemVerilog схему, приведённую ниже?
|
||||
How would you describe the schematic shown below in SystemVerilog?
|
||||
|
||||

|
||||
|
||||
## Список источников
|
||||
## References
|
||||
|
||||
1. Ш. Габриелян, Е. Вахтина / Электротехника и электроника. Методические рекомендации. — Ставрополь: Аргус, 2013
|
||||
1. Sh. Gabrielyan, E. Vakhtina / Electrical Engineering and Electronics. Methodological Guidelines. — Stavropol: Argus, 2013
|
||||
|
||||
Reference in New Issue
Block a user