mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 09:10:10 +00:00
Перенос drawio-изображений в svg-формат
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
Предположим, у нас есть следующий набор сигналов:
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
|
||||
@@ -25,7 +25,7 @@ logic [5:0] e;
|
||||
- на его следующие 2 бита подавались биты `[4:3]` сигнала `c`
|
||||
- на младшие 2 бита подавался сигнал `d`
|
||||
|
||||

|
||||

|
||||
|
||||
Это можно сделать путем 4 непрерывных присваиваний:
|
||||
|
||||
@@ -58,7 +58,7 @@ assign e = {a, b, c[4:3], d};
|
||||
|
||||
Кроме того, возможна и обратная ситуация. Предположим, мы хотим подать отдельные биты сигнала `e` на различные провода:
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
logic a;
|
||||
@@ -105,4 +105,3 @@ logic [7:0] e;
|
||||
|
||||
assign e = { {3{c[4:3]}}, a, b};
|
||||
```
|
||||
|
||||
|
@@ -86,19 +86,19 @@ endmodule
|
||||
|
||||
Для начала, добавим на структурную схему входы и выходы модуля:
|
||||
|
||||

|
||||

|
||||
|
||||
В первую очередь, спецификация вводит понятия **запрос на чтение** и **запрос на запись**. Создадим вспомогательные провода, которые будут сигнализировать о том, что произошел **запрос на чтение** или **запрос на запись**:
|
||||
|
||||

|
||||

|
||||
|
||||
Далее, спецификация накладывает ограничение на допустимые адреса и значения. Поэтому создадим вспомогательные сигналы, сигнализирующие о том, что текущий адрес соответствует одному из регистров контроллера, а данные для записи соответствуют диапазону допустимых значений этих регистров:
|
||||
|
||||

|
||||

|
||||
|
||||
Теперь, когда подготовительные работы выполнены, начнем с реализации сброса этого контроллера. Сброс может произойти в двух случаях: когда `rst_i == 1` либо же в случае **запроса на запись** единицы по адресу `0x24`. Создадим вспомогательный провод `rst`, который будет равен единице в случае, если произойдет любое из этих событий. Этот сигнал будет сбрасывать все созданные в данном модуле регистры.
|
||||
|
||||

|
||||

|
||||
|
||||
Продолжим описание контроллера, создав первый из **архитектурных регистров** — `led_val`. Запись в этот регистр возможна только в случае выполнения трех условий:
|
||||
|
||||
@@ -108,7 +108,7 @@ endmodule
|
||||
|
||||
Создадим вспомогательный сигнал `val_en`, который будет равен единице только в случае выполнения этих трех условий:
|
||||
|
||||

|
||||

|
||||
|
||||
Теперь реализация регистра `lev_val` становится совершенно тривиальной задачей, ведь у нас есть:
|
||||
|
||||
@@ -116,11 +116,11 @@ endmodule
|
||||
* сигнал разрешения записи в регистр `val_en`;
|
||||
* сигнал данных для записи в регистр `write_data_i`(из которого мы будем брать только младшие 16 бит данных).
|
||||
|
||||

|
||||

|
||||
|
||||
Аналогичным образом реализуем еще один **архитектурный регистр** `led_mode`:
|
||||
|
||||

|
||||

|
||||
|
||||
Два этих регистра должны управлять поведением выходного сигнала `led_o` следующим образом:
|
||||
|
||||
@@ -140,7 +140,7 @@ endmodule
|
||||
* счетчик досчитал до 20 миллионов (`cntr >= 32'd20_000_000`);
|
||||
* в остальных ситуациях, счетчик инкрементирует свое значение.
|
||||
|
||||

|
||||

|
||||
|
||||
Последним этапом описания контроллера будет добавление логики управления выходным сигналом `read_data_o`.
|
||||
|
||||
@@ -154,4 +154,4 @@ endmodule
|
||||
|
||||
Таким образом, итоговая схема примет вид:
|
||||
|
||||

|
||||

|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
Определим наш модуль:
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
module
|
||||
@@ -21,7 +21,7 @@ endmodule
|
||||
|
||||
У всякого модуля должно быть название. Назовём его `box`. В круглых скобках пишутся имена портов, их направление и типы. Если модуль не имеет ни входов, ни выходов, внутри скобок ничего не пишется. После них всегда ставится точка с запятой.
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
module box();
|
||||
@@ -32,7 +32,7 @@ endmodule
|
||||
|
||||
Модуль без входов и выходов (портов) — это просто коробка, которая никак не взаимодействует с внешним миром. Подключим к нему два входных сигнала `a, b` и один выходной `q`. Для объявления портов, необходимо указать направление порта (вход это или выход), и тип используемого сигнала. В рамках данного курса лабораторных работ в качестве типа и входов и выходов будет использоваться тип `logic`, о котором будет рассказано чуть позже.
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
module box(
|
||||
@@ -47,7 +47,7 @@ endmodule
|
||||
|
||||
Внутри модуля могут быть объявления сигналов, параметров, констант и т.п., о которых другой модуль не узнает. Объявим внутри модуля `box` провод `c`.
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
module box(
|
||||
@@ -66,7 +66,7 @@ endmodule
|
||||
|
||||
Подключим провод `c` ко входу `a`. Для этого используется конструкция `assign c = a;`. Такая конструкция называется **непрерывным присваиванием**. Если очень сильно упростить, то непрерывное присваивание схоже со спайкой двух проводов. После подобного присваивания, провод `c` всегда будет иметь то же значение, что и `a` — как только входной сигнал `a` изменит свое значение, внутренний провод `c` также изменит свое значение (проводу `c` будет **непрерывно присваиваться** значение входа `a`).
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
module box(
|
||||
@@ -91,7 +91,7 @@ endmodule
|
||||
|
||||
К примеру, мы можем присвоить проводу `с` значение выхода логического вентиля. Пусть нам нужно, чтобы к сигналу `c` был подключен результат операции `a ИЛИ b`.
|
||||
|
||||

|
||||

|
||||
|
||||
Такую схему можно реализовать следующим описанием:
|
||||
|
||||
@@ -112,7 +112,7 @@ endmodule
|
||||
|
||||
Пусть в схеме имеется ещё один логический вентиль - Исключающее ИЛИ. На него подаётся результат операции `a ИЛИ b`, то есть `c`, а также входной сигнал `b`. Результат операции `c ИСКЛЮЧАЮЩЕЕ ИЛИ b` подаётся на выход `q` нашего модуля.
|
||||
|
||||

|
||||

|
||||
|
||||
```SystemVerilog
|
||||
module box(
|
||||
@@ -182,7 +182,7 @@ endmodule
|
||||
|
||||
Допустим, у нас есть модуль `inv`, который подает на выход инверсию входа, и мы хотим реализовать модуль `top`, который хочет использовать функционал модуля `inv` следующим образом:
|
||||
|
||||

|
||||

|
||||
|
||||
Опишем `inv`:
|
||||
|
||||
@@ -223,7 +223,7 @@ endmodule
|
||||
|
||||
Мы можем подключить сколько угодно экземпляров одного модуля, поэтому у каждого из экземпляра должно быть свое уникальное имя. Пусть `c` подаётся на логический вентиль И вместе со входом `b`. Результат операции И тоже пойдет на инвертор, а затем на выход `q` модуля top.
|
||||
|
||||

|
||||

|
||||
|
||||
Тогда в нашем описании добавится подключение второго модуля `inv` и провод `c`.
|
||||
|
||||
@@ -293,4 +293,4 @@ ___
|
||||
|
||||
Обратите внимание, что вход `a` модуля `top` является двухразрядным: нулевой его бит идет на вход `a` модуля `or`, первый бит идет на вход `b` модуля `or`.
|
||||
|
||||

|
||||

|
||||
|
@@ -4,11 +4,11 @@
|
||||
|
||||
Иными словами, мультиплексор — это переключатель (коммутатор), соединяющий выход с одним из множества входов.
|
||||
|
||||

|
||||

|
||||
|
||||
Для начала создадим простой двухвходовой мультиплексор. Предположим, на `Y` нам необходимо передать один из сигналов — `D0` или `D1` в зависимости от значения управляющего сигнала `S`: когда `S==0`, на `Y` подается сигнал `D0`, в противном случае — `D1`.
|
||||
|
||||

|
||||

|
||||
|
||||
На языке SystemVerilog это можно описать несколькими способами. Первый — с помощью **[тернарного условного оператора](https://ru.wikipedia.org/wiki/Тернарная_условная_операция)**:
|
||||
|
||||
@@ -49,7 +49,7 @@ assign Y = S==1 ? D1 : D0;
|
||||
|
||||
Данное выражение говорит нам, что если `S==1`, то `Y` присваивается значение `D1`, в противном случае — значение `D0`.
|
||||
|
||||

|
||||

|
||||
|
||||
Также мультиплексор можно описать через конструкцию `if-else` в блоке `always`.
|
||||
|
||||
@@ -137,7 +137,7 @@ end // (так же как каждый begin должен ок
|
||||
|
||||
Рассмотрим вариант посложнее и опишем следующую схему:
|
||||
|
||||

|
||||

|
||||
|
||||
Здесь уже используется мультиплексор 4в1. Управляющий сигнал `S` в данном случае двухбитный. В блоке `case` мы перечисляем всевозможные варианты значений `S` и описываем выход мультиплексора.
|
||||
|
||||
@@ -234,7 +234,7 @@ endmodule
|
||||
2. использование конструкции [`if-else`](#блок-if-else) внутри блока `always`;
|
||||
3. использование конструкции [`case`](#case-блок) внутри блока always.
|
||||
3. Во избежание появления [защелок](#защелка) при описании мультиплексора, необходимо убедиться что у блоков `if` есть соответствующие им блоки `else`, а у мультиплексоров описаны все комбинации управляющего сигнала (при необходимости, множество оставшихся комбинаций можно покрыть с помощью комбинации `default`). Появление непреднамеренной защелки в дизайне ведет к ухудшению временных характеристик, избыточному использованию ресурсов, а также непредсказуемому поведению схемы из-за возможного удержания сигнала.
|
||||
4. Важно отметить, что блоки `if-else` и `case` могут использоваться не только для описания мультиплексоров.
|
||||
4. Важно отметить, что блоки `if-else` и `case` могут использоваться не только для описания мультиплексоров.
|
||||
5. Конструкции `if-else` и `case` в рамках данных лабораторных работ можно описывать только внутри блока [`always`](#блок-always). При работе с этим блоком необходимо помнить следующие особенности:
|
||||
1. Существует несколько типов блока `always`: `always_comb`, `always_ff`, `always_latch`, определяющих то, к чему будет подключена описанная в этом блоке логика: проводу, регистру или защелке соответственно.
|
||||
2. Внутри блока always следует использовать оператор неблокирующего присваивания `<=`.
|
||||
@@ -246,4 +246,4 @@ endmodule
|
||||
|
||||
Как, по-вашему, описать на языке SystemVerilog схему, приведённую ниже?
|
||||
|
||||

|
||||

|
||||
|
@@ -6,7 +6,7 @@
|
||||
logic reg_name;
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
У регистра может быть несколько входов и один выход. Основных входов, без которых не может существовать регистр два: вход данных и вход тактирующего синхроимпульса. На рисунке они обозначены как `D` и `clk`. Опциональный вход сигнала сброса (`rst`) позволяет обнулять содержимое регистра вне зависимости от входных данных и может работать как с тактовым синхроимпульсом (синхронный сброс), так и без него (асинхронный сброс).
|
||||
|
||||
@@ -18,11 +18,11 @@ logic reg_name;
|
||||
|
||||
Поскольку все сигналы в цифровой схеме передаются по цепям, удобно представлять, что к выходу регистра всегда неявно подключен провод, с именем, совпадающим с именем регистра, поэтому вы можете использовать имя регистра в дальнейшей цифровой логике:
|
||||
|
||||

|
||||

|
||||
|
||||
Итак, мы добавили регистр на холст схемы, но как соединить его с какой-то логикой? Предположим, у нас есть сигнал тактового синхроимпульса и данные, которые мы хотим записать:
|
||||
|
||||

|
||||

|
||||
|
||||
Данной схеме соответствует код:
|
||||
|
||||
@@ -40,7 +40,7 @@ modulе rеg_ехаmрlе(
|
||||
|
||||
Очевидно, мы хотим подключить сигнал `clk` ко входу тактирующего сигнала регистра, вход `data` ко входу данных, а выход регистра к выходу `reg_data`:
|
||||
|
||||

|
||||

|
||||
|
||||
Запись в регистр возможна только по фронту тактирующего синхроимпульса. **Фронт** — это переход сигнала из нуля в единицу (**положительный фронт**), либо из единицы в ноль (**отрицательный фронт**).
|
||||
|
||||
@@ -116,7 +116,7 @@ modulе rеg_ехаmрlе(
|
||||
|
||||
Итоговая схема регистра со сбросом и сигналом разрешения записи:
|
||||
|
||||

|
||||

|
||||
|
||||
Помимо прочего есть еще одно важное правило, которое необходимо знать при описании регистра:
|
||||
|
||||
@@ -126,7 +126,7 @@ modulе rеg_ехаmрlе(
|
||||
|
||||
В блоке присваивания регистру можно описывать и комбинационную логику, стоящую перед ним, например схему:
|
||||
|
||||

|
||||

|
||||
|
||||
можно описать как
|
||||
|
||||
@@ -214,4 +214,4 @@ modulе rеg_ехаmрlе(
|
||||
|
||||
Как, по-вашему, описать на языке SystemVerilog схему, приведённую ниже?
|
||||
|
||||

|
||||

|
||||
|
Reference in New Issue
Block a user