ЛР2, 12, 15. Изменение в упоминаниях generate блоков

This commit is contained in:
Andrei Solodovnikov
2024-03-18 12:36:18 +03:00
parent 8d2ea38c54
commit d06a561d53
3 changed files with 29 additions and 3 deletions

View File

@@ -62,7 +62,7 @@ _Рисунок 3. Пример исполнения операции АЛУ._
Допустим, ваше устройство должно включить тостер, если на вход ему придет сигнал `32'haf3c5bd0`. Человек, не знакомый с устройством, при прочтении этого кода будет недоумевать, что это за число и почему используется именно оно. Однако, скрыв его за параметром `TOASTER_EN`, читающий поймет, что это код включения тостера. Кроме того, если некоторая константа должна использоваться в нескольких местах кода, то определив её через в виде параметра, можно будет менять её в одном месте, и она тут же поменяется везде.
Параметры позволяют влиять на структуру модуля. К примеру, описывая сумматор, можно параметризовать его разрядность и использовать этот параметр при описании модуля (например, в блоке `generate for`). В этом случае вы сможете создавать множество сумматоров различных разрядностей, подставляя при создании нужное вам значение параметра.
Параметры позволяют влиять на структуру модуля. К примеру, описывая сумматор, можно параметризовать его разрядность и использовать этот параметр при описании модуля (например, в качестве диапазона массива модулей). В этом случае вы сможете создавать множество сумматоров различных разрядностей, подставляя при создании нужное вам значение параметра.
Параметр может быть объявлен в модуле двумя способами:

View File

@@ -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;`, однако в случае реализации верхнего ряда элементов И, подобное многобитное непрерывное присваивание не приведет к синтезу требуемой схемы.
## Практика
Рассмотрим реализацию нашего контроллера прерываний:

View File

@@ -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