mirror of
https://github.com/MPSU/APS.git
synced 2025-09-16 17:40:41 +00:00
Merge pull request #73 from MPSU/module_array_ref
ЛР1. Замена generate на массив модулей
This commit is contained in:
Binary file not shown.
Before Width: | Height: | Size: 52 KiB |
@@ -239,9 +239,21 @@ module fulladder(
|
||||
);
|
||||
```
|
||||
|
||||
Далее, вам необходимо реализовать полный 32-разрядный сумматор. Соединять вручную 32 однотипных модуля чревато усталостью и ошибками, поэтому можно сначала создать 4-разрядный сумматор (либо другой разрядности), а затем из набора 4-разрядных сумматоров сделать 32-битный.
|
||||
Далее, вам необходимо реализовать полный 32-разрядный сумматор со следующим прототипом:
|
||||
|
||||
Модуль должен быть описан в соответствии со следующим прототипом:
|
||||
```systemverilog
|
||||
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
|
||||
);
|
||||
```
|
||||
|
||||
Соединять вручную 32 однотипных модуля чревато усталостью и ошибками, поэтому можно сначала создать 4-разрядный сумматор (либо другой разрядности), а затем из набора 4-разрядных сумматоров сделать 32-битный.
|
||||
|
||||
Если вы решите делать 4-разрядный сумматор, то модуль должен быть описан в соответствии со следующим прототипом:
|
||||
|
||||
```SystemVerilog
|
||||
module fulladder4(
|
||||
@@ -253,38 +265,61 @@ module fulladder4(
|
||||
);
|
||||
```
|
||||
|
||||
Либо же можно воспользоваться конструкцией `generate for`, пример использования которой вы можете увидеть на изображении ниже (так же существуют конструкции `generate if`, `generate case`).
|
||||
либо же можно создать массив однобитных сумматоров.
|
||||
|
||||

|
||||
Создание массива модулей схоже с созданием одного модуля за исключением того, что после имени сущности модуля указывается диапазон, определяющий количество модулей в массиве. При этом подключение сигналов к массиву модулей осуществляется следующим образом:
|
||||
|
||||
_Рисунок 7. Пример использования конструкции generate for._
|
||||
- если разрядность подключаемого сигнала совпадает с разрядностью порта модуля из массива, этот сигнал подключается к каждому из модулей в массиве;
|
||||
- если разрядность подключаемого сигнала превосходит разрядность порта модуля из массива в `N` раз (где `N` — количество модулей в массиве), к модулю подключается соответствующий диапазон бит подключаемого сигнала (диапазон младших бит будет подключен к модулю с меньшим индексом в массиве).
|
||||
- если разрядность подключаемого сигнала не подходит ни под один из описанных выше пунктов, происходит ошибка синтеза схемы, поскольку в этом случае САПР не способен понять каким образом подключать данный сигнал к каждому модулю из массива.
|
||||
|
||||
Как вы можете догадаться, в этом примере создано 3 модуля, имена которых оканчиваются на значение итератора, по которому шел цикл, а к самим модулям подключены соответствующие итератору провода из шин. Разумеется, для своих целей вы можете использовать и **i+1** и двойные циклы.
|
||||
Далее идет пример того, как можно создать массив модулей:
|
||||
|
||||
Обратите внимание на `: newgen` стоящий после ключевого слова `begin`. В некоторых САПР, код может не собраться, если у конструкции `generate for` нет названия (**лейбла**) с помощью подобной записи (двоеточия и названия).
|
||||
|
||||
**Обратите внимание**, что данный рисунок не является решением вашей задачи, поскольку у вашего сумматора три входа и два выхода, а у сумматора в примере нет бита переноса.
|
||||
|
||||
Несмотря на то, что конструкция выглядит как [~~утка, плавает как утка и крякает как утка~~](https://ru.wikipedia.org/wiki/Утиный_тест) цикл и ведет себя как цикл, нужно понимать, что **это не цикл в привычном вам понимании этого слова**. Это по-прежнему не программа. Вместо этого, вы выделяете общую закономерность по размещению однотипных модулей на схеме и описываете эту закономерность в виде цикла.
|
||||
|
||||
Если вы захотите воспользоваться этой конструкцией, вам будет нужно продумать как вы будете:
|
||||
|
||||
1. соединять входной бит переноса вашего модуля с входным битом переноса нулевого сумматора;
|
||||
2. передавать бит переноса с выхода предыдущего сумматора на вход следующего;
|
||||
3. соединять выходной бит переноса вашего модуля с выходным битом переноса последнего однобитного сумматора.
|
||||
|
||||
Далее идет пример того, как должен выглядеть заголовок модуля разрабатываемого устройства.
|
||||
|
||||
```systemverilog
|
||||
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
|
||||
```SystemVerilog
|
||||
module example1(
|
||||
input logic [3:0] a,
|
||||
input logic b,
|
||||
output logic c,
|
||||
output logic d
|
||||
);
|
||||
|
||||
assign c = |a ^ b;
|
||||
assign d = &a;
|
||||
|
||||
endmodule
|
||||
|
||||
module example2(
|
||||
input logic [31:0] A,
|
||||
input logic B,
|
||||
output logic [ 8:0] C
|
||||
);
|
||||
|
||||
example1 instance_array[7:0]( // Создается массив из 8 модулей example1
|
||||
.a(A), // Поскольку разрядность сигнала A в 8 раз больше
|
||||
// разрядности входа a, к каждому модулю в массиве
|
||||
// будет подключен свой диапазон бит сигнала A
|
||||
// (к instance_array[0] будет подключен диапазон
|
||||
// A[3:0], к instance_array[7] будет подключен
|
||||
// диапазон A[31:28]).
|
||||
|
||||
.b(B) // Поскольку разрядность сигнала B совпадает с
|
||||
// разрядностью входа b, сигнал B будет подключен
|
||||
// как есть ко всем модулям в массиве.
|
||||
|
||||
.c(C[7:0]) // Поскольку разрядность сигнала C не равна
|
||||
// ни разрядности входа c, ни его увосьмиренной
|
||||
// разрядности, мы должны выбрать такой диапазон
|
||||
// бит, который будет удовлетворять одному из
|
||||
// этих требований.
|
||||
|
||||
.d(C[8]) // Аналогично предыдущему.
|
||||
);
|
||||
endmodule
|
||||
```
|
||||
|
||||
_Листинг 3. Пример создания массива модулей._
|
||||
|
||||
|
||||
### Порядок выполнения задания
|
||||
|
||||
1. Создайте проект, согласно [руководству по созданию проекта в Vivado](../../Vivado%20Basics/Vivado%20trainer.md)
|
||||
@@ -305,7 +340,7 @@ module fulladder32(
|
||||
4. Проверьте содержимое TCL-консоли. Убедитесь в появлении сообщения о завершении теста. В случае, если в tcl-консоли написано `CLICK THE BUTTON 'Run All'`, вам необходимо нажать соответствующую кнопку на панели моделирования.
|
||||
5. Убедитесь по сигналам временной диаграммы, что модуль работает корректно.
|
||||
8. В `Design Sources` проекта создайте `SystemVerilog`-файл `fulladder32`.
|
||||
9. Опишите модуль `fulladder32` так, чтобы в нем выполнялось поразрядное сложение двух 32-разрядных чисел и входного бита переноса. Его можно реализовать через последовательное соединение восьми 4-битных сумматоров, либо же можно соединить 32 однобитных сумматора (как вручную, так и с помощью конструкции `generate for`).
|
||||
9. Опишите модуль `fulladder32` так, чтобы в нем выполнялось поразрядное сложение двух 32-разрядных чисел и входного бита переноса. Его можно реализовать через последовательное соединение восьми 4-битных сумматоров, либо же можно соединить 32 однобитных сумматора (как вручную, так и с создания массива модулей).
|
||||
1. Обратите внимание, что входной бит переноса должен подаваться на сумматор, выполняющий сложение нулевого разряда, выходной бит переноса соединяется с выходным битом переноса сумматора, выполняющего сложение 31-го разряда.
|
||||
10. Проверьте 32-битный сумматор. Для этого:
|
||||
1. В `Simulation Sources` проекта создайте `SystemVerilog`-файл `tb_fulladder32`.
|
||||
|
@@ -62,7 +62,7 @@ _Рисунок 3. Пример исполнения операции АЛУ._
|
||||
|
||||
Допустим, ваше устройство должно включить тостер, если на вход ему придет сигнал `32'haf3c5bd0`. Человек, не знакомый с устройством, при прочтении этого кода будет недоумевать, что это за число и почему используется именно оно. Однако, скрыв его за параметром `TOASTER_EN`, читающий поймет, что это код включения тостера. Кроме того, если некоторая константа должна использоваться в нескольких местах кода, то определив её через в виде параметра, можно будет менять её в одном месте, и она тут же поменяется везде.
|
||||
|
||||
Параметры позволяют влиять на структуру модуля. К примеру, описывая сумматор, можно параметризовать его разрядность и использовать этот параметр при описании модуля (например, в блоке `generate for`). В этом случае вы сможете создавать множество сумматоров различных разрядностей, подставляя при создании нужное вам значение параметра.
|
||||
Параметры позволяют влиять на структуру модуля. К примеру, описывая сумматор, можно параметризовать его разрядность и использовать этот параметр при описании модуля (например, в качестве диапазона массива модулей). В этом случае вы сможете создавать множество сумматоров различных разрядностей, подставляя при создании нужное вам значение параметра.
|
||||
|
||||
Параметр может быть объявлен в модуле двумя способами:
|
||||
|
||||
|
@@ -17,10 +17,30 @@ _Рисунок 1. Структурная схема daisy chain._
|
||||
|
||||
Данная схема состоит из двух массивов элементов И. Первый массив (верхний ряд элементов) формирует многоразрядный сигнал (назовем его для определенности `ready`, на _рис. 1_ он обозначен как "_Приоритет_"), который перемножается с запросами с помощью массива элементов И нижнего ряда, формируя многоразрядный сигнал `y`. Обратите внимание на то, что результат операции И на очередном элементе нижнего массива влияет на результат И следующего за ним элемента верхнего массива и наоборот (`readyₙ₊₁` зависит от `yₙ`, в то время как `yₙ` зависит от `readyₙ`). Как только на одном из разрядов `y` появится значение `1`, оно сразу же распространится в виде `0` по всем оставшимся последующим разрядам `ready`, обнуляя их. А обнулившись, разряды `ready` обнулят соответствующие разряды `y` (нулевые разряды `ready` запрещают генерацию прерывания для соответствующих разрядов `y`).
|
||||
|
||||
Для описания верхнего ряда элементов И на языке SystemVerilog будет удобно воспользоваться конструкцией `generate for`, о которой рассказывалось в [ЛР 1 "Сумматор"](../01.%20Adder#Задание) (необходимо сделать непрерывное присваивание `readyₙ & !yₙ` для `n+1`-ого бита `ready`).
|
||||
|
||||
Нижний массив элементов И можно описать через непрерывное присваивание побитового И между `ready` и сигналом запросов на прерывание.
|
||||
|
||||
Для описания верхнего ряда элементов И вам будет необходимо сделать непрерывное присваивание `readyₙ & !yₙ` для `n+1`-ого бита `ready`. Для этого будет удобно воспользоваться конструкцией `generate for`, которая позволяет автоматизировать создание множества однотипных структур.
|
||||
|
||||
Рассмотрим принцип работы этой конструкции. Предположим, мы хотим создать побитовое присваивание 5-битного сигнала `a` 5-битному сигналу `b`.
|
||||
|
||||
Индексы, используемые конструкцией, должны быть объявлены с помощью ключевого слова `genvar`. Далее, в области, ограниченной ключевыми словами `generate`/`endgenerate` описывается цикл присваиваний / созданий модулей:
|
||||
|
||||
```SystemVerilog
|
||||
logic [4:0] a;
|
||||
logic [4:0] b;
|
||||
|
||||
// ...
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for(i = 0; i < 5; i++) begin
|
||||
assign a[i] = b[i];
|
||||
end
|
||||
endgenerate
|
||||
```
|
||||
|
||||
Разумеется в этом примере можно было бы просто сделать одно непрерывное присваивание `assign a = b;`, однако в случае реализации верхнего ряда элементов И, подобное многобитное непрерывное присваивание не приведет к синтезу требуемой схемы.
|
||||
|
||||
## Практика
|
||||
|
||||
Рассмотрим реализацию нашего контроллера прерываний:
|
||||
|
@@ -287,6 +287,12 @@ localparam FLASH_MSG_SIZE = 57;
|
||||
localparam ACK_MSG_SIZE = 4;
|
||||
|
||||
logic [7:0] [7:0] flash_size_ascii, flash_addr_ascii;
|
||||
// Блок generate позволяет создавать структуры модуля цикличным или условным
|
||||
// образом. В данном случае, при описании непрерывных присваиваний была
|
||||
// обнаружена закономерность, позволяющая описать четверки присваиваний в более
|
||||
// общем виде, который был описан в виде цикла.
|
||||
// Важно понимать, данный цикл лишь автоматизирует описание присваиваний и во
|
||||
// время синтеза схемы развернется в четыре четверки непрерывных присваиваний.
|
||||
genvar i;
|
||||
generate
|
||||
for(i=0; i < 4; i=i+1) begin
|
||||
|
Reference in New Issue
Block a user