ЛР12. Обновление методички

This commit is contained in:
Andrei Solodovnikov
2023-09-22 11:02:58 +03:00
parent 62e8e1a93e
commit e16cb09099
13 changed files with 152 additions and 115 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

View File

@@ -28,7 +28,7 @@
В случае отсутствия **запроса на чтения**, на выход `read_data_o` должно подаваться значение `32'hfa11_1eaf`. Это никак не повлияет на работу процессора, но будет удобно в процессе отладки на временной диаграмме (тоже самое было сделано в процессе разработки памяти данных).
Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение или наоборот), данный запрос должен игнорироваться, а на выходе `read_data_o` должно появиться значение `32'hdead_beef`.
Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно появиться значение `32'hdead_beef`.
К примеру, в случае запроса на чтение по адресу `0x0100004` (четвертый байт в адресном пространстве периферийного устройства "переключатели"), на выходе `read_data_o` должно оказаться значение `32'hdead_beef`. В случае отсутствия запроса на чтение (`req_i == 0` или `write_enable_i == 1`), на выходе `read_data_o` контроллера переключателей должно оказаться значение `32'hfa11_1eaf`.

View File

@@ -18,7 +18,9 @@
## Порядок выполнения работы
1. Интегрируйте модули `csr_controller` и `irq_controller` в модуль `riscv_core`.
1. Обратите внимание, что что в модуле `riscv_core` появились новые входные и выходные сигналы. Эти сигналы должны быть подключены и в модуле `riscv_unit` (просто в виде проводов, которые с другой стороны не подключены ни к чему, в следующей лабораторной мы найдем им применение).
1. Обратите внимание, что что в модуле `riscv_core` появились новые входные и выходные сигналы: `irq_req_i` и `irq_ret_o`. Эти сигналы должны быть использованы при подключении `riscv_core` в модуле `riscv_unit`.
1. На вход `irq_req_i` пока что необходимо подать `32'd0` (в следующей лабораторной это будет изменено).
2. При подключении сигнала `irq_ret_o` можно ничего не указывать (до следующей лабораторной к нему ничего не будет подключено).
2. Большой мультиплексор на схеме, определяющий записываемое в `PC` значение является мультиплексором с приоритетами (в первую очередь проверяется сигнал `trap`, затем, если он равен нулю, проверяется сигнал `mret`, и только если оба предыдущих равны нулю выдается значение `default`). Такой мультиплексор можно описать как на цепочке выражений `if-else-if`, так и с помощью выражения `case` в качестве управляющего сигнала которого подана единица, а выбор осуществляется не по значениям, а по сигналам:
```SystemVerilog

View File

@@ -1,4 +1,4 @@
# Лабораторная работа 7 "Периферийные устройства"
# Лабораторная работа 12 "Периферийные устройства"
На прошлой лабораторной работе вы реализовали свой собственный RISC-V процессор. Однако пока что он находится "в вакууме" и никак не связан с внешним миром. Для исправления этого недостатка вами будет реализована системная шина, через которую к процессору смогут подключаться различные периферийные устройства.
@@ -35,15 +35,15 @@
### Адресное пространство
Архитектура RISC-V подразумевает использование совместного адресного пространства, это значит, что в лабораторной работе будет использована единая шина для подключения памяти и регистров управления периферийными устройствами. При обращении по одному диапазону адресов процессор будет
попадать в память, при обращении по другим взаимодействовать с регистрами управления/статуса периферийного устройства. Например, можно разделить 32-битное адресное пространство на 256 частей, отдав старшие 8 бит адреса под указание конкретного периферийного устройства. Тогда каждое из периферийных устройств получит 24-битное адресное пространство (16 MiB). Допустим, мы распределили эти части адресного пространства в следующем порядке (от младшего диапазона адресов к старшему):
Архитектура RISC-V подразумевает использование совместного адресного пространства, это значит, что в лабораторной работе будет использована единая шина для подключения памяти и регистров управления периферийными устройствами. При обращении по одному диапазону адресов процессор будет попадать в память, при обращении по другим взаимодействовать с регистрами управления/статуса периферийного устройства. Например, можно разделить 32-битное адресное пространство на 256 частей, отдав старшие 8 бит адреса под указание конкретного периферийного устройства. Тогда каждое из периферийных устройств получит 24-битное адресное пространство (16 MiB). Допустим, мы распределили эти части адресного пространства в следующем порядке (от младшего диапазона адресов к старшему):
0. Переключатели
1. Светодиоды
2. Клавиатура PS/2
3. Семисегментные индикаторы
4. UART-приемник
5. UART-передатчик
0. Память данных
1. Переключатели
2. Светодиоды
3. Клавиатура PS/2
4. Семисегментные индикаторы
5. UART-приемник
6. UART-передатчик
В таком случае, если мы захотим обратиться в четвертый регистр семисегментных индикаторов, мы должны будем использовать адрес `0x03000004`. Старшие 8 бит (`0x03`) определяют выбранное периферийное устройство, оставшиеся 24 бита определяют конкретный адрес в адресном пространстве этого устройства.
@@ -51,11 +51,13 @@
![../../.pic/Labs/lab_12_periph/fig_01.drawio.png](../../.pic/Labs/lab_12_periph/fig_01.drawio.png)
_Рисунок 1. Итоговая структура процессорной системы_
### Активация выбранного устройства
В зависимости от интерфейса используемой шины, периферийные устройства либо знают какой диапазон адресов им выделен (например, в интерфейсе I²C), либо нет (интерфейс APB). В первом случае, устройство понимает что к нему обратились непосредственно по адресу в данном обращении, во втором случае — по специальному сигналу.
На приведенной выше схеме используется второй вариант — устройство понимает, что к нему обратились по специальному сигналу `req_i`. Данный сигнал формируется из двух частей: сигнала `req` исходящего из процессорного ядра (сигнал о том, обращение в память вообще происходит) и специального сигнала-селектора исходящего из 256-разрядной шины. Формирование значения на этой шине происходит с помощью [унитарного](https://ru.wikipedia.org/wiki/Унитарный_код) ([one-hot](https://en.wikipedia.org/wiki/One-hot)) кодирования. Процесс кодирования достаточно прост. В любой момент времени на выходной шине должен быть **ровно один** бит, равный единице. Индекс этого бита совпадает со значением старших восьми бит адреса. Поскольку для восьмибитного значения существует 256 комбинаций значений, именно такая разрядность будет на выходе кодировщика. Это означает, что в данной системе можно связать процессор с 256 устройствами (одним из которых будет память данных).
На _рис. 1_ используется второй вариант — устройство понимает, что к нему обратились по специальному сигналу `req_i`. Данный сигнал формируется из двух частей: сигнала `req` исходящего из процессорного ядра (сигнал о том, обращение в память вообще происходит) и специального сигнала-селектора исходящего из 256-разрядной шины. Формирование значения на этой шине происходит с помощью [унитарного](https://ru.wikipedia.org/wiki/Унитарный_код) ([one-hot](https://en.wikipedia.org/wiki/One-hot)) кодирования. Процесс кодирования достаточно прост. В любой момент времени на выходной шине должен быть **ровно один** бит, равный единице. Индекс этого бита совпадает со значением старших восьми бит адреса. Поскольку для восьмибитного значения существует 256 комбинаций значений, именно такая разрядность будет на выходе кодировщика. Это означает, что в данной системе можно связать процессор с 256 устройствами (одним из которых будет память данных).
Реализация такого кодирования предельно проста:
@@ -64,7 +66,7 @@
* ...
* Двести пятьдесят пятый бит шины будет равен единице только если `data_addr_o[31:24] = 8'd255`.
Для реализации такого кодирования достаточно выполнить сдвиг влево `255'd1` на значение `data_addr_o[31:24]`.
Для реализации такого кодирования достаточно выполнить сдвиг влево константы `255'd1` на значение `data_addr_o[31:24]`.
### Дополнительные правки модуля riscv_unit
@@ -91,7 +93,7 @@ module riscv_unit(
endmodule
```
Эти входы порты подключены к одноименным портам ваших контроллеров периферии (речь идет только о реализуемых вами контроллерах, остальные порты должны остаться неподключенными).
Эти порты подключены к одноименным портам ваших контроллеров периферии (речь идет только о реализуемых вами контроллерах, остальные порты должны остаться неподключенными).
Обратите внимание на то, что изменился сигнал сброса (`resetn_i`). Буква `n` на конце означает, что сброс работает по уровню `0` (когда сигнал равен нулю — это сброс, когда единице — не сброс).
@@ -99,8 +101,8 @@ endmodule
Для этого необходимо:
1. Подключить файл [`sys_clk_rst_gen.v`](sys_clk_rst_gen.v) в ваш проект.
2. Подключить этот модуль внутри `riscv_unit` следующим образом:
1. Подключить файл [`sys_clk_rst_gen.sv`](sys_clk_rst_gen.sv) в ваш проект.
2. Подключить этот модуль в начале описания модуля `riscv_unit` следующим образом:
```SystemVerilog
logic sysclk, rst;
@@ -113,19 +115,19 @@ sys_clk_rst_gen divider(.ex_clk_i(clk_i),.ex_areset_n_i(resetn_i),.div_i(10),.sy
## Задание
В рамках данной лабораторной работы необходимо реализовать модули-контроллеры двух периферийных устройств, реализующих управление в соответствии с приведенной ниже картой памяти и встроить их в процессорную систему, используя используя схему приведенную выше. На карте приведено шесть периферийных устройств, вам необходимо взять только два из них в зависимости от вашего варианта индивидуального задания (ИЗ) по следующему правилу:
В рамках данной лабораторной работы необходимо реализовать модули-контроллеры двух периферийных устройств, реализующих управление в соответствии с приведенной ниже картой памяти и встроить их в процессорную систему, используя используя [_рис. 1_](../../.pic/Labs/lab_12_periph/fig_01.drawio.png). На карте приведено шесть периферийных устройств, вам необходимо взять только два из них в зависимости от вашего варианта индивидуального задания (ИЗ) по следующему правилу:
1. Те кому достались варианты ИЗ 1-5 должны реализовать контроллеры переключателей и светодиодов.
2. Те кому достались варианты ИЗ 6-15 должны реализовать контроллеры клавиатуры PS/2 и семисегментных индикаторов.
3. Те кому достались варианты BP 16-29 должны реализовать контроллеры приемника и передатчика UART.
![Карта памяти](../../.pic/Labs/riscv_periph_memory_map.png)
![Карта памяти](../../.pic/Labs/lab_12_periph/fig_02.png)
Работа с картой осуществляется следующим образом. Под названием каждого периферийного устройства указана старшая часть адреса (чему должны быть равны старшие 8 бит адреса, чтобы было сформировано обращение к данному периферийному устройству). Например, для переключателей это значение равно `0x01`, для светодиодов `0x02` и т.п.
В самом левом столбце указаны используемые/неиспользуемые адреса в адресном пространстве данного периферийного устройства. Например для переключателей есть только один используемый адрес: `0x000000`. Его функциональное назначение и разрешения на доступ указаны в столбце соответствующего периферийного устройства. Возвращаясь к адресу `0x000000` для переключателей мы видим следующее:
* (R) означает что разрешен доступ только на чтение (операция записи по этому адресу должна игнорироваться вашим контроллером).
* "Выставленное на переключателях значение" означает ровно то что и означает. Если процессор выполняет операцию чтения по адресу 0x01000000 (`0x01` (старшая часть адреса переключателей) + `0x000000` (младшая часть адреса для получения выставленного на переключателях значения) ), то контроллер должен выставить на выходной сигнал RD значение на переключателях (о том как получить это значение будет рассказано чуть позже).
* **(R)** означает что разрешен доступ только на чтение (операция записи по этому адресу должна игнорироваться вашим контроллером).
* **"Выставленное на переключателях значение"** означает ровно то что и означает. Если процессор выполняет операцию чтения по адресу `0x01000000` (`0x01` (старшая часть адреса переключателей) + `0x000000` (младшая часть адреса для получения выставленного на переключателях значения) ), то контроллер должен выставить на выходной сигнал `RD` значение на переключателях (о том как получить это значение будет рассказано чуть позже).
Рассмотрим еще один пример. При обращении по адресу `0x02000024` (`0x02` (старшая часть адреса контроллера светодиодов) + `0x000024` (младшая часть адреса для доступа на запись к регистру сброса) ) должна произойти запись в регистр сброса, который должен сбросить значения в регистре управления зажигаемых светодиодов и регистре управления режимом "моргания" светодиодов (подробнее о том как должны работать эти регистры будет ниже).
@@ -145,14 +147,15 @@ sys_clk_rst_gen divider(.ex_clk_i(clk_i),.ex_areset_n_i(resetn_i),.div_i(10),.sy
3. Реализуйте модули контроллеров периферии. Имена модулей и их порты будут указаны в [описании контроллеров](#описание-контроллеров-периферийных-устройств). Пример разработки контроллера приведен [здесь](../../Basic%20Verilog%20structures/Controllers.md).
4. Обновите модуль `riscv_unit` в соответствии с разделом ["Дополнительные правки модуля riscv_unit"](#дополнительные-правки-модуля-riscv_unit).
1. Подключите в проект файл `sys_clk_rst_gen.sv`.
2. Добавьте в модуль `riscv_unit` входы и выходы периферии.
3. Подключите к модулю `riscv_unit` модуль `sys_clk_rst_gen` скопировав приведенный фрагмент кода.
2. Добавьте в модуль `riscv_unit` входы и выходы периферии. Необходимо добавить порты даже тех периферийных устройств, которые вы не будете реализовывать.
3. Создайте в начале описания модуля `riscv_unit` экземпляр модуля `sys_clk_rst_gen`, скопировав приведенный фрагмент кода.
4. Замените подключение тактового сигнала исходных подмодулей `riscv_unit` на появившийся сигнал `sysclk`. Убедитесь, что на модули имеющие сигнал сброса приходит сигнал `rst`.
5. Интегрируйте модули контроллеров периферии в процессорную систему по приведенной схеме руководствуясь старшими адресами контроллеров, представленными на карте памяти. Это означает, что если вы реализуете контроллер светодиодов, на его входов `req_i` должна подаваться единица в случае если `mem_req_o == 1` и старшие 8 бит адреса равны `0x02`.
5. Интегрируйте модули контроллеров периферии в процессорную систему по приведенной схеме руководствуясь старшими адресами контроллеров, представленными на карте памяти ([_рис. 2_](../../.pic/Labs/lab_12_periph/fig_02.png)). Это означает, что если вы реализуете контроллер светодиодов, на его вход `req_i` должна подаваться единица в случае если `mem_req_o == 1` и старшие 8 бит адреса равны `0x02`.
1. При интеграции вы должны подключить только модули-контроллеры вашего варианта. Контроллеры периферии других вариантов подключать не надо.
2. При этом во время интеграции, вы должны использовать старшую часть адреса, представленную в карте памяти для формирования сигнала `req_i` для ваших модулей-контроллеров.
3. Даже если вы не используете какие-то входные/выходные сигналы в модуле `riscv_unit` (например по варианту вам не достался контроллер клавиатуры и поэтому вы не используете сигналы `kclk_i` и `kdata_i`), вы все равно должны их описать во входах и выходах модуля `riscv_unit`.
6. Проинициализируйте память инструкций с помощью предоставленной для каждой пары контроллеров программы.
6. Проверьте работу процессорной системы с помощью моделирования.
1. Для каждой пары контроллеров периферии предложено две программы: с обновлением данных по опросу и по прерываниям. Запустите моделирование сначала для одной программы, затем для другой (для этого необходимо обновить файл, инициализирующий память инструкций). После проверки работоспособности процессора, сравните поведение сигналов LSU для этих программ.
7. Подключите к проекту файл ограничений ([nexys_a7_100t.xdc](nexys_a7_100t.xdc)), если тот еще не был подключен, либо замените его содержимое данными из файла к этой лабораторной работе.
8. Проверьте работу вашей процессорной системы с помощью отладочного стенда с ПЛИС и (при соответствующем варианте) клавиатуры/рабочего компьютера.
1. Обратите внимание, что в данной лабораторной уже не будет модуля верхнего уровня `nexys_...`, так как ваш модуль процессорной системы уже полностью самостоятелен и взаимодействует непосредственно с ножками ПЛИС через модули, управляемые контроллерами периферии.
@@ -183,7 +186,7 @@ sys_clk_rst_gen divider(.ex_clk_i(clk_i),.ex_areset_n_i(resetn_i),.div_i(10),.sy
В случае отсутствия **запроса на чтения**, на выход `read_data_o` должно подаваться значение `32'hfa11_1eaf`. Это никак не повлияет на работу процессора, но будет удобно в процессе отладки на временной диаграмме (тоже самое было сделано в процессе разработки памяти данных).
Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение или наоборот), данный запрос должен игнорироваться, а на выходе `read_data_o` должно появиться значение `32'hdead_beef`.
Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно появиться значение `32'hdead_beef`.
К примеру, в случае запроса на чтение по адресу `0x0100004` (четвертый байт в адресном пространстве периферийного устройства "переключатели"), на выходе `read_data_o` должно оказаться значение `32'hdead_beef`. В случае отсутствия запроса на чтение (`req_i == 0` или `write_enable_i == 1`), на выходе `read_data_o` контроллера переключателей должно оказаться значение `32'hfa11_1eaf`.
@@ -201,7 +204,7 @@ module sw_sb_ctrl(
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i
input logic rst_i,
input logic req_i,
input logic write_enable_i,
input logic [31:0] addr_i,
@@ -237,7 +240,7 @@ module led_sb_ctrl(
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i
input logic rst_i,
input logic req_i,
input logic write_enable_i,
input logic [31:0] addr_i,
@@ -318,7 +321,7 @@ logic scan_code_is_unread;
endmodule
```
В первую очередь, вы должны инстанциировать модуль `PS2Receiver` внутри вашего модуля-контроллера, соединив соответствующие входы. Для подключения к выходам необходимо создать дополнительные провода.
В первую очередь, вы должны создать экземпляр модуля `PS2Receiver` внутри вашего модуля-контроллера, соединив соответствующие входы. Для подключения к выходам необходимо создать дополнительные провода.
По каждому восходящему фронту сигнала `clk_i` вы должны проверять выход `keycode_valid_o` и если тот равен единице, записать значение с выхода `keycode_o` в регистр `scan_code`. При этом значение регистра `scan_code_is_unread` необходимо выставить в единицу.
@@ -355,7 +358,7 @@ module hex_digits(
input logic [7:0] bitmask_i, // Битовая маска для включения/отключения
// отдельных индикаторов
output logic [6:0] hex_led_o // Сигнал, контролирующий каждый отдельный
output logic [6:0] hex_led_o, // Сигнал, контролирующий каждый отдельный
// светодиод индикатора
output logic [7:0] hex_sel_o // Сигнал, указывающий на какой индикатор
// выставляется hex_led
@@ -408,14 +411,14 @@ endmodule
|Адрес|Режим доступа|Допустимые значения| Функциональное назначение |
|-----|-------------|-------------------|---------------------------------------------------------|
|0x00 | RW | [0:31] | Регистр, хранящий значение, выводимое на hex0 |
|0x04 | RW | [0:31] | Регистр, хранящий значение, выводимое на hex1 |
|0x08 | RW | [0:31] | Регистр, хранящий значение, выводимое на hex2 |
|0x0C | RW | [0:31] | Регистр, хранящий значение, выводимое на hex3 |
|0x10 | RW | [0:31] | Регистр, хранящий значение, выводимое на hex4 |
|0x14 | RW | [0:31] | Регистр, хранящий значение, выводимое на hex5 |
|0x18 | RW | [0:31] | Регистр, хранящий значение, выводимое на hex6 |
|0x1C | RW | [0:31] | Регистр, хранящий значение, выводимое на hex7 |
|0x00 | RW | [0:15] | Регистр, хранящий значение, выводимое на hex0 |
|0x04 | RW | [0:15] | Регистр, хранящий значение, выводимое на hex1 |
|0x08 | RW | [0:15] | Регистр, хранящий значение, выводимое на hex2 |
|0x0C | RW | [0:15] | Регистр, хранящий значение, выводимое на hex3 |
|0x10 | RW | [0:15] | Регистр, хранящий значение, выводимое на hex4 |
|0x14 | RW | [0:15] | Регистр, хранящий значение, выводимое на hex5 |
|0x18 | RW | [0:15] | Регистр, хранящий значение, выводимое на hex6 |
|0x1C | RW | [0:15] | Регистр, хранящий значение, выводимое на hex7 |
|0x20 | RW | [0:255] | Регистр, управляющий включением/отключением индикаторов |
|0x24 | W | 1 | Запись сигнала сброса |
@@ -472,7 +475,7 @@ module uart_rx_sb_ctrl(
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i
input logic rst_i,
input logic [31:0] addr_i,
input logic req_i,
input logic [31:0] write_data_i,
@@ -502,7 +505,7 @@ module uart_tx_sb_ctrl(
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i
input logic rst_i,
input logic [31:0] addr_i,
input logic req_i,
input logic [31:0] write_data_i,

View File

@@ -1,21 +0,0 @@
93 04 10 00
13 09 a0 0a
93 02 a0 0a
13 19 89 00
33 09 59 00
93 09 50 55
93 02 50 00
93 99 49 00
b3 89 59 00
37 0e 00 01
b7 0e 00 02
03 2a 0e 00
63 0a 2a 01
63 0c 3a 01
23 a0 4e 01
23 a2 0e 00
ef f2 df fe
23 a2 9e 02
ef f2 5f fe
23 a2 9e 00
ef f2 df fd

View File

@@ -0,0 +1,32 @@
01400293
30529073
00200293
30429073
00000063
34202373
00200393
06731063
01000337
00032383
0000BE37
AAAE0E13
01C39463
FCDFF06F
00005E37
555E0E13
01C38A63
02000E37
007E2023
000E2223
02C0006F
02000E37
004E0E13
00100E93
01DE2023
0180006F
02000E37
024E0E13
00100E93
01DE2023
0040006F
30200073

View File

@@ -0,0 +1,21 @@
00100493
0aa00913
0aa00293
00891913
00590933
55500993
00500293
00499993
005989b3
01000e37
02000eb7
000e2a03
012a0a63
013a0c63
014ea023
000ea223
fedff2ef
029ea223
fe5ff2ef
009ea223
fddff2ef

View File

@@ -0,0 +1,54 @@
module sys_clk_rst_gen#(
parameter DIV_WIDTH = 4
)(
input logic ex_clk_i,
input logic ex_areset_n_i,
input logic [DIV_WIDTH-1:0] div_i,
output logic sys_clk_o,
output logic sys_reset_o
);
logic [1:0] ex_arstn_buf;
logic [1:0] sys_rstn_buf;
logic ex_arstn_buffered;
assign ex_arstn_buffered = ex_arstn_buf[1];
assign sys_reset_o = !sys_rstn_buf[1];
always_ff @(posedge ex_clk_i or negedge ex_areset_n_i) begin
if(!ex_areset_n_i) begin
ex_arstn_buf <= 2'b0;
end
else begin
ex_arstn_buf <= {ex_arstn_buf[0], 1'b1};
end
end
logic [DIV_WIDTH-1:0] cnt;
logic clk_div;
always_ff @(posedge ex_clk_i or negedge ex_arstn_buffered) begin
if ( ~ex_arstn_buffered ) begin
cnt <= 0;
clk_div <= 0;
end else if ( cnt == 0 ) begin
cnt <= div_i;
clk_div <= !clk_div;
end else begin
cnt <= cnt - 1;
end
end
BUFG clkbuf (.O(sys_clk_o),.I(clk_div));
always_ff @(posedge sys_clk_o or negedge ex_arstn_buffered) begin
if(!ex_arstn_buffered) begin
sys_rstn_buf <= 2'b0;
end
else begin
sys_rstn_buf <= {sys_rstn_buf[0], 1'b1};
end
end
endmodule

View File

@@ -1,54 +0,0 @@
module sys_clk_rst_gen#(
parameter DIV_WIDTH = 4
)(
input ex_clk_i,
input ex_areset_n_i,
input [DIV_WIDTH-1:0] div_i,
output sys_clk_o,
output sys_reset_o
);
reg [1:0] ex_arstn_buf;
reg [1:0] sys_rstn_buf;
wire ex_arstn_buffered;
assign ex_arstn_buffered = ex_arstn_buf[1];
assign sys_reset_o = !sys_rstn_buf[1];
always @(posedge ex_clk_i or negedge ex_areset_n_i) begin
if(!ex_areset_n_i) begin
ex_arstn_buf <= 2'b0;
end
else begin
ex_arstn_buf <= {ex_arstn_buf[0], 1'b1};
end
end
reg [DIV_WIDTH-1:0] cnt;
reg clk_div;
always@( posedge ex_clk_i or negedge ex_arstn_buffered ) begin
if ( ~ex_arstn_buffered ) begin
cnt <= 0;
clk_div <= 0;
end else if ( cnt == 0 ) begin
cnt <= div_i;
clk_div <= !clk_div;
end else begin
cnt <= cnt - 1;
end
end
BUFG clkbuf (.O(sys_clk_o),.I(clk_div));
always @(posedge sys_clk_o or negedge ex_arstn_buffered) begin
if(!ex_arstn_buffered) begin
sys_rstn_buf <= 2'b0;
end
else begin
sys_rstn_buf <= {sys_rstn_buf[0], 1'b1};
end
end
endmodule

View File

@@ -1,4 +1,4 @@
# Лабораторная работа 8 "Высокоуровневое программирование"
# Лабораторная работа 13 "Высокоуровневое программирование"
## Цель