ЛР13. Рефактор методички

This commit is contained in:
Andrei Solodovnikov
2024-07-22 11:54:52 +03:00
parent 6cff6abc12
commit 9aa0d2d5e5

View File

@@ -1,6 +1,6 @@
# Лабораторная работа 13 "Периферийные устройства"
На прошлой лабораторной работе вы реализовали свой собственный RISC-V процессор. Однако пока что он находится "в вакууме" и никак не связан с внешним миром. Для исправления этого недостатка вами будет реализована системная шина, через которую к процессору смогут подключаться различные периферийные устройства.
В [ЛР№11](../11.%20Interrupt%20integration/) вы закончили реализовывать свой собственный RISC-V процессор. Однако пока что он находится "в вакууме" и никак не связан с внешним миром. Для исправления этого недостатка вами будет реализована системная шина, через которую к процессору смогут подключаться различные периферийные устройства.
## Цель
@@ -12,8 +12,8 @@
Для успешного выполнения лабораторной работы, вам необходимо:
* ознакомиться с [примером описания модуля-контроллера](../../Basic%20Verilog%20structures/Controllers.md);
* ознакомиться с [описанием](#описание-контроллеров-периферийных-устройств) контроллеров периферийных устройств.
- ознакомиться с [примером описания модуля-контроллера](../../Basic%20Verilog%20structures/Controllers.md);
- ознакомиться с [описанием](#описание-контроллеров-периферийных-устройств) контроллеров периферийных устройств.
## Ход работы
@@ -62,10 +62,10 @@ _Рисунок 1. Итоговая структура процессорной
Реализация унитарного кодирования предельно проста:
* Нулевой сигнал этой шины будет равен единице только если `data_addr_o[31:24] = 8'd0`.
* Первый бит этой шины будет равен единице только если `data_addr_o[31:24] = 8'd1`.
* ...
* Двести пятьдесят пятый бит шины будет равен единице только если `data_addr_o[31:24] = 8'd255`.
- Нулевой сигнал этой шины будет равен единице только если `data_addr_o[31:24] = 8'd0`.
- Первый бит этой шины будет равен единице только если `data_addr_o[31:24] = 8'd1`.
- ...
- Двести пятьдесят пятый бит шины будет равен единице только если `data_addr_o[31:24] = 8'd255`.
Для реализации такого кодирования достаточно выполнить сдвиг влево константы `255'd1` на значение `data_addr_o[31:24]`.
@@ -107,7 +107,7 @@ endmodule
Эти порты нужно подключить к одноименным портам ваших контроллеров периферии (**речь идет только о реализуемых вами контроллерах, остальные порты должны остаться неподключенными**). Иными словами, в описании модуля должны быть все указанные входы и выходы. Но использовать вам нужно только порты, связанные с теми периферийными устройствами, реализацию которых вам необходимо подключить к процессорной системе в рамках индивидуального задания.
Обратите внимание на то, что изменился сигнал сброса (`resetn_i`). Буква `n` на конце означает, что сброс работает по уровню `0` (когда сигнал равен нулю — это сброс, когда единице — не сброс).
Обратите внимание на то, что изменился сигнал сброса (`resetn_i`). Буква `n` на конце означает, что сброс работает по уровню `0` (в таком случае говорят, что **активный уровень** данного сигнала `0`: когда сигнал равен нулю — это сброс, когда единице — не сброс).
Помимо прочего, необходимо подключить к вашему модулю `блок делителя частоты`. Поскольку в данном курсе лабораторных работ вы выполняли реализацию однотактного процессора, инструкция должна пройти через все ваши блоки за один такт. Из-за этого критический путь схемы не позволит использовать тактовый сигнал частотой в `100 МГц`, от которого работает отладочный стенд. Поэтому, необходимо создать отдельный сигнал с пониженной тактовой частотой, от которого будет работать ваша схема.
@@ -121,13 +121,13 @@ logic sysclk, rst;
sys_clk_rst_gen divider(.ex_clk_i(clk_i),.ex_areset_n_i(resetn_i),.div_i(5),.sys_clk_o(sysclk), .sys_reset_o(rst));
```
3. После вставки данных строк в начало описания модуля `riscv_unit` вы получите тактовый сигнал `sysclk` с частотой в 10 МГц и сигнал сброса `rst` с активным уровнем `1` (как и в предыдущих лабораторных). Все ваши внутренние модули (`riscv_core`, `data_mem` и `контроллеры периферии`) должны работать от тактового сигнала `sysclk`. На модули, имеющие входной сигнал сброса (`rst_i`) необходимо подать ваш сигнал `rst`.
3. После вставки данных строк в начало описания модуля `riscv_unit` вы получите тактовый сигнал `sysclk` с частотой в 10 МГц и сигнал сброса `rst` с активным уровнем `1` (как и в предыдущих лабораторных). Все ваши внутренние модули (`riscv_core`, `data_mem` и контроллеры периферии) должны работать от тактового сигнала `sysclk`. На модули, имеющие входной сигнал сброса (`rst_i`) необходимо подать ваш сигнал `rst`.
---
## Задание
В рамках данной лабораторной работы необходимо реализовать модули-контроллеры двух периферийных устройств, реализующих управление в соответствии с приведенной на _рис. 2_ картой памяти и встроить их в процессорную систему, используя [_рис. 1_](../../.pic/Labs/lab_13_periph/fig_01.drawio.svg). На карте приведено шесть периферийных устройств, вам необходимо взять только два из них. Какие именно — сообщит преподаватель.
В рамках данной лабораторной работы необходимо реализовать модули-контроллеры двух периферийных устройств, реализующих управление в соответствии с приведенной на _рис. 2_ картой памяти и встроить их в процессорную систему, используя [_рис. 1_](../../.pic/Labs/lab_13_periph/fig_01.drawio.svg). На карте приведено семь периферийных устройств, вам необходимо взять только два из них. Какие именно — сообщит преподаватель.
![Карта памяти](../../.pic/Labs/lab_13_periph/fig_02.png)
@@ -136,8 +136,8 @@ _Рисунок 2. Карта памяти периферийных устрой
Работа с картой осуществляется следующим образом. Под названием каждого периферийного устройства указана старшая часть адреса (чему должны быть равны старшие 8 бит адреса, чтобы было сформировано обращение к данному периферийному устройству). Например, для переключателей это значение равно `0x01`, для светодиодов `0x02` и т.п.
В самом левом столбце указаны используемые/неиспользуемые адреса в адресном пространстве данного периферийного устройства. Например для переключателей есть только один используемый адрес: `0x000000`. Его функциональное назначение и разрешения на доступ указаны в столбце соответствующего периферийного устройства. Возвращаясь к адресу `0x000000`, для переключателей мы видим следующее:
* **(R)** означает что разрешен доступ только на чтение (операция записи по этому адресу должна игнорироваться вашим контроллером).
* **"Выставленное на переключателях значение"** означает ровно то, что и означает. Если процессор выполняет операцию чтения по адресу `0x01000000` (`0x01` [старшая часть адреса переключателей] + `0x000000` [младшая часть адреса для получения выставленного на переключателях значения]), то контроллер должен выставить на выходной сигнал `RD` значение на переключателях (о том как получить это значение будет рассказано чуть позже).
- **(R)** означает что разрешен доступ только на чтение (операция записи по этому адресу должна игнорироваться вашим контроллером).
- **"Выставленное на переключателях значение"** означает ровно то, что и означает. Если процессор выполняет операцию чтения по адресу `0x01000000` (`0x01` [старшая часть адреса переключателей] + `0x000000` [младшая часть адреса для получения выставленного на переключателях значения]), то контроллер должен выставить на выходной сигнал `RD` значение на переключателях (о том как получить это значение будет рассказано чуть позже).
Рассмотрим еще один пример. При обращении по адресу `0x02000024` (`0x02` (старшая часть адреса контроллера светодиодов) + `0x000024` (младшая часть адреса для доступа на запись к регистру сброса) ) должна произойти запись в регистр сброса, который должен сбросить значения в регистре управления зажигаемых светодиодов и регистре управления режимом "моргания" светодиодов (подробнее о том как должны работать эти регистры будет ниже).
@@ -154,24 +154,26 @@ _Рисунок 2. Карта памяти периферийных устрой
1. Внимательно ознакомьтесь с [примером описания модуля контроллера](../../Basic%20Verilog%20structures/Controllers.md).
2. Внимательно ознакомьтесь со спецификацией контроллеров периферии своего варианта. В случае возникновения вопросов, проконсультируйтесь с преподавателем.
3. Реализуйте модули контроллеров периферии. Имена модулей и их порты будут указаны в [описании контроллеров](#описание-контроллеров-периферийных-устройств). Пример разработки контроллера приведен [здесь](../../Basic%20Verilog%20structures/Controllers.md).
3. Реализуйте модули контроллеров периферии. Имена модулей и их порты будут указаны в [описании контроллеров](#описание-контроллеров-периферийных-устройств). Пример разработки контроллера приведен в [примере описания модуля контроллера](../../Basic%20Verilog%20structures/Controllers.md).
1. Готовые модули периферии, управление которыми должны осуществлять модули-контроллеры хранятся в папке `peripheral modules`.
4. Обновите модуль `riscv_unit` в соответствии с разделом ["Дополнительные правки модуля riscv_unit"](#дополнительные-правки-модуля-riscv_unit).
1. Подключите в проект файл `sys_clk_rst_gen.sv`.
2. Добавьте в модуль `riscv_unit` входы и выходы периферии. **Необходимо добавить порты даже тех периферийных устройств, которые вы не будете реализовывать**.
2. Добавьте в модуль `riscv_unit` входы и выходы периферии, а так же замените вход `rst_i` входом `resetn_i`. **Необходимо добавить порты даже тех периферийных устройств, которые вы не будете реализовывать**.
3. Создайте в начале описания модуля `riscv_unit` экземпляр модуля `sys_clk_rst_gen`, скопировав приведенный фрагмент кода.
4. Замените подключение тактового сигнала исходных подмодулей `riscv_unit` на появившийся сигнал `sysclk`. Убедитесь, что на модули, имеющие сигнал сброса, приходит сигнал `rst`.
5. Интегрируйте модули контроллеров периферии в процессорную систему по приведенной схеме руководствуясь старшими адресами контроллеров, представленными на карте памяти ([_рис. 2_](../../.pic/Labs/lab_13_periph/fig_02.png)). Это означает, что если вы реализуете контроллер светодиодов, на его вход `req_i` должна подаваться единица в случае, если `mem_req_o == 1` и старшие 8 бит адреса равны `0x02`.
1. При интеграции вы должны подключить только модули-контроллеры вашего варианта. Контроллеры периферии других вариантов подключать не надо.
2. При этом во время интеграции, вы должны использовать старшую часть адреса, представленную в карте памяти для формирования сигнала `req_i` для ваших модулей-контроллеров.
2. Во время интеграции, вы должны использовать старшую часть адреса, представленную в карте памяти для формирования сигнала `req_i` для ваших модулей-контроллеров.
6. Проверьте работу процессорной системы с помощью моделирования.
1. Для каждой пары контроллеров в папке `firmware/mem_files` представлены файлы, инициализирующие память инструкций. Обратите внимание, что для пары "PS2-VGA" также необходим файл, инициализирующий память данных (в модуле `ext_mem` необходимо прописать блок `$readmemh`).
2. Исходный код программ с адресами и результирующими инструкциями находится в папке `firmware/software`.
3. При моделировании светодиодов лучше уменьшить значение, до которого считает счетчик в режиме "моргания" в 1000 раз, чтобы сократить время моделирования до очередного переключения светодиодов. Перед генерацией битстрима это значение будет необходимо восстановить.
4. Для проверки тестбенч имитирует генерацию данных периферийных устройств ввода. При реализации контроллера клавиатуры или uart_rx рекомендуется ознакомиться с тем, какие именно данные тестбенч подает на вход.
5. Для того, чтобы понять, что устройство работает должным образом, в первую очередь необходимо убедиться, что контроллер устройства ввода успешно осуществил прием данных (сгенерированные тестбенчем данные оказались в соответствующем регистре контроллера периферийного устройства) и сгенерировал запрос на прерывание.
6. После чего, необходимо убедиться, что процессор среагировал на данное прерывание, и в процессе его обработки в контроллер устройства вывода были поданы выходные данные.
7. Для того, чтобы лучше понимать как именно процессор будет обрабатывать прерывание, рекомендуется ознакомиться с исходным кодом исполняемой программы, расположенным в папке `firmware/software`.
1. Для каждой пары контроллеров в папке `firmware/mem_files` представлены файлы, инициализирующие память инструкций. Обратите внимание, что для пары "PS2-VGA" также необходим файл, инициализирующий память данных (в модуле `data_mem` необходимо добавить вызов инициализирующей функции `$readmemh` в блоке `initial`).
2. Для проверки тестбенч имитирует генерацию данных периферийных устройств ввода. Перед проверкой желательно найти в тестбенче `initial`-блок своего устройства ввода (`sw_block`, `ps2_block`, `uart_block`) — по этому блоку будет понятно, какие данные будет передавать устройство ввода. Именно эти данные в итоге должны оказаться на шине `mem_rd_i`.
3. Для того, чтобы понять, что устройство работает должным образом, в первую очередь необходимо убедиться, что контроллер устройства ввода успешно осуществил прием данных (сгенерированные тестбенчем данные оказались в соответствующем регистре контроллера периферийного устройства) и выполнил запрос на прерывание.
4. После чего, необходимо убедиться, что процессор среагировал на данное прерывание, и в процессе его обработки в контроллер устройства вывода были поданы выходные данные.
5. Для того, чтобы лучше понимать как именно процессор будет обрабатывать прерывание, рекомендуется ознакомиться с исходным кодом исполняемой программы, расположенным в папке `firmware/software`.
1. Общая логика программ для всех периферий сводится к ожиданию в бесконечном цикле прерывания от устройства ввода, после чего в процессе обработки прерывания процессор загружает данные от устройства ввода и (возможно преобразовав их) выдает их на устройство вывода.
2. В случае правильной работы программы на временной диаграмме это будет отображено следующим образом: сразу после поступления прерывания от устройства ввода, на системной шине начинается операция чтения из устройства ввода (это легко определить по старшей части адреса, к которому обращается процессор), после чего выполняются операции записи в устройство вывода (аналогично, обращение к устройству вывода можно определить по адресу, к которому обращается процессор).
6. При моделировании светодиодов лучше уменьшить значение, до которого считает счетчик в режиме "моргания" в 1000 раз, чтобы сократить время моделирования до очередного переключения светодиодов. Перед генерацией битстрима это значение будет необходимо восстановить, иначе моргание станет слишком быстрым и его нельзя будет воспринять невооруженным взглядом.
7. Переходить к следующему пункту можно только после того, как вы полностью убедились в работоспособности модуля на этапе моделирования (увидели корректные значения на выходных сигналах периферии, либо (если по сигналам периферии сложно судить о работоспособности), значениям в контрольных/статусных регистрах модуля-контроллера этой периферии). Генерация битстрима будет занимать у вас долгое время, а итогом вы получите результат: заработало / не заработало, без какой-либо дополнительной информации, поэтому без прочного фундамента на моделировании далеко уехать у вас не выйдет.
<!-- 1. Для каждой пары контроллеров периферии предложено две программы: с обновлением данных по опросу и по прерываниям. Запустите моделирование сначала для одной программы, затем для другой (для этого необходимо обновить файл, инициализирующий память инструкций). После проверки работоспособности процессора, сравните поведение сигналов LSU для этих программ. -->
8. Подключите к проекту файл ограничений ([nexys_a7_100t.xdc](nexys_a7_100t.xdc)), если тот еще не был подключен, либо замените его содержимое данными из файла к этой лабораторной работе.
@@ -195,13 +197,13 @@ _Рисунок 2. Карта памяти периферийных устрой
3. На входе `write_enable_i` выставлено значение `0`.
4. На входе `addr_i` выставлено значение `0xАДРЕС`
Обратите внимание на то, что **запрос на чтение** должен обрабатываться **синхронно** (выходные данные должны выдаваться по положительному фронту `clk_i`).
Обратите внимание на то, что **запрос на чтение** должен обрабатываться **синхронно** (выходные данные должны выдаваться по положительному фронту `clk_i`) так же как был реализован порт на чтение памяти данных в [ЛР№6](../06.%20Main%20memory/).
При описании поддерживаемых режимов доступа по данному адресу используется следующее обозначение:
При описании поддерживаемых режимов доступа по данному адресу используются следующее обозначения:
* R — доступ **только на чтение**;
* W — доступ **только на запись**;
* RW — доступ на **чтение и запись**.
- R — доступ **только на чтение**;
- W — доступ **только на запись**;
- RW — доступ на **чтение и запись**.
В случае отсутствия **запроса на чтение**, на выходе `read_data_o` не должно меняться значение (тоже самое было сделано в процессе разработки памяти данных).
@@ -288,15 +290,15 @@ logic led_mode;
endmodule
```
Данный модуль должен выводить на выходной сигнал `led_o` данные с регистра `led_val`. Запись и чтение регистра `led_val` осуществляется по адресу `0x00`. Запись любого значения, превышающего `2¹⁶-1` должна игнорироваться.
Данный модуль должен подавать на выходной сигнал `led_o` данные с регистра `led_val`. Запись и чтение регистра `led_val` осуществляется по адресу `0x00`.
Регистр `led_mode` отвечает за режим вывода данных на светодиоды. Когда этот регистр равен единице, светодиоды должны "моргать" выводимым значением. Под морганием подразумевается вывод значения из регистра `led_val` на выход `led_o` на одну секунду (загорится часть светодиодов, соответствующие которым биты шины `led_o` равны единице), после чего на одну секунду выход `led_o` необходимо подать нули. Запись и чтение регистра `led_mode` осуществляется по адресу `0x04`. Запись любого значения, отличного от `0` и `1` в регистр `led_mode` должна игнорироваться.
Регистр `led_mode` отвечает за режим вывода данных на светодиоды. Когда этот регистр равен единице, светодиоды должны "моргать" выводимым значением. Под морганием подразумевается вывод значения из регистра `led_val` на выход `led_o` на одну секунду (загорится часть светодиодов, соответствующие которым биты шины `led_o` равны единице), после чего на одну секунду выход `led_o` необходимо подать нули. Запись и чтение регистра `led_mode` осуществляется по адресу `0x04`.
Отсчет времени можно реализовать простейшим счетчиком, каждый такт увеличивающимся на 1 и сбрасывающимся по достижении определенного значения, чтобы продолжить считать с нуля. Зная тактовую частоту, нетрудно определить до скольки должен считать счетчик. При тактовой частоте в 10 МГц происходит 10 миллионов тактов в секунду. Это означает, что при такой тактовой частоте через секунду счетчик будет равен `10⁷-1` (счет идет с нуля). Тем не менее удобней будет считать не до `10⁷-1` (что было бы достаточно очевидным и тоже правильным решением), а до `2*10⁷-1`. В этом случае старший бит счетчика каждую секунду будет инвертировать свое значение, что может быть использовано при реализации логики "моргания".
Важно отметить, что счетчик должен работать только при `led_mode == 1`, в противном случае счетчик должен быть равен нулю.
Обратите внимание на то, что адрес `0x24` является адресом сброса. В случае **запроса на запись** по этому адресу значения `1`. вы должны сбросить регистры `led_val`, `led_mode` и все вспомогательные регистры, которые вы создали. Для реализации сброса вы можете как создать отдельный регистр `led_rst`, в который будет происходить запись, а сам сброс будет происходить по появлению единицы в этом регистре (в этом случае необходимо не забыть сбрасывать и этот регистр), так и создать обычный провод, формирующий единицу в случае выполнения всех указанных условий (условий **запроса на запись**, адреса сброса и значения записываемых данных равному единице).
Обратите внимание на то, что адрес `0x24` является адресом сброса. В случае **запроса на запись** по этому адресу значения `1`. вы должны сбросить регистры `led_val`, `led_mode` и все вспомогательные регистры, которые вы создали. Для реализации сброса вы можете как создать отдельный регистр `led_rst`, в который будет происходить запись, а сам сброс будет происходить по появлению единицы в этом регистре (в этом случае необходимо не забыть сбрасывать и этот регистр тоже), так и создать обычный провод, формирующий единицу в случае выполнения всех указанных условий (условий **запроса на запись**, адреса сброса и значения записываемых данных равному единице).
Адресное пространство контроллера:
@@ -449,7 +451,7 @@ endmodule
Доступ на чтение/запись регистра `bitmask` осуществляется по адресу `0x20`.
При **запросе на запись** единицы по адресу `0x24` необходимо выполнить сброс всех регистров. При этом регистр `bitmask` должен сброситься в значение `0xFF`.
При **запросе на запись** единицы по адресу `0x24` необходимо выполнить сброс всех регистров. При этом регистр `bitmask` должен сброситься в значение `0xFF` (т.е. после сброса все семисегментные индикаторы должны загореться с цифрой `0`).
Адресное пространство контроллера:
@@ -472,9 +474,9 @@ endmodule
Для того, чтобы передача данных была успешно осуществлена, приемник и передатчик на обоих концах одного провода должны договориться о параметрах передачи:
* её скорости (бодрейт);
* контроля целостности данных (использовать или нет [бит четности](https://en.wikipedia.org/wiki/Parity_bit));
* длины стопового бита.
- её скорости (бодрейт);
- контроля целостности данных (использовать или нет [бит четности](https://en.wikipedia.org/wiki/Parity_bit));
- длины стопового бита.
Вам будут предоставлены модули, осуществляющие прием и передачу данных по этому интерфейсу, от вас лишь требуется написать модули, осуществляющие управление предоставленными модулями.
@@ -643,7 +645,7 @@ _Рисунок 3. Пример игры с использованием сим
_Рисунок 4. Карта памяти vga-модуля._
Для того, чтобы вывести символ на экран, необходимо использовать адрес этого символа на сетке `80x30` (диапазон адресов `char_map`). К примеру, мы хотим вывести символ в верхнем левом углу. Это нулевой символ в диапазоне адресов `char_map`. Поскольку данный диапазон начинается с адреса `0x0000_0000`, запись по этому адресу приведет к отображению символа, соответствующего [ASCII-коду](https://www.asciitable.com/), пришедшему на `write_data_i`.
Для того, чтобы вывести символ на экран, необходимо использовать адрес этого символа на сетке `80x30` (диапазон адресов `char_map`). К примеру, мы хотим вывести символ в верхнем левом углу (т.е. нулевой символ нулевой строки). Это нулевой символ в диапазоне адресов `char_map`. Поскольку данный диапазон начинается с адреса `0x0000_0000`, запись по этому адресу приведет к отображению символа, соответствующего [ASCII-коду](https://www.asciitable.com/), пришедшему на `write_data_i`.
Если мы хотим вывести нулевой (левый) символ в первой строке (счет ведется с нуля), то необходимо произвести запись по адресу `1*80+0=80=0x0000_0050`.
@@ -651,9 +653,9 @@ _Рисунок 4. Карта памяти vga-модуля._
Установка цветовой схемы осуществляется по тем же самым адресам, к которым прибавлено значение `0x0000_1000`:
* верхний левый символ — `0x0000_1000`
* нулевой символ первой строки — `0x0000_1050`
* нижний правый символ — `0x0000_195F`
- верхний левый символ — `0x0000_1000`
- нулевой символ первой строки — `0x0000_1050`
- нижний правый символ — `0x0000_195F`
Цветовая схема каждой позиции состоит из двух цветов: цвета фона и цвета символа. Оба эти цвета выбираются из палитры 8 цветов, каждый из которых содержит два оттенка: цвет на полной яркости и цвет на уменьшенной яркости (см. _рис. 5_). Один из цветов — черный, оба его оттенка представляют собой один и тот же цвет. На _рис. 5_ приведены коды цветов их rgb-значения:
@@ -663,9 +665,9 @@ _Рисунок 5. Цветовая палитра vga-модуля._
Код цвета формируется следующим образом: старший бит определяет яркость оттенка цвета. Оставшиеся 3 бита кодируют используемый канал:
* 0 бит кодирует использование синего канала;
* 1 бит кодирует использование зеленого канала;
* 2 бит кодирует использование красного канала.
- 0 бит кодирует использование синего канала;
- 1 бит кодирует использование зеленого канала;
- 2 бит кодирует использование красного канала.
Таким образом, для установки цветовой схемы, необходимо выбрать два цвета из палитры, склеить их (в старших разрядах идет цвет символа, в младших — цвет фона) и записать получившееся 8-битное значение по адресу выбранной позиции в диапазоне адресов цветовой схемы (color_map).
@@ -685,13 +687,15 @@ _Рисунок 6. Отрисовка символа `F` в разрешении
Для хранения шрифтов в модуле отведен диапазон адресов `0x00002000-0x00002FFF`. В отличие от предыдущих диапазонов адресов, где каждый адрес был закреплен за соответствующей позицией символа в сетке `80x30`, адреса данного диапазона распределены следующим образом:
* 0-ой байт — нулевая (верхняя) строчка символа с кодом 0;
* 1-ый байт — первая строчка символа с кодом 0;
* ...
* 15-ый байт — пятнадцатая (нижняя) строчка символа с кодом 0;
* 16-ый байт — нулевая (верхняя) строчка символа с кодом 1;
* ...
* 4095-ый байт — пятнадцатая (нижняя) строчка символа с кодом 255.
- 0-ой байт — нулевая (верхняя) строчка символа с кодом 0;
- 1-ый байт — первая строчка символа с кодом 0;
- ...
- 15-ый байт — пятнадцатая (нижняя) строчка символа с кодом 0;
- 16-ый байт — нулевая (верхняя) строчка символа с кодом 1;
- ...
- 4095-ый байт — пятнадцатая (нижняя) строчка символа с кодом 255.
Для простоты работы с модулем вам будут даны файлы, которыми можно проинициализировать память шрифтов и цветов. В этом случае вам будет достаточно только записывать выводимые символы по нужным адресам.
Прототип vga-модуля следующий:
@@ -739,15 +743,14 @@ module vgachargen (
Файлы модуля:
* peripheral modules/vhachargen.sv
* peripheral modules/vhachargen_pkg.sv
* firmware/mem_files/lab_13_ps2_vga_instr.mem — этим файлом необходимо проинициализировать память инструкций
* firmware/mem_files/lab_13_ps2ascii_data.mem — этим файлом необходимо проинициализировать память данных
* firmware/mem_files/lab_13_vga_ch_map.mem
* firmware/mem_files/lab_13_vga_ch_t.mem
* firmware/mem_files/lab_13_vga_col_map.mem
- peripheral modules/vhachargen.sv
- peripheral modules/vhachargen_pkg.sv
- firmware/mem_files/lab_13_ps2_vga_instr.mem — этим файлом необходимо проинициализировать память инструкций
- firmware/mem_files/lab_13_ps2ascii_data.mem — этим файлом необходимо проинициализировать память данных
- firmware/mem_files/lab_13_vga_ch_t.mem
- firmware/mem_files/lab_13_vga_col_map.mem
Вам необходимо добавить в проект все эти файлы.
Вам необходимо добавить в проект все эти файлы. Последние два файла отвечают за инициализацию памятей шрифтов и цветов. Инициализация будет выполнена автоматически. Главное, чтобы файлы были добавлены в проект.
Для управления данным модулем, необходимо написать модуль-контроллер со следующим прототипом:
@@ -773,14 +776,14 @@ module vga_sb_ctrl (
Реализация данного модуля исключительно простая. В первую очередь необходимо подключить одноименные сигналы напрямую:
* `clk_i`,
* `rst_i`,
* `clk100m_i`,
* `vga_r_o`,
* `vga_g_o`,
* `vga_b_o`,
* `vga_hs_o`,
* `vga_vs_o`
- `clk_i`,
- `rst_i`,
- `clk100m_i`,
- `vga_r_o`,
- `vga_g_o`,
- `vga_b_o`,
- `vga_hs_o`,
- `vga_vs_o`
Кроме того, необходимо: