BREAKING CHANGE! Сдвиг нумерации в лабах

Лабу по дейзи-цепочке необходимо вставить сразу после лабы по интеграции
контроллера прерываний, поэтому приходится увеличить нумерацию
оставшихся лаб.
This commit is contained in:
Andrei Solodovnikov
2024-02-04 11:08:37 +03:00
parent d4d813a7ea
commit 45585ff9c4
60 changed files with 37 additions and 37 deletions

View File

@@ -0,0 +1,805 @@
# Лабораторная работа 13 "Периферийные устройства"
На прошлой лабораторной работе вы реализовали свой собственный RISC-V процессор. Однако пока что он находится "в вакууме" и никак не связан с внешним миром. Для исправления этого недостатка вами будет реализована системная шина, через которую к процессору смогут подключаться различные периферийные устройства.
## Цель
Интегрировать периферийные устройства в процессорную систему.
---
## Допуск к лабораторной работе
Для успешного выполнения лабораторной работы, вам необходимо:
* ознакомиться с [примером описания модуля-контроллера](../../Basic%20Verilog%20structures/Controllers.md);
* ознакомиться с [описанием](#описание-контроллеров-периферийных-устройств) контроллеров периферийных устройств.
## Ход работы
1. Изучить теорию об адресном пространстве
2. Получить индивидуальный вариант со своим набором периферийных устройств
3. Интегрировать контроллеры периферийных устройств в адресное пространство вашей системы
4. Собрать финальную схему вашей системы
5. Проверить работу системы в ПЛИС с помощью демонстрационного ПО, загружаемого в память инструкций
---
## Теория
Помимо процессора и памяти, третьим ключевым элементом вычислительной системы является система ввода/вывода, обеспечивающая обмен информации между ядром вычислительной машины и периферийными устройствами[1, стр.364].
Любое периферийное устройство со стороны вычислительной машины видится как набор ячеек памяти (регистров). С помощью чтения и записи этих регистров происходит обмен информации с периферийным устройством, и управление им. Например, датчик температуры может быть реализован самыми разными способами, но для процессора он в любом случае ячейка памяти, из которой он считывает число температуру.
Система ввода/вывода может быть организована одним из двух способов: с **выделенным адресным пространством** устройств ввода/вывода, или с **совместным адресным пространством**. В первом случае система ввода/вывода имеет отдельную шину для подключения к процессору (и отдельные инструкции для обращения к периферии), во втором шина для памяти и системы ввода/вывода общая (а обращение к периферии осуществляется теми же инструкциями, что и обращение к памяти).
### Адресное пространство
Архитектура RISC-V подразумевает использование совместного адресного пространства — это значит, что в лабораторной работе будет использована единая шина для подключения памяти и регистров управления периферийными устройствами. При обращении по одному диапазону адресов процессор будет попадать в память, при обращении по другим взаимодействовать с регистрами управления/статуса периферийного устройства. Например, можно разделить 32-битное адресное пространство на 256 частей, отдав старшие 8 бит адреса под указание конкретного периферийного устройства. Тогда каждое из периферийных устройств получит 24-битное адресное пространство (16 MiB). Допустим, мы распределили эти части адресного пространства в следующем порядке (от младшего диапазона адресов к старшему):
0. Память данных
1. Переключатели
2. Светодиоды
3. Клавиатура PS/2
4. Семисегментные индикаторы
5. UART-приемник
6. UART-передатчик
7. Видеоадаптер
В таком случае, если мы захотим обратиться к первому (счет идет с нуля) байту семисегментных индикаторов, мы должны будем использовать адрес `0x04000001`. Старшие 8 бит (`0x04`) определяют выбранное периферийное устройство, оставшиеся 24 бита определяют конкретный адрес в адресном пространстве этого устройства.
На рисунке ниже представлен способ подключения процессора к памяти инструкций и данных, а также 255 периферийным устройствам.
![../../.pic/Labs/lab_13_periph/fig_01.drawio.svg](../../.pic/Labs/lab_13_periph/fig_01.drawio.svg)
_Рисунок 1. Итоговая структура процессорной системы._
### Активация выбранного устройства
В зависимости от интерфейса используемой шины, периферийные устройства либо знают какой диапазон адресов им выделен (например, в интерфейсе I²C), либо нет (интерфейс APB). В первом случае, устройство понимает что к нему обратились непосредственно по адресу в данном обращении, во втором случае — по специальному сигналу.
На _рис. 1_ используется второй вариант — устройство понимает, что к нему обратились по специальному сигналу `req_i`. Данный сигнал формируется из двух частей: сигнала `req` исходящего из процессорного ядра (сигнал о том, обращение в память вообще происходит) и специального сигнала-селектора исходящего из 256-разрядной шины. Формирование значения на этой шине происходит с помощью [унитарного](https://ru.wikipedia.org/wiki/Унитарный_код) ([one-hot](https://en.wikipedia.org/wiki/One-hot)) кодирования. Процесс кодирования достаточно прост. В любой момент времени на выходной шине должен быть **ровно один** бит, равный единице. Индекс этого бита совпадает со значением старших восьми бит адреса. Поскольку для восьмибитного значения существует 256 комбинаций значений, именно такая разрядность будет на выходе кодировщика. Это означает, что в данной системе можно связать процессор с 256 устройствами (одним из которых будет память данных).
Реализация такого кодирования предельно проста:
* Нулевой сигнал этой шины будет равен единице только если `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]`.
### Дополнительные правки модуля riscv_unit
Ранее, для того чтобы ваши модули могли работать в ПЛИС, вам предоставлялся специальный модуль верхнего уровня, который выполнял всю работу по связи с периферией через входы и выходы ПЛИС. Поскольку в текущей лабораторной вы завершаете свою процессорную систему, она сама должна оказаться модулем верхнего уровня, а значит здесь вы должны и выполнить всё подключение к периферии.
Для этого необходимо добавить в модуль `riscv_unit` дополнительные входы и выходы, которые подключены посредством файла ограничений ([nexys_a7_100t.xdc](nexys_a7_100t.xdc)) к входам и выходам ПЛИС.
```SystemVerilog
module riscv_unit(
input logic clk_i,
input logic resetn_i,
// Входы и выходы периферии
input logic [15:0] sw_i, // Переключатели
output logic [15:0] led_o, // Светодиоды
input logic kclk_i, // Тактирующий сигнал клавиатуры
input logic kdata_i, // Сигнал данных клавиатуры
output logic [ 6:0] hex_led_o, // Вывод семисегментных индикаторов
output logic [ 7:0] hex_sel_o, // Селектор семисегментных индикаторов
input logic rx_i, // Линия приема по UART
output logic tx_o, // Линия передачи по UART
output logic [3:0] vga_r_o, // красный канал vga
output logic [3:0] vga_g_o, // зеленый канал vga
output logic [3:0] vga_b_o, // синий канал vga
output logic vga_hs_o, // линия горизонтальной синхронизации vga
output logic vga_vs_o // линия вертикальной синхронизации vga
);
//...
endmodule
```
Эти порты нужно подключить к одноименным портам ваших контроллеров периферии (**речь идет только о реализуемых вами контроллерах, остальные порты должны остаться неподключенными**). Иными словами, в описании модуля должны быть все указанные входы и выходы. Но использовать вам нужно только порты, связанные с теми периферийными устройствами, реализацию которых вам необходимо подключить к процессорной системе в рамках индивидуального задания.
Обратите внимание на то, что изменился сигнал сброса (`resetn_i`). Буква `n` на конце означает, что сброс работает по уровню `0` (когда сигнал равен нулю — это сброс, когда единице — не сброс).
Помимо прочего, необходимо подключить к вашему модулю `блок делителя частоты`. Поскольку в данном курсе лабораторных работ вы выполняли реализацию однотактного процессора, инструкция должна пройти через все ваши блоки за один такт. Из-за этого критический путь вашей схемы не позволит использовать тактовый сигнал частотой в `100 МГц`, от которого работает отладочный стенд. Поэтому, необходимо создать отдельный сигнал с пониженной тактовой частотой, от которого будет работать ваша схема.
Для этого необходимо:
1. Подключить файл [`sys_clk_rst_gen.sv`](sys_clk_rst_gen.sv) в ваш проект.
2. Подключить этот модуль в начале описания модуля `riscv_unit` следующим образом:
```SystemVerilog
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`.
---
## Задание
В рамках данной лабораторной работы необходимо реализовать модули-контроллеры двух периферийных устройств, реализующих управление в соответствии с приведенной ниже картой памяти и встроить их в процессорную систему, используя [_рис. 1_](../../.pic/Labs/lab_13_periph/fig_01.drawio.svg). На карте приведено шесть периферийных устройств, вам необходимо взять только два из них. Какие именно — сообщит преподаватель.
![Карта памяти](../../.pic/Labs/lab_13_periph/fig_02.png)
_Рисунок 2. Карта памяти периферийных устройств._
Работа с картой осуществляется следующим образом. Под названием каждого периферийного устройства указана старшая часть адреса (чему должны быть равны старшие 8 бит адреса, чтобы было сформировано обращение к данному периферийному устройству). Например, для переключателей это значение равно `0x01`, для светодиодов `0x02` и т.п.
В самом левом столбце указаны используемые/неиспользуемые адреса в адресном пространстве данного периферийного устройства. Например для переключателей есть только один используемый адрес: `0x000000`. Его функциональное назначение и разрешения на доступ указаны в столбце соответствующего периферийного устройства. Возвращаясь к адресу `0x000000`, для переключателей мы видим следующее:
* **(R)** означает что разрешен доступ только на чтение (операция записи по этому адресу должна игнорироваться вашим контроллером).
* **"Выставленное на переключателях значение"** означает ровно то, что и означает. Если процессор выполняет операцию чтения по адресу `0x01000000` (`0x01` [старшая часть адреса переключателей] + `0x000000` [младшая часть адреса для получения выставленного на переключателях значения]), то контроллер должен выставить на выходной сигнал `RD` значение на переключателях (о том как получить это значение будет рассказано чуть позже).
Рассмотрим еще один пример. При обращении по адресу `0x02000024` (`0x02` (старшая часть адреса контроллера светодиодов) + `0x000024` (младшая часть адреса для доступа на запись к регистру сброса) ) должна произойти запись в регистр сброса, который должен сбросить значения в регистре управления зажигаемых светодиодов и регистре управления режимом "моргания" светодиодов (подробнее о том как должны работать эти регистры будет ниже).
Таким образом, каждый контроллер периферийного устройства должен выполнять две вещи:
1. При получении сигнала `req_i`, записать в регистр или вернуть значение из регистра, ассоциированного с переданным адресом (адрес передается с обнуленной старшей частью). Если регистра, ассоциированного с таким адресом нет (например, для переключателей не ассоциировано ни одного адреса кроме `0x000000`), игнорировать эту операцию.
2. Выполнять управление периферийным устройством с помощью управляющих регистров.
Подробное описание периферийных устройств их управления и назначение управляющих регистров будет дано после порядка выполнения задания.
---
## Порядок выполнения задания
1. Внимательно ознакомьтесь с [примером описания модуля контроллера](../../Basic%20Verilog%20structures/Controllers.md).
2. Внимательно ознакомьтесь со спецификацией контроллеров периферии своего варианта. В случае возникновения вопросов, проконсультируйтесь с преподавателем.
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` входы и выходы периферии. **Необходимо добавить порты даже тех периферийных устройств, которые вы не будете реализовывать**.
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` для ваших модулей-контроллеров.
6. Проверьте работу процессорной системы с помощью моделирования.
1. Для каждой пары контроллеров в папке `firmware/mem_files` представлены файлы, инициализирующие память инструкций. Обратите внимание, что для пары "PS2-VGA" также необходим файл, инициализирующий память данных (в модуле `ext_mem` необходимо прописать блок `$readmemh`).
2. Исходный код программ с адресами и результирующими инструкциями находится в папке `firmware/software`.
3. При моделировании светодиодов лучше уменьшить значение, до которого считает счетчик в режиме "моргания" в 10 раз, чтобы уменьшить время моделирования. Перед генерацией битстрима это значение будет необходимо восстановить.
4. Для проверки тестбенч имитирует генерацию данных периферийных устройств ввода. При реализации контроллера клавиатуры или uart_rx рекомендуется ознакомиться с тем, какие именно данные тестбенч подает на вход.
5. Для того, чтобы понять, что устройство работает должным образом, в первую очередь необходимо убедиться, что контроллер устройства ввода успешно осуществил прием данных (сгенерированные тестбенчем данные оказались в соответствующем регистре контроллера периферийного устройства) и сгенерировал запрос на прерывание.
6. После чего, необходимо убедиться, что процессор среагировал на данное прерывание, и в процессе его обработки в контроллер устройства вывода были поданы выходные данные.
7. Для того, чтобы лучше понимать как именно процессор будет обрабатывать прерывание, рекомендуется ознакомиться с исходным кодом исполняемой программы, расположенным в папке `firmware/software`.
7. Переходить к следующему пункту можно только после того, как вы полностью убедились в работоспособности модуля на этапе моделирования (увидели корректные значения на выходных сигналах периферии, либо (если по сигналам периферии сложно судить о работоспособности), значениям в контрольных/статусных регистрах модуля-контроллера этой периферии). Генерация битстрима будет занимать у вас долгое время, а итогом вы получите результат: заработало / не заработало, без какой-либо дополнительной информации, поэтому без прочного фундамента на моделировании далеко уехать у вас не выйдет.
<!-- 1. Для каждой пары контроллеров периферии предложено две программы: с обновлением данных по опросу и по прерываниям. Запустите моделирование сначала для одной программы, затем для другой (для этого необходимо обновить файл, инициализирующий память инструкций). После проверки работоспособности процессора, сравните поведение сигналов LSU для этих программ. -->
8. Подключите к проекту файл ограничений ([nexys_a7_100t.xdc](nexys_a7_100t.xdc)), если тот еще не был подключен, либо замените его содержимое данными из файла к этой лабораторной работе.
9. Проверьте работу вашей процессорной системы на отладочном стенде с ПЛИС.
1. Обратите внимание, что в данной лабораторной уже не будет модуля верхнего уровня `nexys_...`, так как ваш модуль процессорной системы уже полностью самостоятелен и взаимодействует непосредственно с ножками ПЛИС через модули, управляемые контроллерами периферии.
---
## Описание контроллеров периферийных устройств
Для того, чтобы избежать избыточности в контексте описания контроллеров периферийных устройств будет использоваться два термина:
1. Под "**запросом на запись** по адресу `0xАДРЕС`" будет пониматься совокупность следующих условий:
1. Происходит восходящий фронт `clk_i`.
2. На входе `req_i` выставлено значение `1`.
3. На входе `write_enable_i` выставлено значение `1`.
4. На входе `addr_i` выставлено значение `0xАДРЕС`
2. Под "**запросом на чтение** по адресу `0xАДРЕС`" будет пониматься совокупность следующих условий:
1. На входе `req_i` выставлено значение `1`.
2. На входе `write_enable_i` выставлено значение `0`.
3. На входе `addr_i` выставлено значение `0xАДРЕС`
Обратите внимание на то, что **запрос на чтение** должен обрабатываться **синхронно** (выходные данные должны выдаваться по положительному фронту `clk_i`).
При описании поддерживаемых режимов доступа по данному адресу используется следующее обозначение:
* R — доступ **только на чтение**;
* W — доступ **только на запись**;
* RW — доступ на **чтение и запись**.
В случае отсутствия **запроса на чтение**, на выходе `read_data_o` не должно меняться значение (тоже самое было сделано в процессе разработки памяти данных).
Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу, поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно остаться прежнее значение.
В случае осуществления записи по принятому запросу, необходимо записать данные с сигнала `write_data_i` в регистр, ассоциированный с адресом `addr_i` (если разрядность регистра меньше разрядности сигнала `write_data_i`, старшие биты записываемых данных отбрасываются).
В случае осуществления чтения по принятому запросу, необходимо по положительному фронту `clk_i` выставить данные с сигнала, ассоциированного с адресом `addr_i` на выходной сигнал `read_data_o` (если разрядность сигнала меньше разрядности выходного сигнала `read_data_o`, возвращаемые данные должны дополниться нулями в старших битах).
### Переключатели
Переключатели являются простейшим устройством ввода на отладочном стенде `Nexys A7`. Соответственно и контроллер, осуществляющий доступ процессора к ним так же будет очень простым. Рассмотрим прототип модуля, который вам необходимо реализовать:
```SystemVerilog
module sw_sb_ctrl(
/*
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i,
input logic req_i,
input logic write_enable_i,
input logic [31:0] addr_i,
input logic [31:0] write_data_i, // не используется, добавлен для
// совместимости с системной шиной
output logic [31:0] read_data_o,
/*
Часть интерфейса модуля, отвечающая за отправку запросов на прерывание
процессорного ядра
*/
output logic interrupt_request_o,
input logic interrupt_return_i,
/*
Часть интерфейса модуля, отвечающая за подключение к периферии
*/
input logic [15:0] sw_i
);
endmodule
```
По сути, логика работы контроллера сводится к тому, выдавать на шину `read_data_o` данные со входа `sw_i` каждый раз, когда приходит **запрос на чтение** по нулевому адресу. Поскольку разрядность `sw_i` в два раза меньше разрядности выхода `read_data_o` его старшие биты необходимо дополнить нулями.
Адресное пространство контроллера:
|Адрес|Режим доступа| Функциональное назначение |
|-----|-------------|-------------------------------------------------|
|0x00 | R | Чтение значения, выставленного на переключателях|
При этом, будучи устройством ввода, данный модуль может генерировать прерывание, чтобы сообщить процессору о том, что данные на переключателях были изменены. Если на очередном такте `clk_i` данные на входе `sw_i` изменились (т.е. отличаются от тех, что были на предыдущем такте), модуль должен выставить значение `1` на выходе `interrupt_request_o` и удерживать его до получения сигнала о завершении обработки прерывания `interrupt_return_i`.
Для отслеживания изменений на входе `sw_i` между тактами синхроимпульса вам потребуется вспомогательный регистр, каждый такт сохраняющий значение `sw_i`. При реализации данного регистра, не забывайте о том, что его необходимо сбрасывать посредством сигнала `rst_i`.
### Светодиоды
Как и переключатели, светодиоды являются простейшим устройством вывода. Поэтому, чтобы задание было интересней, для их управления был добавлен регистр, управляющий режимом вывода данных на светодиоды.
Рассмотрим прототип модуля, который вам необходимо реализовать:
```SystemVerilog
module led_sb_ctrl(
/*
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i,
input logic req_i,
input logic write_enable_i,
input logic [31:0] addr_i,
input logic [31:0] write_data_i,
output logic [31:0] read_data_o,
/*
Часть интерфейса модуля, отвечающая за подключение к периферии
*/
output logic [15:0] led_o
);
logic [15:0] led_val;
logic led_mode;
endmodule
```
Данный модуль должен выводить на выходной сигнал `led_o` данные с регистра `led_val`. Запись и чтение регистра `led_val` осуществляется по адресу `0x00`. Запись любого значения, превышающего `2¹⁶-1` должна игнорироваться.
Регистр `led_mode` отвечает за режим вывода данных на светодиоды. Когда этот регистр равен единице, светодиоды должны "моргать" выводимым значением. Под морганием подразумевается вывод значения из регистра `led_val` на выход `led_o` на одну секунду (загорится часть светодиодов, соответствующие которым биты шины `led_o` равны единице), после чего на одну секунду выход `led_o` необходимо подать нули. Запись и чтение регистра `led_mode` осуществляется по адресу `0x04`. Запись любого значения, отличного от `0` и `1` в регистр `led_mode` должна игнорироваться.
Отсчет времени можно реализовать простейшим счетчиком, каждый такт увеличивающимся на 1 и сбрасывающимся по достижении определенного значения, чтобы продолжить считать с нуля. Зная тактовую частоту, нетрудно определить до скольки должен считать счетчик. При тактовой частоте в 10 МГц происходит 10 миллионов тактов в секунду. Это означает, что при такой тактовой частоте через секунду счетчик будет равен `10⁷-1` (счет идет с нуля). Тем не менее удобней будет считать не до `10⁷-1` (что было бы достаточно очевидным и тоже правильным решением), а до `2*10⁷-1`. В этом случае старший бит счетчика каждую секунду будет инвертировать свое значение, что может быть использовано при реализации логики "моргания".
Важно отметить, что счетчик должен работать только при `led_mode == 1`, в противном случае счетчик должен быть равен нулю.
Обратите внимание на то, что адрес `0x24` является адресом сброса. В случае **запроса на запись** по этому адресу значения `1`. вы должны сбросить регистры `led_val`, `led_mode` и все вспомогательные регистры, которые вы создали. Для реализации сброса вы можете как создать отдельный регистр `led_rst`, в который будет происходить запись, а сам сброс будет происходить по появлению единицы в этом регистре (в этом случае необходимо не забыть сбрасывать и этот регистр), так и создать обычный провод, формирующий единицу в случае выполнения всех указанных условий (условий **запроса на запись**, адреса сброса и значения записываемых данных равному единице).
Адресное пространство контроллера:
|Адрес|Режим доступа|Допустимые значения| Функциональное назначение |
|-----|-------------|-------------------|-----------------------------------------------------------------------------------|
|0x00 | RW | [0:65535] | Чтение и запись в регистр `led_val` отвечающий за вывод данных на светодиоды |
|0x04 | RW | [0:1] | Чтение и запись в регистр `led_mode`, отвечающий за режим "моргания" светодиодами |
|0x24 | W | 1 | Запись сигнала сброса |
### Клавиатура PS/2
Клавиатура [PS/2](https://ru.wikipedia.org/wiki/PS/2_(порт)) осуществляет передачу [скан-кодов](https://ru.wikipedia.org/wiki/Скан-код), нажатых на этой клавиатуре клавиш.
В рамках данной лабораторной работы вам будет дан готовый модуль, осуществляющий прием данных с клавиатуры. От вас требуется написать лишь модуль, осуществляющий контроль предоставленным модулем. У готового модуля будет следующий прототип:
```SystemVerilog
module PS2Receiver(
input clk_i, // Сигнал тактирования процессора и вашего модуля-контроллера
input kclk_i, // Тактовый сигнал, приходящий с клавиатуры
input kdata_i, // Сигнал данных, приходящий с клавиатуры
output [7:0] keycode_o, // Сигнал полученного с клавиатуры скан-кода клавиши
output keycode_valid_o // Сигнал готовности данных на выходе keycodeout
);
endmodule
```
Вам необходимо реализовать модуль-контроллер со следующим прототипом:
```SystemVerilog
module ps2_sb_ctrl(
/*
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i,
input logic [31:0] addr_i,
input logic req_i,
input logic [31:0] write_data_i,
input logic write_enable_i,
output logic [31:0] read_data_o,
/*
Часть интерфейса модуля, отвечающая за отправку запросов на прерывание
процессорного ядра
*/
output logic interrupt_request_o,
input logic interrupt_return_i,
/*
Часть интерфейса модуля, отвечающая за подключение к модулю,
осуществляющему прием данных с клавиатуры
*/
input logic kclk_i,
input logic kdata_i
);
logic [7:0] scan_code;
logic scan_code_is_unread;
endmodule
```
В первую очередь, вы должны создать экземпляр модуля `PS2Receiver` внутри вашего модуля-контроллера, соединив соответствующие входы. Для подключения к выходам необходимо создать дополнительные провода.
По каждому восходящему фронту сигнала `clk_i` вы должны проверять выход `keycode_valid_o` и, если тот равен единице, записать значение с выхода `keycode_o` в регистр `scan_code`. При этом значение регистра `scan_code_is_unread` необходимо выставить в единицу.
В случае, если произошел **запрос на чтение** по адресу `0x00`, необходимо выставить на выход `read_data_o` значение регистра `scan_code` (дополнив старшие биты нулями), при этом значение регистра `scan_code_is_unread` необходимо обнулить. В случае, если одновременно с **запросом на чтение** пришел сигнал `keycode_valid_o`, регистр `scan_code_is_unread` обнулять не нужно (в этот момент в регистр `scan_code` уже записывается новое, еще непрочитанное значение).
Обнуление регистра `scan_code_is_unread` должно происходить и в случае получения сигнала `interrupt_return_i` (однако опять же, если в этот момент приходит сигнал `keycode_valid_o`, обнулять регистр не нужно).
В случае **запроса на чтение** по адресу `0x04` необходимо вернуть значение регистра `scan_code_is_unread`.
В случае **запроса на запись** значения `1` по адресу `0x24`, необходимо осуществить сброс регистров `scan_code` и `scan_code_is_unread` в `0`.
Регистр `scan_code_is_unread` необходимо подключить к выходу `interrupt_request_o`. Таким образом процессор может узнавать о нажатых клавишах как посредством программного опроса путем чтения значения регистра`scan_code_is_unread`, так и посредством прерываний через сигнал`interrupt_request_o`.
Адресное пространство контроллера:
|Адрес|Режим доступа|Допустимые значения| Функциональное назначение |
|-----|-------------|-------------------|-------------------------------------------------------------------------------------------------------------------|
|0x00 | R | [0:255] | Чтение из регистра `scan_code`, хранящего скан-код нажатой клавиши |
|0x04 | R | [0:1] | Чтение из регистра `scan_code_is_unread`, сообщающего о том, что есть непрочитанные данные в регистре `scan_code` |
|0x24 | W | 1 | Запись сигнала сброса |
### Семисегментные индикаторы
Семисегментные индикаторы позволяют выводить арабские цифры и первые шесть букв латинского алфавита, тем самым позволяя отображать шестнадцатеричные цифры. На отладочном стенде `Nexys A7` размещено восемь семисегментных индикаторов. Для вывода цифр на эти индикаторы, вам будет предоставлен модуль `hex_digits`, вам нужно лишь написать модуль, осуществляющий контроль над ним. Прототип модуля `hex_digits` следующий:
```SystemVerilog
module hex_digits(
input logic clk_i,
input logic rst_i,
input logic [3:0] hex0_i, // Цифра, выводимой на нулевой (самый правый) индикатор
input logic [3:0] hex1_i, // Цифра, выводимая на первый индикатор
input logic [3:0] hex2_i, // Цифра, выводимая на второй индикатор
input logic [3:0] hex3_i, // Цифра, выводимая на третий индикатор
input logic [3:0] hex4_i, // Цифра, выводимая на четвертый индикатор
input logic [3:0] hex5_i, // Цифра, выводимая на пятый индикатор
input logic [3:0] hex6_i, // Цифра, выводимая на шестой индикатор
input logic [3:0] hex7_i, // Цифра, выводимая на седьмой индикатор
input logic [7:0] bitmask_i, // Битовая маска для включения/отключения
// отдельных индикаторов
output logic [6:0] hex_led_o, // Сигнал, контролирующий каждый отдельный
// светодиод индикатора
output logic [7:0] hex_sel_o // Сигнал, указывающий на какой индикатор
// выставляется hex_led
);
endmodule
```
Для того, чтобы вывести шестнадцатеричную цифру на любой из индикаторов, необходимо выставить двоичное представление этой цифры на соответствующий вход `hex0-hex7`.
За включение/отключение индикаторов отвечает входной сигнал `bitmask_i`, состоящий из 8 бит, каждый из которых включает/отключает соответствующий индикатор. Например, при `bitmask_i == 8'b0000_0101`, включены будут нулевой и второй индикаторы, остальные будут погашены.
Выходные сигналы `hex_led` и `hex_sel` необходимо просто подключить к соответствующим выходным сигналам модуля-контроллера. Они пойдут на выходы ПЛИС, соединенные с семисегментными индикаторами.
Для управления данным модулем, необходимо написать модуль-контроллер со следующим прототипом:
```SystemVerilog
module hex_sb_ctrl(
/*
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic [31:0] addr_i,
input logic req_i,
input logic [31:0] write_data_i,
input logic write_enable_i,
output logic [31:0] read_data_o,
/*
Часть интерфейса модуля, отвечающая за подключение к модулю,
осуществляющему вывод цифр на семисегментные индикаторы
*/
output logic [6:0] hex_led,
output logic [7:0] hex_sel
);
logic [3:0] hex0, hex1, hex2, hex3, hex4, hex5, hex6, hex7;
logic [7:0] bitmask;
endmodule
```
Регистры `hex0-hex7` отвечают за вывод цифры на соответствующий семисегментный индикатор. Регистр `bitmask` отвечает за включение/отключение семисегментных индикаторов. Когда в регистре `bitmask` бит, индекс которого совпадает с номером индикатора равен единице — тот включен и выводит число, совпадающее со значением в соответствующем регистре `hex0-hex7`. Когда бит равен нулю — этот индикатор гаснет.
Доступ на чтение/запись регистров `hex0-hex7` осуществляется по адресам `0x00-0x1c` (см. таблицу адресного пространства).
Доступ на чтение/запись регистра `bitmask` осуществляется по адресу `0x20`.
При **запросе на запись** единицы по адресу `0x24` необходимо выполнить сброс всех регистров. При этом регистр `bitmask` должен сброситься в значение `0xFF`.
Адресное пространство контроллера:
|Адрес|Режим доступа|Допустимые значения| Функциональное назначение |
|-----|-------------|-------------------|---------------------------------------------------------|
|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 | Запись сигнала сброса |
### UART
[UART](https://ru.wikipedia.org/wiki/Универсальный_асинхронный_приёмопередатчик) — это последовательный интерфейс, использующий для приема и передачи данных по одной независимой линии с поддержкой контроля целостности данных.
Для того, чтобы передача данных была успешно осуществлена, приемник и передатчик на обоих концах одного провода должны договориться о параметрах передачи:
* её скорости (бодрейт);
* контроля целостности данных (использование бита четности/нечетности/отсутствие контроля);
* длины стопового бита.
Вам будут предоставлены модули, осуществляющие прием и передачу данных по этому интерфейсу, от вас лишь требуется написать модули, осуществляющие управление предоставленными модулями.
```SystemVerilog
module uart_rx (
input logic clk_i, // Тактирующий сигнал
input logic rst_i, // Сигнал сброса
input logic rx_i, // Сигнал линии, подключенной к выводу ПЛИС,
// по которой будут приниматься данные
output logic busy_o, // Сигнал о том, что модуль занят приемом данных
input logic [16:0] baudrate_i, // Настройка скорости передачи данных
input logic parity_en_i,// Настройка контроля целостности через бит четности
input logic stopbit_i, // Настройка длины стопового бита
output logic [7:0] rx_data_o, // Принятые данные
output logic rx_valid_o // Сигнал о том, что прием данных завершен
);
endmodule
```
```SystemVerilog
module uart_tx (
input logic clk_i, // Тактирующий сигнал
input logic rst_i, // Сигнал сброса
output logic tx_o, // Сигнал линии, подключенной к выводу ПЛИС,
// по которой будут отправляться данные
output logic busy_o, // Сигнал о том, что модуль занят передачей данных
input logic [16:0] baudrate_i, // Настройка скорости передачи данных
input logic parity_en_i,// Настройка контроля целостности через бит четности
input logic stopbit_i, // Настройка длины стопового бита
input logic [7:0] tx_data_i, // Отправляемые данные
input logic tx_valid_i // Сигнал о старте передачи данных
);
endmodule
```
Для управления этими модулями вам необходимо написать два модуля-контроллера со следующими прототипами
```SystemVerilog
module uart_rx_sb_ctrl(
/*
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i,
input logic [31:0] addr_i,
input logic req_i,
input logic [31:0] write_data_i,
input logic write_enable_i,
output logic [31:0] read_data_o,
/*
Часть интерфейса модуля, отвечающая за отправку запросов на прерывание
процессорного ядра
*/
output logic interrupt_request_o,
input logic interrupt_return_i,
/*
Часть интерфейса модуля, отвечающая за подключение передающему,
входные данные по UART
*/
input logic rx_i
);
logic busy;
logic [16:0] baudrate;
logic parity_en;
logic stopbit;
logic [7:0] data;
logic valid;
endmodule
```
```SystemVerilog
module uart_tx_sb_ctrl(
/*
Часть интерфейса модуля, отвечающая за подключение к системной шине
*/
input logic clk_i,
input logic rst_i,
input logic [31:0] addr_i,
input logic req_i,
input logic [31:0] write_data_i,
input logic write_enable_i,
output logic [31:0] read_data_o,
/*
Часть интерфейса модуля, отвечающая за подключение передающему,
выходные данные по UART
*/
output logic tx_o
);
logic busy;
logic [16:0] baudrate;
logic parity_en;
logic stopbit;
logic [7:0] data;
endmodule
```
У обоих предоставленных модулей схожий прототип, различия заключаются лишь в направлениях сигналов `data` и `valid`.
Взаимодействие модулей `uart_rx` и `uart_tx` с соответствующими модулями-контроллерами осуществляется следующим образом.
Сигналы `clk_i` и `rx_i`/`tx_o` подключаются напрямую к соответствующим сигналам модулей-контроллеров.
Сигнал `rst_i` модулей `uart_rx` / `uart_tx` должен быть равен единице при **запросе на запись** единицы по адресу `0x24`, а также в случае, когда сигнал `rst_i` модуля-контроллера равен единице.
Выходной сигнал `busy_o` на каждом такте `clk_i` должен записываться в регистр `busy`, доступ на чтение к которому осуществляется по адресу `0x08`.
Значения входных сигналов `baudrate_i`, `parity_en_i`, `stopbit_i` берутся из соответствующих регистров, доступ на запись к которым осуществляется по адресам `0x0C`, `0x10`, `0x14` соответственно, но только в моменты, когда выходной сигнал `busy_o` равен нулю. Иными словами, изменение настроек передачи возможно только в моменты, когда передача не происходит. Доступ на чтение этих регистров может осуществляться в любой момент времени.
В регистр `data` модуля `uart_rx_sb_ctrl` записывается значение одноименного выхода модуля `uart_rx` в моменты положительного фронта `clk_i`, когда сигнал `rx_valid_o` равен единице. Доступ на чтение этого регистра осуществляется по адресу `0x00`.
В регистр `valid` модуля `uart_rx_sb_ctrl` записывается единица по положительному фронту clk_i, когда выход `rx_valid_o` равен единице. Данный регистр сбрасывается в ноль при выполнении **запроса на чтение** по адресу `0x00`, а также при получении сигнала `interrupt_return_i`. Сам регистр доступен для чтения по адресу `0x04`. Регистр `valid` подключается к выходу `interrupt_request_o`. Что позволяет узнать о пришедших данных и посредством прерывания.
На вход `tx_data_i` модуля `uart_tx` подаются данные из регистра `data` модуля `uart_tx_sb_ctrl`. Доступ на запись в этот регистр происходит по адресу `0x00` в моменты положительного фронта `clk_i`, когда сигнал `busy_o` равен нулю. Доступ на чтение этого регистра может осуществляться в любой момент времени.
На вход `tx_valid_i` модуля `uart_tx` подается единица в момент выполнения **запроса на запись** по адресу `0x00` (при сигнале `busy` равном нулю). В остальное время на вход этого сигнала подается `0`.
В случае **запроса на запись** значения `1` по адресу `0x24` (адресу сброса), все регистры модуля-контроллера должны сброситься. При этом регистр `baudrate` должен принять значение `9600`, регистр `parity` должен принять значение `1`, регистр, `stopbit` должен принять значение `1`. Остальные регистры должны принять значение `0`.
Адресное пространство контроллера `uart_rx_sb_ctrl`:
|Адрес|Режим доступа|Допустимые значения| Функциональное назначение |
|-----|-------------|-------------------|---------------------------------------------------------------------------------------------------------|
|0x00 | R | [0:255] | Чтение из регистра `data`, хранящего значение принятых данных |
|0x04 | R | [0:1] | Чтение из регистра `valid`, сообщающего о том, что есть непрочитанные данные в регистре `data` |
|0x08 | R | [0:1] | Чтение из регистра `busy`, сообщающего о том, что модуль находится в процессе приема данных |
|0x0C | RW | [0:65535] | Чтение/запись регистра `baudrate`, отвечающего за скорость передачи данных |
|0x10 | RW | [0:1] | Чтение/запись регистра `parity`, отвечающего за включение отключение проверки данных через бит четности |
|0x14 | RW | [0:1] | Чтение/запись регистра `stopbit`, отвечающего за длину стопового бита |
|0x24 | W | 1 | Запись сигнала сброса |
Адресное пространство контроллера `uart_tx_sb_ctrl`:
|Адрес|Режим доступа|Допустимые значения| Функциональное назначение |
|-----|-------------|-------------------|---------------------------------------------------------------------------------------------------------|
|0x00 | RW | [0:255] | Чтение и запись регистра `data`, хранящего значение отправляемых данных |
|0x08 | R | [0:1] | Чтение из регистра `busy`, сообщающего о том, что модуль находится в процессе передачи данных |
|0x0C | RW | [0:65535] | Чтение/запись регистра `baudrate`, отвечающего за скорость передачи данных |
|0x10 | RW | [0:1] | Чтение/запись регистра `parity`, отвечающего за включение отключение проверки данных через бит четности |
|0x14 | RW | [0:1] | Чтение/запись регистра `stopbit`, отвечающего за длину стопового бита |
|0x24 | W | 1 | Запись сигнала сброса |
### Видеоадаптер
Видеоадаптер позволяет выводить информацию на экран через интерфейс **VGA**. Предоставляемый в данной лабораторной работе vga-модуль способен выводить `80х30` символов (разрешение символа `8x16`). Таким образом, итоговое разрешение экрана, поддерживаемого vga-модулем будет `80*8 x 30*16 = 640x480`. VGA-модуль поддерживает управление цветовой схемой для каждого поля символа в сетке `80х30`. Это значит, что каждый символ (и фон символа) может быть отрисован отдельным цветом из диапазона 16-ти цветов.
![https://upload.wikimedia.org/wikipedia/commons/c/cf/RebelstarII.png](https://upload.wikimedia.org/wikipedia/commons/c/cf/RebelstarII.png)
_Рисунок 3. Пример игры с использованием символьной графики[[2]](https://en.wikipedia.org/wiki/Rebelstar)._
Для управления выводимым на экран содержимым, адресное пространство модуля разделено на следующие диапазоны:
![../../.pic/Labs/lab_13_periph/fig_04.png](../../.pic/Labs/lab_13_periph/fig_04.png)
_Рисунок 4. Карта памяти vga-модуля._
Для того, чтобы вывести символ на экран, необходимо использовать адрес этого символа на сетке `80x30` (диапазон адресов `char_map`). К примеру, мы хотим вывести символ в верхнем левом углу. Это нулевой символ в диапазоне адресов `char_map`. Поскольку данный диапазон начинается с адреса `0x0000_0000`, запись по этому адресу приведет к отображению символа, соответствующего [ASCII-коду](https://www.asciitable.com/), пришедшему на `write_data_i`.
Если мы хотим вывести нулевой (левый) символ в первой строке (счет ведется с нуля), то необходимо произвести запись по адресу `1*80+0=80=0x0000_0050`.
Вывод символа в правом нижнем углу осуществляется записью по адресу `0x0000_095F` (80*30-1)
Установка цветовой схемы осуществляется по тем же самым адресам, к которым прибавлено значение `0x0000_1000`:
* верхний левый символ — `0x0000_1000`
* нулевой символ первой строки — `0x0000_1050`
* нижний правый символ — `0x0000_195F`
Цветовая схема каждой позиции состоит из двух цветов: цвета фона и цвета символа. Оба эти цвета выбираются из палитры 8 цветов, каждый из которых содержит два оттенка: цвет на полной яркости и цвет на уменьшенной яркости (см. рис. 5). Один из цветов — черный, оба его оттенка представляют собой один и тот же цвет. Ниже приведены коды цветов их rgb-значения:
![../../.pic/Labs/lab_13_periph/fig_05.png](../../.pic/Labs/lab_13_periph/fig_05.png)
_Рисунок 5. Цветовая палитра vga-модуля._
Код цвета формируется следующим образом: старший бит определяет яркость оттенка цвета. Оставшиеся 3 бита кодируют используемый канал:
* 0 бит кодирует использование синего канала;
* 1 бит кодирует использование зеленого канала;
* 2 бит кодирует использование красного канала.
Таким образом, для установки цветовой схемы, необходимо выбрать два цвета из палитры, склеить их (в старших разрядах идет цвет символа, в младших — цвет фона) и записать получившееся 8-битное значение по адресу выбранной позиции в диапазоне адресов цветовой схемы (color_map).
К примеру, мы хотим установить черный фоновый цвет и белый цвет в качестве цвета символа для верхней левой позиции. В этом случае, мы должны записать значение `f0` (f(15) — код белого цвета, 0 — код черного цвета) по адресу `0x0000_1000` (нулевой адрес в диапазоне `color_map`).
Для отрисовки символов, мы условно поделили экран на сетку `80х30`, и для каждой позиции в этой сетке определили фоновый и активный цвет. Чтобы модуль мог отрисовать символ на очередной позиции (которая занимает `16х8` пикселей), ему необходимо знать в какой цвет необходимо окрасить каждый пиксель для каждого ascii-кода. Для этого используется память шрифтов.
Допустим, нам необходимо отрисовать символ `F` (ascii-код `0x46`).
![../../.pic/Labs/lab_13_periph/fig_06.png](../../.pic/Labs/lab_13_periph/fig_06.png)
_Рисунок 6. Отрисовка символа `F` в разрешении 16х8 пикселей._
Данный символ состоит из 16 строчек по 8 пикселей. Каждый пиксель кодируется одним битом (горит/не горит, цвет символа/фоновый цвет). Каждая строчка кодируется одним байтом (8 бит на 8 пикселей). Таким образом, каждый сканкод требует 16 байт памяти.
Данный модуль поддерживает 256 сканкодов. Следовательно, для хранения шрифта под каждый из 256 сканкодов требуется 16 * 256 = 4KiB памяти.
Для хранения шрифтов в модуле отведен диапазон адресов `0x00002000-0x00002FFF`. В отличие от предыдущих диапазонов адресов, где каждый адрес был закреплен за соответствующей позицией символа в сетке `80x30`, адреса данного диапазона распределены следующим образом:
* 0-ой байт — нулевая (верхняя) строчка символа с кодом 0;
* 1-ый байт — первая строчка символа с кодом 0;
* ...
* 15-ый байт — пятнадцатая (нижняя) строчка символа с кодом 0;
* 16-ый байт — нулевая (верхняя) строчка символа с кодом 1;
* ...
* 4095-ый байт — пятнадцатая (нижняя) строчка символа с кодом 255.
Прототип vga-модуля следующий:
```SystemVerilog
module vgachargen (
input logic clk_i, // системный синхроимпульс
input logic clk100m_i, // клок с частотой 100МГц
input logic rst_i, // сигнал сброса
/*
Интерфейс записи выводимого символа
*/
input logic [ 9:0] char_map_addr_i, // адрес позиции выводимого символа
input logic char_map_we_i, // сигнал разрешения записи кода
input logic [ 3:0] char_map_be_i, // сигнал выбора байтов для записи
input logic [31:0] char_map_wdata_i, // ascii-код выводимого символа
output logic [31:0] char_map_rdata_o, // сигнал чтения кода символа
/*
Интерфейс установки цветовой схемы
*/
input logic [ 9:0] col_map_addr_i, // адрес позиции устанавливаемой схемы
input logic col_map_we_i, // сигнал разрешения записи схемы
input logic [ 3:0] col_map_be_i, // сигнал выбора байтов для записи
input logic [31:0] col_map_wdata_i, // код устанавливаемой цветовой схемы
output logic [31:0] col_map_rdata_o, // сигнал чтения кода схемы
/*
Интерфейс установки шрифта
*/
input logic [ 9:0] char_tiff_addr_i, // адрес позиции устанавливаемого шрифта
input logic char_tiff_we_i, // сигнал разрешения записи шрифта
input logic [ 3:0] char_tiff_be_i, // сигнал выбора байтов для записи
input logic [31:0] char_tiff_wdata_i,// отображаемые пиксели в текущей позиции шрифта
output logic [31:0] char_tiff_rdata_o,// сигнал чтения пикселей шрифта
output logic [3:0] vga_r_o, // красный канал vga
output logic [3:0] vga_g_o, // зеленый канал vga
output logic [3:0] vga_b_o, // синий канал vga
output logic vga_hs_o, // линия горизонтальной синхронизации vga
output logic vga_vs_o // линия вертикальной синхронизации vga
);
```
Файлы модуля:
* peripheral modules/vhachargen.sv
* peripheral modules/vhachargen_pkg.sv
* firmware/mem_files/lab_12_ps2_vga_instr.mem — этим файлом необходимо проинициализировать память инструкций
* firmware/mem_files/lab_12_ps2ascii_data.mem — этим файлом необходимо проинициализировать память данных
* firmware/mem_files/lab_12_vga_ch_map.mem
* firmware/mem_files/lab_12_vga_ch_t_ro.mem
* firmware/mem_files/lab_12_vga_ch_t_rw.mem
* firmware/mem_files/lab_12_vga_col_map.mem
Вам необходимо добавить в проект все эти файлы.
Для управления данным модулем, необходимо написать модуль-контроллер со следующим прототипом:
```SystemVerilog
module vga_sb_ctrl (
input logic clk_i,
input logic rst_i,
input logic clk100m_i,
input logic req_i,
input logic write_enable_i,
input logic [3:0] mem_be_i,
input logic [31:0] addr_i,
input logic [31:0] write_data_i,
output logic [31:0] read_data_o,
output logic [3:0] vga_r_o,
output logic [3:0] vga_g_o,
output logic [3:0] vga_b_o,
output logic vga_hs_o,
output logic vga_vs_o
);
```
Реализация данного модуля исключительно простая. В первую очередь необходимо подключить одноименные сигналы напрямую:
* `clk_i`,
* `rst_i`,
* `clk100m_i`,
* `vga_r_o`,
* `vga_g_o`,
* `vga_b_o`,
* `vga_hs_o`,
* `vga_vs_o`
Кроме того, необходимо:
1. подключить напрямую сигнал `write_data_i` ко входам:
1. `char_map_wdata_i`,
2. `col_map_wdata_i`,
3. `char_tff_wdata_i`,
2. подключить биты `addr_i[11:2]` ко входам:
1. `char_map_addr_i`,
2. `col_map_addr_i`,
3. `char_tiff_addr_i`,
3. сигнал `mem_be_i` подключить ко входам:
1. `char_map_be_i`,
2. `col_map_be_i`,
3. `char_tiff_be_i`.
Остается только разобраться с сигналами `write_enable_i` и `read_data_o`.
Оба эти сигнала мультиплексируются / демультиплексируются с помощью одного и того же управляющего сигнала: `addr_i[13:12]` в соответствии с диапазонами адресов (рис. 4):
* `addr_i[13:12] == 2'b00` — сигнал `write_enable_i` поступает на вход `char_map_we_i`, выход `char_map_rdata_o` записывается в выходной регистр `read_data_o`;
* `addr_i[13:12] == 2'b01` — сигнал `write_enable_i` поступает на вход `col_map_we_i`, выход `col_map_rdata_o` записывается в выходной регистр `read_data_o`;
* `addr_i[13:12] == 2'b10` — сигнал `write_enable_i` поступает на вход `char_tiff_we_i`, выход `char_tiff_rdata_o` записывается в выходной регистр `read_data_o`.
## Список использованной литературы
1. С.А. Орлов, Б.Я. Цилькер / Организация ЭВМ и систем: Учебник для вузов. 2-е изд. / СПб.: Питер, 2011.
2. [Rebelstar](https://en.wikipedia.org/wiki/Rebelstar)

View File

@@ -0,0 +1,599 @@
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958
5f5e5d5c
63626160
67666564
6b6a6968
6f6e6d6c
73727170
77767574
7b7a7978
7f7e7d7c
03020100
07060504
0b0a0908
0f0e0d0c
13121110
17161514
1b1a1918
1f1e1d1c
23222120
27262524
2b2a2928
2f2e2d2c
33323130
37363534
3b3a3938
3f3e3d3c
43424140
47464544
4b4a4948
4f4e4d4c
53525150
57565554
5b5a5958

View File

@@ -0,0 +1,128 @@
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00011110000100000001000000010000000100000001000000010000000100000001000000010000000111100000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000010000000100000000000000010000000100000001000000010000000100000001000000010000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000101000001010000000000000000
00000000000000000000000000000000000100100001001000111111000100100001001000010010001111110001001000010010000000000000000000000000
00000000000000000000000000000100000011100001000100010001000100000001000000001110000000010001000100010001000011100000010000000000
00000000000000000000000000100000010100000101000100100010000001000000100000010000001000100100010100000101000000100000000000000000
00000000000000000000000000000000010011100011000100100001001100010100101001001100000100100001001000010010000011000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000010000000100000000000000000
00000000000000000000000000000100000000100000000100000001000000010000000100000001000000010000000100000010000001000000000000000000
00000000000000000000000000000001000000100000010000000100000001000000010000000100000001000000010000000010000000010000000000000000
00000000000000000000000000000000000000000000000000010010000011000011111100001100000100100000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000100000001000001111100000100000001000000000000000000000000000000000000000000
00000000000000000000000000000001000000100000001000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000010000000100000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000010000000100000010000000100000010000000100000010000000100000010000000100000000000000000000
00000000000000000000000000000000000111100010000100100011001001010010010100101001001010010011000100100001000111100000000000000000
00000000000000000000000000000000000010000000100000001000000010000000100000001000000010010000101000001100000010000000000000000000
00000000000000000000000000000000001111110000000100000001000000100000010000001000000100000010000000100001000111100000000000000000
00000000000000000000000000000000000111100010000100100000001000000010000000011100001000000010000000100001000111100000000000000000
00000000000000000000000000000000000100000001000000010000000100000011111100010001000100100001010000011000000100000000000000000000
00000000000000000000000000000000000111100010000100100000001000000010000000011111000000010000000100000001001111110000000000000000
00000000000000000000000000000000000111100010000100100001001000010010000100011111000000010000000100000010000111000000000000000000
00000000000000000000000000000000000001000000010000000100000001000000100000010000001000000010000000100000001111110000000000000000
00000000000000000000000000000000000111100010000100100001001000010010000100011110001000010010000100100001000111100000000000000000
00000000000000000000000000000000000111100010000100100000001000000010000000111110001000010010000100100001000111100000000000000000
00000000000000000000000000000000000000010000000100000000000000000000000000000001000000010000000000000000000000000000000000000000
00000000000000000000000000000001000000100000001000000000000000000000000000000010000000100000000000000000000000000000000000000000
00000000000000000000000000000000000100000000100000000100000000100000000100000010000001000000100000010000000000000000000000000000
00000000000000000000000000000000000000000000000000000000001111110000000000111111000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000010000001000000100000010000001000000001000000001000000001000000001000000000000000000000000
00000000000000000000000000000000000001000000010000000000000001000000100000010000001000000010000100100001000111100000000000000000
00000000000000000000000000000000011111000000001001111001101001011011100110100001100110010100001000111100000000000000000000000000
00000000000000000000000000000000001000010010000100100001001000010011111100100001001000010010000100100001000111100000000000000000
00000000000000000000000000000000000111110010000100100001001000010010000100011111001000010010000100100001000111110000000000000000
00000000000000000000000000000000000111100010000100000001000000010000000100000001000000010000000100100001000111100000000000000000
00000000000000000000000000000000000011110001000100100001001000010010000100100001001000010010000100010001000011110000000000000000
00000000000000000000000000000000001111110000000100000001000000010000000100001111000000010000000100000001001111110000000000000000
00000000000000000000000000000000000000010000000100000001000000010000000100001111000000010000000100000001001111110000000000000000
00000000000000000000000000000000000111100010000100100001001000010011100100000001000000010000000100100001000111100000000000000000
00000000000000000000000000000000001000010010000100100001001000010010000100111111001000010010000100100001001000010000000000000000
00000000000000000000000000000000000000010000000100000001000000010000000100000001000000010000000100000001000000010000000000000000
00000000000000000000000000000000000111100010000100100001001000000010000000100000001000000010000000100000001000000000000000000000
00000000000000000000000000000000001000010010000100100001000100010000100100000111000010010001000100100001001000010000000000000000
00000000000000000000000000000000001111110000000100000001000000010000000100000001000000010000000100000001000000010000000000000000
00000000000000000000000000000000010000010100000101000001010000010100000101001001010010010101010101100011010000010000000000000000
00000000000000000000000000000000001000010010000100100001001000010010000100110001001010010010010100100011001000010000000000000000
00000000000000000000000000000000000111100010000100100001001000010010000100100001001000010010000100100001000111100000000000000000
00000000000000000000000000000000000000010000000100000001000000010000000100011111001000010010000100100001000111110000000000000000
00000000000000000000000000100000001111100011000100101001001000010010000100100001001000010010000100100001000111100000000000000000
00000000000000000000000000000000001000010010000100100001001000010001000100011111001000010010000100100001000111110000000000000000
00000000000000000000000000000000000111100010000100100000001000000001000000001100000000100000000100100001000111100000000000000000
00000000000000000000000000000000000010000000100000001000000010000000100000001000000010000000100000001000011111110000000000000000
00000000000000000000000000000000000111100010000100100001001000010010000100100001001000010010000100100001001000010000000000000000
00000000000000000000000000000000000010000000100000010100000101000010001000100010010000010100000101000001010000010000000000000000
00000000000000000000000000000000010000010110001101010101010010010100100101001001010000010100000101000001010000010000000000000000
00000000000000000000000000000000001000010010000100100001000100100000110000001100000100100010000100100001001000010000000000000000
00000000000000000000000000000000000010000000100000001000000010000000100000010100001000100010001001000001010000010000000000000000
00000000000000000000000000000000001111110000000100000001000000100000010000001000000100000010000000100000001111110000000000000000
00000000000000000000000000000111000000010000000100000001000000010000000100000001000000010000000100000001000001110000000000000000
00000000000000000000000000000000000100000001000000001000000010000000010000000100000000100000001000000001000000010000000000000000
00000000000000000000000000000111000001000000010000000100000001000000010000000100000001000000010000000100000001110000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001000010100000010000000000
00000000000000000011111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000001000000010000000000000000
00000000000000000000000000000000001111100010000100100001001000010011111000100000000111100000000000000000000000000000000000000000
00000000000000000000000000000000000111110010000100100001001000010010000100100001000111110000000100000001000000010000000000000000
00000000000000000000000000000000000111100010000100000001000000010000000100100001000111100000000000000000000000000000000000000000
00000000000000000000000000000000001111100010000100100001001000010010000100100001001111100010000000100000001000000000000000000000
00000000000000000000000000000000000111100010000100000001001111110010000100100001000111100000000000000000000000000000000000000000
00000000000000000000000000000000000000100000001000000010000000100000001000001111000000100000001000100010000111000000000000000000
00000000000111100010000100100000001011100011000100100001001000010010000100100001000111100000000000000000000000000000000000000000
00000000000000000000000000000000001000010010000100100001001000010010000100100001000111110000000100000001000000010000000000000000
00000000000000000000000000000000000000010000000100000001000000010000000100000001000000010000000000000001000000000000000000000000
00000000000011100001000100010001000100000001000000010000000100000001000000010000000100000000000000010000000000000000000000000000
00000000000000000000000000000000001000010010000100010001000011110001000100100001001000010000000100000001000000010000000000000000
00000000000000000000000000000000000000100000000100000001000000010000000100000001000000010000000100000001000000010000000000000000
00000000000000000000000000000000010000010100100101001001010010010100100101001001001101110000000000000000000000000000000000000000
00000000000000000000000000000000001000010010000100100001001000010010000100100001000111110000000000000000000000000000000000000000
00000000000000000000000000000000000111100010000100100001001000010010000100100001000111100000000000000000000000000000000000000000
00000000000000010000000100000001000111110010000100100001001000010010000100100001000111110000000000000000000000000000000000000000
00000000001000000010000000100000001111100010000100100001001000010010000100100001001111100000000000000000000000000000000000000000
00000000000000000000000000000000000000010000000100000001000000010000000100000011000111010000000000000000000000000000000000000000
00000000000000000000000000000000000111100010000100100000000111100000000100100001000111100000000000000000000000000000000000000000
00000000000000000000000000000000000110000000010000000100000001000000010000000100000111110000010000000100000000000000000000000000
00000000000000000000000000000000001111100010000100100001001000010010000100100001001000010000000000000000000000000000000000000000
00000000000000000000000000000000000010000001010000010100001000100010001001000001010000010000000000000000000000000000000000000000
00000000000000000000000000000000001000100101010101001001010010010100100101000001010000010000000000000000000000000000000000000000
00000000000000000000000000000000010000010010001000010100000010000001010000100010010000010000000000000000000000000000000000000000
00000000000011110001000000100000001011100011000100100001001000010010000100100001001000010000000000000000000000000000000000000000
00000000000000000000000000000000001111110000000100000010000001000000100000010000001111110000000000000000000000000000000000000000
00000000000000000000000000011000000001000000010000000100000001000000001100000100000001000000010000000100000110000000000000000000
00000000000000000000000000000000000000010000000100000001000000010000000100000000000000010000000100000001000000010000000000000000
00000000000000000000000000000011000001000000010000000100000001000001100000000100000001000000010000000100000000110000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011001001001100000000000000000
00000000000000000000000001100000001000000010000000101100000001000000110000001100000000000000001100000101000001010000001100000000

View File

@@ -0,0 +1,33 @@
00000000000000000000000000000000000000000000000000000000000000000000000001000010010000100111111001000010001001000010010000011000
00000000000000000000000000000000000000000000000000000000000000000000000000111110010000100100001000111110000000100000001000111110
00000000000000000000000000000000000000000000000000000000000000000000000000111110010000100100001000111110001000100010001000011110
00000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000001000000010000000100000001001111110
00000000000000000000000000000000000000000000000000000000000000000100000101111111001000010010001000100010001001000010010000111100
00000000000000000000000000000000000000000000000000000000000000000000000001111110000000100000001000011110000000100000001001111110
00000000000000000000000000000000000000000000000000000000000000000000000001111110000000100000001000011110000000100111111000100100
00000000000000000000000000000000000000000000000000000000000000000000000001001001010010010010101000011100001010100100100101001001
00000000000000000000000000000000000000000000000000000000000000000000000000111100010000100100000000111000010000000100010000111000
00000000000000000000000000000000000000000000000000000000000000000000000001000110010010100100101001010010010100100110001001100010
00000000000000000000000000000000000000000000000000000000000000000000000001000110010010100101001001100010010000100001100000100100
00000000000000000000000000000000000000000000000000000000000000000000000001000010001000100010001000011110000010100001001000100010
00000000000000000000000000000000000000000000000000000000000000000000000001000010010000100100010001000100010010000100100001111000
00000000000000000000000000000000000000000000000000000000000000000000000001001001010010010101010101010101011000110110001101000001
00000000000000000000000000000000000000000000000000000000000000000000000001000010010000100100001001111110010000100100001001000010
00000000000000000000000000000000000000000000000000000000000000000000000000011100001000100100001001000010010000100100010000111000
00000000000000000000000000000000000000000000000000000000000000000000000001000010010000100100001001000010010000100100001001111110
00000000000000000000000000000000000000000000000000000000000000000000000000000010000000100001111000100010010000100100001000111110
00000000000000000000000000000000000000000000000000000000000000000000000000111000010001000000001000000010000000100100010000111000
00000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000100000001000000010000000100001111111
00000000000000000000000000000000000000000000000000000000000000000000000000000010000001000000100000011000001001000100001001000010
00000000000000000000000000000000000000000000000000000000000000000000000000001000001111100100100101001001010010010011111000001000
00000000000000000000000000000000000000000000000000000000000000000000000001000010010000100010010000011000001001000100001001000010
00000000000000000000000000000000000000000000000000000000000000000100000001111110001000100010001000100010001000100010001000100010
00000000000000000000000000000000000000000000000000000000000000000000000001000000010000000101110001100010010000100100001001000010
00000000000000000000000000000000000000000000000000000000000000000000000001111111010010010100100101001001010010010100100101001001
00000000000000000000000000000000000000000000000000000000000000000100000001111111010010010100100101001001010010010100100101001001
00000000000000000000000000000000000000000000000000000000000000000000000000111100010001000100010001000100001111000000010000000111
00000000000000000000000000000000000000000000000000000000000000000000000001001111010100010101000101010001010011110100000101000001
00000000000000000000000000000000000000000000000000000000000000000000000000011110001000100010001000100010000111100000001000000010
00000000000000000000000000000000000000000000000000000000000000000000000000011100001000100100000001111000010000000010001000011100
00000000000000000000000000000000000000000000000000000000000000000000000000011001001001010100010101000111010001010100100100110001
00000000000000000000000000000000000000000000000000000000000000000000000001000010010001000111110001000010010000100100010001111000

View File

@@ -0,0 +1,600 @@
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0
a0a0a0a0

View File

@@ -0,0 +1,43 @@
030000b7
04000137
0e000193
0f000213
00e00413
00f00493
00000593
00100293
30429073
03400293
00028293
30529073
00000063
0000a383
04338263
04438c63
00700333
00435313
00612223
00f3f393
00712023
00b04c63
00012a23
00012823
00012623
00012423
00300513
000005b3
00356513
02a12023
30200073
00812a23
00012823
03056513
02a12023
00158593
30200073
00912623
00012423
00c56513
02a12023
00158593
30200073

View File

@@ -0,0 +1,17 @@
030000b7
07000137
070011b7
96018193
00100293
30429073
02400293
30529073
00000063
0000a383
00038403
00810023
00110113
00315463
30200073
07000137
30200073

View File

@@ -0,0 +1,23 @@
00000000
00000000
00000000
007E0900
00000000
00317100
737A0000
00327761
64786300
00333465
66762000
00357274
68626E00
00367967
6A6D0000
00383775
696B2C00
0039306F
6C2F2E00
002D703B
00270000
00003D5B
5D0D0000

View File

@@ -0,0 +1,20 @@
050000b7
04000137
0001c1b7
20018193
0030a623
00100213
0040a823
00100293
30429073
03400293
00028293
30529073
00000063
0000a383
00700333
00435313
00612223
00f3f393
00712023
30200073

View File

@@ -0,0 +1,31 @@
050000b7
02000137
0001c1b7
20018193
0030a623
00100213
0040a823
000011b7
d0d18193
00008237
f7f20213
0ff00493
00100313
00100293
30429073
04c00293
00028293
30529073
00000063
0000a383
00947433
00841413
00746433
00340863
00440a63
00812023
30200073
00612223
30200073
02612223
30200073

View File

@@ -0,0 +1,18 @@
050000b7
06000137
0001c1b7
20018193
0030a623
00312623
00100213
0040a823
00412823
00100293
30429073
03c00293
00028293
30529073
00000063
0000a383
00712023
30200073

View File

@@ -0,0 +1,22 @@
010000b7
02000137
0000b1b7
aaa18193
00005237
55520213
00100313
00100293
30429073
03400293
00028293
30529073
00000063
0000a383
00338863
00438a63
00712023
30200073
00612223
30200073
02612223
30200073

View File

@@ -0,0 +1,65 @@
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1 , 0x03000000 # сохраняем базовый адрес клавиатуры
4: 04000137 li x2 , 0x04000000 # сохраняем базовый адрес хекс-контроллера
8: 0e000193 li x3 , 0x000000e0 # сохраняем сканкод e0
c: 0f000213 li x4 , 0x000000f0 # сохраняем сканкод f0
10: 00e00413 li x8 , 0x0000000e # сохраняем значение e
14: 00f00493 li x9 , 0x0000000f # сохраняем значение f
18: 00000593 li x11, 0x00000000 # сохраняем ноль
1c: 00100293 li x5 , 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
34: 0000a383 lw x7, 0(x1) # загружаем сканкод
38: 04338263 beq x7, x3, print_e0 # если сканкод e0, отображаем с помощью print_e0
3c: 04438c63 beq x7, x4, print_f0 # если сканкод f0, отображаем с помощью print_f0
40: 00700333 add x6, x0, x7 # дублируем сканкод
44: 00435313 srl x6, x6, 4 # сдвигаем на 4, чтобы получить старший нибл
48: 00612223 sw x6, 4(x2) # записываем старший нибл в первый семисегментник
4c: 00f3f393 andi x7, x7, 0xf # маскируем с f, чтобы получить младший нибл
50: 00712023 sw x7, 0(x2) # записываем младший нибл в нулевой семисегментник
54: 00b04c63 blt x0, x11, print_code # пропускаем обнуление старших хексов
58: 00012a23 sw x0, 20(x2)
5c: 00012823 sw x0, 16(x2) # обнуляем 2-5 семисегментники
60: 00012623 sw x0, 12(x2)
64: 00012423 sw x0, 8(x2)
68: 00300513 addi x10, x0, 3
print_code:
6c: 000005b3 add x11, x0, x0 # обнуляем счетчик
70: 00356513 ori x10, x10, 3 # инициализируем маску, включающую 2 младших хекса
74: 02a12023 sw x10, 32(x2) # записываем маску
78: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
print_e0:
7c: 00812a23 sw x8, 20(x2) # записываем e в 5ый семисегментник
80: 00012823 sw x0, 16(x2) # записываем 0 в 4ый семисегментник
84: 03056513 ori x10, x10, 0x30 # включаем отображение 4-5 хексов в маске
88: 02a12023 sw x10, 32(x2) # записываем маску
8c: 00158593 addi x11, x11, 1 # инкрементируем счетчик
90: 30200073 mret
print_f0:
94: 00912623 sw x9, 12(x2) # записываем f в 3ый семисегментник
98: 00012423 sw x0, 8(x2) # записываем 0 в 2ый семисегментник
9c: 00c56513 ori x10, x10, 0xc # включаем отображение 3-2 хексов в маске
a0: 02a12023 sw x10, 32(x2) # записываем маску
a4: 00158593 addi x11, x11, 1 # инкрементируем счетчик
a8: 30200073 mret

View File

@@ -0,0 +1,37 @@
_start:
# Инициализируем начальные значения регистров
0: 030000b7 li x1, 0x03000000 # сохраняем базовый адрес клавиатуры
4: 07000137 li x2, 0x07000000 # сохраняем базовый адрес vga-контроллера
8: 070011b7 li x3, 0x07000960 # количество символов на экране
c: # данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
10: 96018193 li x5, 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
14: 00100293 csrw mie, x5 # загружаем маску в регистр маски
18: 30429073 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
# только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
1c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
20: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
24: 0000a383 lw x7, 0(x1) # загружаем сканкод
28: 00038403 lb x8, 0(x7) # берем данные из таблицы подстановки
2c: 00812023 sw x8, 0(x2) # загружаем ascii-значение в vga
30: 00110113 addi x2, x2, 1 # инкрементируем адрес vga
34: 00315463 bge x2, x3, wrap_addr # если адрес vga вышел за границы, то обнуляем
38: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
wrap_addr:
3c: 07000137 li x2, 0x07000000 # сохраняем базовый адрес vga-контроллера
40: 30200073 mret

View File

@@ -0,0 +1,34 @@
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1 , 0x05000000 # сохраняем базовый адрес uart_rx
4: 04000137 li x2 , 0x04000000 # сохраняем базовый адрес хекс-контроллера
8: 0001c1b7 li x3 , 0x0001c200 # устанавливаем бодрейт 115200
c: 20018193
10: 0030a623 sw x3 , 0x0c(x1)
14: 00100213 li x4 , 0x00000001 # устанавливаем parity_bit
18: 0030a823 sw x4 , 0x10(x1)
1c: 00100293 li x5 , 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
34: 0000a383 lw x7, 0(x1) # загружаем пришедший байт
38: 00700333 add x6, x0, x7 # дублируем сканкод
3c: 00435313 srl x6, x6, 4 # сдвигаем на 4, чтобы получить старший нибл
40: 00612223 sw x6, 4(x2) # записываем старший нибл в первый семисегментник
44: 00f3f393 andi x7, x7, 0xf # маскируем с f, чтобы получить младший нибл
48: 00712023 sw x7, 0(x2) # записываем младший нибл в нулевой семисегментник
4c: 30200073 mret

View File

@@ -0,0 +1,50 @@
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1, 0x05000000 # сохраняем базовый адрес uart_rx
4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов
8: 0001c1b7 li x3, 0x0001c200 # устанавливаем бодрейт 115200
c: 20018193
10: 0030a623 sw x3, 0x0c(x1)
14: 00100213 li x4, 0x00000001 # устанавливаем parity_bit
18: 0040a823 sw x4, 0x10(x1)
1c: 000011b7 li x3, 0x00000D0D # сохраняем спец-код для режима моргания
20: d0d18193
24: 00008237 li x4, 0x00000808 # сохраняем спец-код для сброса
28: f7f20213
2c: 0ff00493 li x9, 0x000000ff # сохраняем маску для обнуления старшей части
30: 00100313 li x6, 0x00000001 # сохраняем единицу
34: 00100293 li x5, 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
38: 30429073 csrw mie, x5 # загружаем маску в регистр маски
3c: 04c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
40: 00028293 # только в случае la это число является адресом
40: 00028293 # указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
44: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
48: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
4c: 0000a383 lw x7, 0(x1) # загружаем значение из uart rx
50: 00947433 and x8, x8, x9 # обнуляем старые 3 байта
54: 00841413 slli x8, x8, 8 # Сдвигаем регистр x8 на 1 байт влево
58: 00746433 or x8, x8, x7 # записываем считанный из rx байт на освободившееся место
5c: 00340863 beq x8, x3, blink_mode # если пришел спец-код моргания, переходим в blink_mode
60: 00440a63 beq x8, x4, reset # если пришел спец-код сброса, переходим в reset
64: 00812023 sw x8, 0(x2) # записываем значением с переключателей в светодиоды
68: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
blink_mode:
6c: 00612223 sw x6, 4(x2) # записываем 1 в led_mode
70: 30200073 mret
reset:
74: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset
78: 30200073 mret

View File

@@ -0,0 +1,32 @@
_start:
# Инициализируем начальные значения регистров
0: 050000b7 li x1 , 0x05000000 # сохраняем базовый адрес uart_rx
4: 06000137 li x2 , 0x06000000 # сохраняем базовый адрес uart_tx
8: 0001c1b7 li x3 , 0x0001c200 # устанавливаем бодрейт 115200
c: 20018193
10: 0030a623 sw x3 , 0x0c(x1)
14: 00312623 sw x3 , 0x0c(x2)
18: 00100213 li x4 , 0x00000001 # устанавливаем parity_bit
1c: 0040a823 sw x4 , 0x10(x1)
20: 00412823 sw x4 , 0x10(x2)
24: 00100293 li x5 , 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
28: 30429073 csrw mie, x5 # загружаем маску в регистр маски
2c: 03c00293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
30: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
34: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
38: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
3c: 0000a383 lw x7, 0(x1) # загружаем пришедший байт
40: 00712023 sw x7, 0(x2)
44: 30200073 mret

View File

@@ -0,0 +1,40 @@
_start:
# Инициализируем начальные значения регистров
0: 010000b7 li x1, 0x01000000 # сохраняем базовый адрес переключателей
4: 02000137 li x2, 0x02000000 # сохраняем базовый адрес светодиодов
8: 0000b1b7 li x3, 0x0000aaaa # сохраняем спец-код для режима моргания
c: aaa18193
10: 00005237 li x4, 0x00005555 # сохраняем спец-код для сброса
14: 55520213
18: 00100313 li x6, 0x00000001 # сохраняем единицу
1c: 00100293 li x5, 0x00000001 # подготавливаем маску прерывания единственного
# (нулевого) входа
20: 30429073 csrw mie, x5 # загружаем маску в регистр маски
24: 03400293 la x5, trap_handler # псевдоинструкция la аналогично li загружает число,
28: 00028293 # только в случае la это число является адресом
# указанного места (адреса обработчика перехвата)
# данная псевдоинструкция будет разбита на две
# инструкции: lui и addi
2c: 30529073 csrw mtvec, x5 # устанавливаем вектор прерывания
# Вызов функции main
main:
30: 00000063 beq x0, x0, main # бесконечный цикл, аналогичный while (1);
# ОБРАБОТЧИК ПЕРЕХВАТА
# Без стороннего вмешательства процессор никогда не перейдет к инструкциям ниже,
# однако в случае прерывания в программный счетчик будет загружен адрес первой
# нижележащей инструкции.
# Сохраняем используемые регистры на стек
trap_handler:
34: 0000a383 lw x7, 0(x1) # загружаем значение на переключателях
38: 00338863 beq x7, x3, blink_mode # если пришел спец-код моргания, переходим в blink_mode
3c: 00438a63 beq x7, x4, reset # если пришел спец-код сброса, переходим в reset
40: 00712023 sw x7, 0(x2) # записываем значением с переключателей в светодиоды
44: 30200073 mret # возвращаем управление программе (pc = mepc)
# что означает возврат в бесконечный цикл
blink_mode:
48: 00612223 sw x6, 4(x2) # записываем 1 в led_mode
4c: 30200073 mret
reset:
50: 02612223 sw x6, 0x24(x2) # записываем 1 в led_reset
54: 30200073 mret

View File

@@ -0,0 +1,211 @@
## This file is a general .xdc for the Nexys A7-100T
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
# Clock signal
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk_i]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk_i]
create_generated_clock -name sys_clk10_pin -source [get_ports clk_i] -divide_by 10 [get_pins divider/clkbuf/O]
#Switches
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {sw_i[0]}]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports {sw_i[1]}]
set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS33} [get_ports {sw_i[2]}]
set_property -dict {PACKAGE_PIN R15 IOSTANDARD LVCMOS33} [get_ports {sw_i[3]}]
set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {sw_i[4]}]
set_property -dict {PACKAGE_PIN T18 IOSTANDARD LVCMOS33} [get_ports {sw_i[5]}]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports {sw_i[6]}]
set_property -dict {PACKAGE_PIN R13 IOSTANDARD LVCMOS33} [get_ports {sw_i[7]}]
set_property -dict {PACKAGE_PIN T8 IOSTANDARD LVCMOS18} [get_ports {sw_i[8]}]
set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS18} [get_ports {sw_i[9]}]
set_property -dict {PACKAGE_PIN R16 IOSTANDARD LVCMOS33} [get_ports {sw_i[10]}]
set_property -dict {PACKAGE_PIN T13 IOSTANDARD LVCMOS33} [get_ports {sw_i[11]}]
set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports {sw_i[12]}]
set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {sw_i[13]}]
set_property -dict {PACKAGE_PIN U11 IOSTANDARD LVCMOS33} [get_ports {sw_i[14]}]
set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {sw_i[15]}]
## LEDs
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {led_o[0]}]
set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS33} [get_ports {led_o[1]}]
set_property -dict {PACKAGE_PIN J13 IOSTANDARD LVCMOS33} [get_ports {led_o[2]}]
set_property -dict {PACKAGE_PIN N14 IOSTANDARD LVCMOS33} [get_ports {led_o[3]}]
set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports {led_o[4]}]
set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {led_o[5]}]
set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports {led_o[6]}]
set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {led_o[7]}]
set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {led_o[8]}]
set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS33} [get_ports {led_o[9]}]
set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports {led_o[10]}]
set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS33} [get_ports {led_o[11]}]
set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {led_o[12]}]
set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports {led_o[13]}]
set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports {led_o[14]}]
set_property -dict {PACKAGE_PIN V11 IOSTANDARD LVCMOS33} [get_ports {led_o[15]}]
### RGB LEDs
#set_property -dict {PACKAGE_PIN R12 IOSTANDARD LVCMOS33} [get_ports LED16_B]
#set_property -dict {PACKAGE_PIN M16 IOSTANDARD LVCMOS33} [get_ports LED16_G]
#set_property -dict {PACKAGE_PIN N15 IOSTANDARD LVCMOS33} [get_ports LED16_R]
#set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports LED17_B]
#set_property -dict {PACKAGE_PIN R11 IOSTANDARD LVCMOS33} [get_ports LED17_G]
#set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports LED17_R]
##7 segment display
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports hex_led_o[6]]
set_property -dict {PACKAGE_PIN R10 IOSTANDARD LVCMOS33} [get_ports hex_led_o[5]]
set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports hex_led_o[4]]
set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports hex_led_o[3]]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports hex_led_o[2]]
set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports hex_led_o[1]]
set_property -dict {PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports hex_led_o[0]]
#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { DP }]; #IO_L19N_T3_A21_VREF_15 Sch=dp
set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[0]}]
set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[1]}]
set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[2]}]
set_property -dict {PACKAGE_PIN J14 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[3]}]
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[4]}]
set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[5]}]
set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[6]}]
set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {hex_sel_o[7]}]
##Buttons
set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports resetn_i]
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { BTNC }]; #IO_L9P_T1_DQS_14 Sch=btnc
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { BTNU }]; #IO_L4N_T0_D05_14 Sch=btnu
#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { BTNL }]; #IO_L12P_T1_MRCC_14 Sch=btnl
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { BTNR }]; #IO_L10N_T1_D15_14 Sch=btnr
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { BTND }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
##Pmod Headers
##Pmod Header JA
#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { JA[1] }]; #IO_L20N_T3_A19_15 Sch=ja[1]
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { JA[2] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2]
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { JA[3] }]; #IO_L21P_T3_DQS_15 Sch=ja[3]
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { JA[4] }]; #IO_L18N_T2_A23_15 Sch=ja[4]
#set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { JA[7] }]; #IO_L16N_T2_A27_15 Sch=ja[7]
#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { JA[8] }]; #IO_L16P_T2_A28_15 Sch=ja[8]
#set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { JA[9] }]; #IO_L22N_T3_A16_15 Sch=ja[9]
#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { JA[10] }]; #IO_L22P_T3_A17_15 Sch=ja[10]
##Pmod Header JB
#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { JB[1] }]; #IO_L1P_T0_AD0P_15 Sch=jb[1]
#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { JB[2] }]; #IO_L14N_T2_SRCC_15 Sch=jb[2]
#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { JB[3] }]; #IO_L13N_T2_MRCC_15 Sch=jb[3]
#set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { JB[4] }]; #IO_L15P_T2_DQS_15 Sch=jb[4]
#set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { JB[7] }]; #IO_L11N_T1_SRCC_15 Sch=jb[7]
#set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { JB[8] }]; #IO_L5P_T0_AD9P_15 Sch=jb[8]
#set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { JB[9] }]; #IO_0_15 Sch=jb[9]
#set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { JB[10] }]; #IO_L13P_T2_MRCC_15 Sch=jb[10]
##Pmod Header JC
#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { JC[1] }]; #IO_L23N_T3_35 Sch=jc[1]
#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { JC[2] }]; #IO_L19N_T3_VREF_35 Sch=jc[2]
#set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { JC[3] }]; #IO_L22N_T3_35 Sch=jc[3]
#set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { JC[4] }]; #IO_L19P_T3_35 Sch=jc[4]
#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { JC[7] }]; #IO_L6P_T0_35 Sch=jc[7]
#set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { JC[8] }]; #IO_L22P_T3_35 Sch=jc[8]
#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { JC[9] }]; #IO_L21P_T3_DQS_35 Sch=jc[9]
#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { JC[10] }]; #IO_L5P_T0_AD13P_35 Sch=jc[10]
##Pmod Header JD
#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { JD[1] }]; #IO_L21N_T3_DQS_35 Sch=jd[1]
#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { JD[2] }]; #IO_L17P_T2_35 Sch=jd[2]
#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { JD[3] }]; #IO_L17N_T2_35 Sch=jd[3]
#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { JD[4] }]; #IO_L20N_T3_35 Sch=jd[4]
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { JD[7] }]; #IO_L15P_T2_DQS_35 Sch=jd[7]
#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { JD[8] }]; #IO_L20P_T3_35 Sch=jd[8]
#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { JD[9] }]; #IO_L15N_T2_DQS_35 Sch=jd[9]
#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { JD[10] }]; #IO_L13N_T2_MRCC_35 Sch=jd[10]
##Pmod Header JXADC
#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { XA_N[1] }]; #IO_L9N_T1_DQS_AD3N_15 Sch=xa_n[1]
#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { XA_P[1] }]; #IO_L9P_T1_DQS_AD3P_15 Sch=xa_p[1]
#set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { XA_N[2] }]; #IO_L8N_T1_AD10N_15 Sch=xa_n[2]
#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { XA_P[2] }]; #IO_L8P_T1_AD10P_15 Sch=xa_p[2]
#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { XA_N[3] }]; #IO_L7N_T1_AD2N_15 Sch=xa_n[3]
#set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { XA_P[3] }]; #IO_L7P_T1_AD2P_15 Sch=xa_p[3]
#set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { XA_N[4] }]; #IO_L10N_T1_AD11N_15 Sch=xa_n[4]
#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { XA_P[4] }]; #IO_L10P_T1_AD11P_15 Sch=xa_p[4]
##VGA Connector
set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { vga_r_o[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0]
set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { vga_r_o[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1]
set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { vga_r_o[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2]
set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { vga_r_o[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3]
set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { vga_g_o[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0]
set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { vga_g_o[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1]
set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { vga_g_o[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2]
set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { vga_g_o[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3]
set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { vga_b_o[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0]
set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { vga_b_o[1] }]; #IO_L4N_T0_35 Sch=vga_b[1]
set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { vga_b_o[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2]
set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { vga_b_o[3] }]; #IO_L4P_T0_35 Sch=vga_b[3]
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { vga_hs_o }]; #IO_L4P_T0_15 Sch=vga_hs
set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { vga_vs_o }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs
##Micro SD Connector
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { SD_RESET }]; #IO_L14P_T2_SRCC_35 Sch=sd_reset
#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { SD_CD }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd
#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { SD_SCK }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sd_sck
#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { SD_CMD }]; #IO_L16N_T2_35 Sch=sd_cmd
#set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[0] }]; #IO_L16P_T2_35 Sch=sd_dat[0]
#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[1] }]; #IO_L18N_T2_35 Sch=sd_dat[1]
#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[2] }]; #IO_L18P_T2_35 Sch=sd_dat[2]
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { SD_DAT[3] }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3]
##Accelerometer
#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { ACL_MISO }]; #IO_L11P_T1_SRCC_15 Sch=acl_miso
#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { ACL_MOSI }]; #IO_L5N_T0_AD9N_15 Sch=acl_mosi
#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { ACL_SCLK }]; #IO_L14P_T2_SRCC_15 Sch=acl_sclk
#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { ACL_CSN }]; #IO_L12P_T1_MRCC_15 Sch=acl_csn
#set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports { ACL_INT[1] }]; #IO_L2P_T0_AD8P_15 Sch=acl_int[1]
#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { ACL_INT[2] }]; #IO_L20P_T3_A20_15 Sch=acl_int[2]
##Temperature Sensor
#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { TMP_SCL }]; #IO_L1N_T0_AD0N_15 Sch=tmp_scl
#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { TMP_SDA }]; #IO_L12N_T1_MRCC_15 Sch=tmp_sda
#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { TMP_INT }]; #IO_L6N_T0_VREF_15 Sch=tmp_int
#set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { TMP_CT }]; #IO_L2N_T0_AD8N_15 Sch=tmp_ct
##Omnidirectional Microphone
#set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { M_CLK }]; #IO_25_35 Sch=m_clk
#set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { M_DATA }]; #IO_L24N_T3_35 Sch=m_data
#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { M_LRSEL }]; #IO_0_35 Sch=m_lrsel
##PWM Audio Amplifier
#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { AUD_PWM }]; #IO_L4N_T0_15 Sch=aud_pwm
#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { AUD_SD }]; #IO_L6P_T0_15 Sch=aud_sd
##USB-RS232 Interface
set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { rx_i }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { tx_o }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out
#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { UART_CTS }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts
#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { UART_RTS }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts
##USB HID (PS/2)
set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33} [get_ports kclk_i]
set_property -dict {PACKAGE_PIN B2 IOSTANDARD LVCMOS33} [get_ports kdata_i]
##SMSC Ethernet PHY
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { ETH_MDC }]; #IO_L11P_T1_SRCC_16 Sch=eth_mdc
#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { ETH_MDIO }]; #IO_L14N_T2_SRCC_16 Sch=eth_mdio
#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { ETH_RSTN }]; #IO_L10P_T1_AD15P_35 Sch=eth_rstn
#set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { ETH_CRSDV }]; #IO_L6N_T0_VREF_16 Sch=eth_crsdv
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXERR }]; #IO_L13N_T2_MRCC_16 Sch=eth_rxerr
#set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXD[0] }]; #IO_L13P_T2_MRCC_16 Sch=eth_rxd[0]
#set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { ETH_RXD[1] }]; #IO_L19N_T3_VREF_16 Sch=eth_rxd[1]
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXEN }]; #IO_L11N_T1_SRCC_16 Sch=eth_txen
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXD[0] }]; #IO_L14P_T2_SRCC_16 Sch=eth_txd[0]
#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { ETH_TXD[1] }]; #IO_L12N_T1_MRCC_16 Sch=eth_txd[1]
#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { ETH_REFCLK }]; #IO_L11P_T1_SRCC_35 Sch=eth_refclk
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { ETH_INTN }]; #IO_L12P_T1_MRCC_16 Sch=eth_intn
##Quad SPI Flash
#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0]
#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1]
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2]
#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { QSPI_DQ[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3]
#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { QSPI_CSN }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn

View File

@@ -0,0 +1,100 @@
module PS2Receiver(
input logic clk_i,
input logic rst_i,
input logic kclk_i,
input logic kdata_i,
output logic [7:0] keycodeout_o,
output keycode_valid_o
);
logic flag;
logic [3:0] flag_shift;
logic kclkf, kdataf;
logic [3:0] cnt;
assign keycode_valid_o = flag_shift[0] && !flag_shift[2];
debouncer debounce(
.clk(clk_i),
.I0(kclk_i),
.I1(kdata_i),
.O0(kclkf),
.O1(kdataf)
);
always@(posedge clk_i) begin
if(rst_i) begin
flag_shift <= '0;
end
else begin
flag_shift <= {flag_shift[2:0], flag};
end
end
always_ff @(negedge kclkf or posedge rst_i)begin
if(rst_i) begin
cnt <= '0;
end
else if (cnt <= 9) begin
cnt <= cnt + 1;
end
else begin
cnt <= '0;
end
end
always_ff @(negedge kclkf or posedge rst_i) begin
if(rst_i) begin
keycodeout_o <= '0;
end
else begin
case(cnt)
1:keycodeout_o[0]<=kdataf;
2:keycodeout_o[1]<=kdataf;
3:keycodeout_o[2]<=kdataf;
4:keycodeout_o[3]<=kdataf;
5:keycodeout_o[4]<=kdataf;
6:keycodeout_o[5]<=kdataf;
7:keycodeout_o[6]<=kdataf;
8:keycodeout_o[7]<=kdataf;
default: keycodeout_o <= keycodeout_o;
endcase
end
end
assign flag = cnt == 9;
endmodule
module debouncer(
input logic clk,
input logic I0,
input logic I1,
output logic O0,
output logic O1
);
logic [4:0]cnt0, cnt1;
logic Iv0=0,Iv1=0;
logic out0, out1;
always_ff @(posedge(clk))begin
if (I0==Iv0) begin
if (cnt0==19)O0<=I0;
else cnt0<=cnt0+1;
end
else begin
cnt0<=5'd0;
Iv0<=I0;
end
if (I1==Iv1)begin
if (cnt1==19)O1<=I1;
else cnt1<=cnt1+1;
end
else begin
cnt1<=5'd0;
Iv1<=I1;
end
end
endmodule

View File

@@ -0,0 +1,92 @@
module hex_digits(
input logic clk_i,
input logic rst_i,
input logic [3:0] hex0_i, // Цифра, выводимой на нулевой (самый правый) индикатор
input logic [3:0] hex1_i, // Цифра, выводимая на первый индикатор
input logic [3:0] hex2_i, // Цифра, выводимая на второй индикатор
input logic [3:0] hex3_i, // Цифра, выводимая на третий индикатор
input logic [3:0] hex4_i, // Цифра, выводимая на четвертый индикатор
input logic [3:0] hex5_i, // Цифра, выводимая на пятый индикатор
input logic [3:0] hex6_i, // Цифра, выводимая на шестой индикатор
input logic [3:0] hex7_i, // Цифра, выводимая на седьмой индикатор
input logic [7:0] bitmask_i, // Битовая маска для включения/отключения
// отдельных индикаторов
output logic [6:0] hex_led_o, // Сигнал, контролирующий каждый отдельный
// светодиод индикатора
output logic [7:0] hex_sel_o // Сигнал, указывающий на какой индикатор
// выставляется hex_led
);
logic [4:0] hex0, hex1, hex2, hex3, hex4, hex5, hex6, hex7;
assign hex0 = {bitmask_i[0], hex0_i};
assign hex1 = {bitmask_i[1], hex1_i};
assign hex2 = {bitmask_i[2], hex2_i};
assign hex3 = {bitmask_i[3], hex3_i};
assign hex4 = {bitmask_i[4], hex4_i};
assign hex5 = {bitmask_i[5], hex5_i};
assign hex6 = {bitmask_i[6], hex6_i};
assign hex7 = {bitmask_i[7], hex7_i};
localparam pwm = 32'd1000; //шим сегментов
logic [9:0] counter;
logic [4:0] semseg;
logic [7:0] ANreg;
logic [6:0] hex_ledr;
assign hex_sel_o = ANreg;
assign hex_led_o = hex_ledr;
always_ff @(posedge clk_i) begin
if (rst_i) begin
counter <= 'b0;
ANreg[7:0] <= 8'b11111111;
hex_ledr <= 7'b1111111;
end
else begin
if (counter < pwm) counter <= counter + 'b1;
else begin
counter <= 'b0;
ANreg[1] <= ANreg[0];
ANreg[2] <= ANreg[1];
ANreg[3] <= ANreg[2];
ANreg[4] <= ANreg[3];
ANreg[5] <= ANreg[4];
ANreg[6] <= ANreg[5];
ANreg[7] <= ANreg[6];
ANreg[0] <= !(ANreg[6:0] == 7'b1111111);
end
case (1'b0)
ANreg[0]: semseg <= hex0;
ANreg[1]: semseg <= hex1;
ANreg[2]: semseg <= hex2;
ANreg[3]: semseg <= hex3;
ANreg[4]: semseg <= hex4;
ANreg[5]: semseg <= hex5;
ANreg[6]: semseg <= hex6;
ANreg[7]: semseg <= hex7;
endcase
case (semseg)
5'h10: hex_ledr <= 7'b0000001;
5'h11: hex_ledr <= 7'b1001111;
5'h12: hex_ledr <= 7'b0010010;
5'h13: hex_ledr <= 7'b0000110;
5'h14: hex_ledr <= 7'b1001100;
5'h15: hex_ledr <= 7'b0100100;
5'h16: hex_ledr <= 7'b0100000;
5'h17: hex_ledr <= 7'b0001111;
5'h18: hex_ledr <= 7'b0000000;
5'h19: hex_ledr <= 7'b0000100;
5'h1A: hex_ledr <= 7'b0001000;
5'h1B: hex_ledr <= 7'b1100000;
5'h1C: hex_ledr <= 7'b0110001;
5'h1D: hex_ledr <= 7'b1000010;
5'h1E: hex_ledr <= 7'b0110000;
5'h1F: hex_ledr <= 7'b0111000;
default: hex_ledr <= 7'b1111111;
endcase
end
end
endmodule

View File

@@ -0,0 +1,279 @@
// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
module uart_rx (
input logic clk_i,
input logic rst_i,
input logic rx_i,
output logic busy_o,
input logic [16:0] baudrate_i,
input logic parity_en_i,
input logic stopbit_i,
output logic [7:0] rx_data_o,
output logic rx_valid_o
//, input logic cfg_en_i,
// input logic [1:0] cfg_bits_i,
// output logic err_o,
// input logic err_clr_i,
// input logic rx_ready_i
);
logic rx_ready_i;
logic cfg_en_i;
logic [1:0] cfg_bits_i;
logic rstn_i;
logic [15:0] cfg_div_i;
always_comb begin
case(baudrate_i)
17'd9600 : cfg_div_i = 15'd1041;
17'd19200 : cfg_div_i = 15'd520;
17'd38400 : cfg_div_i = 15'd259;
17'd57600 : cfg_div_i = 15'd173;
17'd115200: cfg_div_i = 15'd86;
default : cfg_div_i = 15'd1041;
endcase
end
assign rstn_i = !rst_i;
assign rx_ready_i = 1'b1;
assign cfg_en_i = 1'b1;
assign cfg_bits_i = 2'd3;
enum logic [2:0] {IDLE,START_BIT,DATA,SAVE_DATA,PARITY,STOP_BIT} CS, NS;
logic [7:0] reg_data;
logic [7:0] reg_data_next;
logic [2:0] reg_rx_sync;
logic [2:0] reg_bit_count;
logic [2:0] reg_bit_count_next;
logic [2:0] s_target_bits;
logic parity_bit;
logic parity_bit_next;
logic sampleData;
logic [15:0] baud_cnt;
logic baudgen_en;
logic bit_done;
logic start_bit;
logic set_error;
logic s_rx_fall;
assign busy_o = (CS != IDLE);
always_comb
begin
case(cfg_bits_i)
2'b00:
s_target_bits = 3'h4;
2'b01:
s_target_bits = 3'h5;
2'b10:
s_target_bits = 3'h6;
2'b11:
s_target_bits = 3'h7;
endcase
end
always_comb
begin
NS = CS;
sampleData = 1'b0;
reg_bit_count_next = reg_bit_count;
reg_data_next = reg_data;
rx_valid_o = 1'b0;
baudgen_en = 1'b0;
start_bit = 1'b0;
parity_bit_next = parity_bit;
set_error = 1'b0;
case(CS)
IDLE:
begin
if (s_rx_fall)
begin
NS = START_BIT;
baudgen_en = 1'b1;
start_bit = 1'b1;
end
end
START_BIT:
begin
parity_bit_next = 1'b0;
baudgen_en = 1'b1;
start_bit = 1'b1;
if (bit_done)
NS = DATA;
end
DATA:
begin
baudgen_en = 1'b1;
parity_bit_next = parity_bit ^ reg_rx_sync[2];
case(cfg_bits_i)
2'b00:
reg_data_next = {3'b000,reg_rx_sync[2],reg_data[4:1]};
2'b01:
reg_data_next = {2'b00,reg_rx_sync[2],reg_data[5:1]};
2'b10:
reg_data_next = {1'b0,reg_rx_sync[2],reg_data[6:1]};
2'b11:
reg_data_next = {reg_rx_sync[2],reg_data[7:1]};
endcase
if (bit_done)
begin
sampleData = 1'b1;
if (reg_bit_count == s_target_bits)
begin
reg_bit_count_next = 'h0;
NS = SAVE_DATA;
end
else
begin
reg_bit_count_next = reg_bit_count + 1;
end
end
end
SAVE_DATA:
begin
baudgen_en = 1'b1;
rx_valid_o = 1'b1;
if(rx_ready_i)
if (parity_en_i)
NS = PARITY;
else
NS = STOP_BIT;
end
PARITY:
begin
baudgen_en = 1'b1;
if (bit_done)
begin
if(parity_bit != reg_rx_sync[2])
set_error = 1'b1;
NS = STOP_BIT;
end
end
STOP_BIT:
begin
baudgen_en = 1'b1;
if (bit_done)
begin
NS = IDLE;
end
end
default:
NS = IDLE;
endcase
end
always_ff @(posedge clk_i or negedge rstn_i)
begin
if (rstn_i == 1'b0)
begin
CS <= IDLE;
reg_data <= 8'hFF;
reg_bit_count <= 'h0;
parity_bit <= 1'b0;
end
else
begin
if(bit_done)
parity_bit <= parity_bit_next;
if(sampleData)
reg_data <= reg_data_next;
reg_bit_count <= reg_bit_count_next;
if(cfg_en_i)
CS <= NS;
else
CS <= IDLE;
end
end
assign s_rx_fall = ~reg_rx_sync[1] & reg_rx_sync[2];
always_ff @(posedge clk_i or negedge rstn_i)
begin
if (rstn_i == 1'b0)
reg_rx_sync <= 3'b111;
else
begin
if (cfg_en_i)
reg_rx_sync <= {reg_rx_sync[1:0],rx_i};
else
reg_rx_sync <= 3'b111;
end
end
always_ff @(posedge clk_i or negedge rstn_i)
begin
if (rstn_i == 1'b0)
begin
baud_cnt <= 'h0;
bit_done <= 1'b0;
end
else
begin
if(baudgen_en)
begin
if(!start_bit && (baud_cnt == cfg_div_i))
begin
baud_cnt <= 'h0;
bit_done <= 1'b1;
end
else if(start_bit && (baud_cnt == {1'b0,cfg_div_i[15:1]}))
begin
baud_cnt <= 'h0;
bit_done <= 1'b1;
end
else
begin
baud_cnt <= baud_cnt + 1;
bit_done <= 1'b0;
end
end
else
begin
baud_cnt <= 'h0;
bit_done <= 1'b0;
end
end
end
// always_ff @(posedge clk_i or negedge rstn_i)
// begin
// if (rstn_i == 1'b0)
// begin
// err_o <= 1'b0;
// end
// else
// begin
// if(err_clr_i)
// begin
// err_o <= 1'b0;
// end
// else
// begin
// if(set_error)
// err_o <= 1'b1;
// end
// end
// end
assign rx_data_o = reg_data;
endmodule

View File

@@ -0,0 +1,233 @@
// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
module uart_tx (
input logic clk_i,
input logic rst_i,
output logic tx_o,
output logic busy_o,
input logic [16:0] baudrate_i,
input logic parity_en_i,
input logic stopbit_i,
input logic [7:0] tx_data_i,
input logic tx_valid_i
//, input logic cfg_en_i,
// input logic [15:0] cfg_div_i,
// input logic cfg_parity_en_i,
// input logic [1:0] cfg_bits_i,
// input logic stopbit_i,
// output logic tx_ready_o
);
logic rstn_i;
logic cfg_en_i;
logic [1:0] cfg_bits_i;
logic [15:0] cfg_div_i;
logic tx_ready_o;
assign rstn_i = !rst_i;
assign cfg_en_i = 1'b1;
assign cfg_bits_i = 2'd3;
always_comb begin
case(baudrate_i)
17'd9600 : cfg_div_i = 15'd1041;
17'd19200 : cfg_div_i = 15'd520;
17'd38400 : cfg_div_i = 15'd259;
17'd57600 : cfg_div_i = 15'd173;
17'd115200: cfg_div_i = 15'd86;
default : cfg_div_i = 15'd1041;
endcase
end
enum logic [2:0] {IDLE,START_BIT,DATA,PARITY,STOP_BIT_FIRST,STOP_BIT_LAST} CS,NS;
logic [7:0] reg_data;
logic [7:0] reg_data_next;
logic [2:0] reg_bit_count;
logic [2:0] reg_bit_count_next;
logic [2:0] s_target_bits;
logic parity_bit;
logic parity_bit_next;
logic sampleData;
logic [15:0] baud_cnt;
logic baudgen_en;
logic bit_done;
assign busy_o = (CS != IDLE);
always_comb
begin
case(cfg_bits_i)
2'b00:
s_target_bits = 3'h4;
2'b01:
s_target_bits = 3'h5;
2'b10:
s_target_bits = 3'h6;
2'b11:
s_target_bits = 3'h7;
endcase
end
always_comb
begin
NS = CS;
tx_o = 1'b1;
sampleData = 1'b0;
reg_bit_count_next = reg_bit_count;
reg_data_next = {1'b1,reg_data[7:1]};
tx_ready_o = 1'b0;
baudgen_en = 1'b0;
parity_bit_next = parity_bit;
case(CS)
IDLE:
begin
if (cfg_en_i)
tx_ready_o = 1'b1;
if (tx_valid_i)
begin
NS = START_BIT;
sampleData = 1'b1;
reg_data_next = tx_data_i;
end
end
START_BIT:
begin
tx_o = 1'b0;
parity_bit_next = 1'b0;
baudgen_en = 1'b1;
if (bit_done)
NS = DATA;
end
DATA:
begin
tx_o = reg_data[0];
baudgen_en = 1'b1;
parity_bit_next = parity_bit ^ reg_data[0];
if (bit_done)
begin
if (reg_bit_count == s_target_bits)
begin
reg_bit_count_next = 'h0;
if (parity_en_i)
begin
NS = PARITY;
end
else
begin
NS = STOP_BIT_FIRST;
end
end
else
begin
reg_bit_count_next = reg_bit_count + 1;
sampleData = 1'b1;
end
end
end
PARITY:
begin
tx_o = parity_bit;
baudgen_en = 1'b1;
if (bit_done)
NS = STOP_BIT_FIRST;
end
STOP_BIT_FIRST:
begin
tx_o = 1'b1;
baudgen_en = 1'b1;
if (bit_done)
begin
if (stopbit_i)
NS = STOP_BIT_LAST;
else
NS = IDLE;
end
end
STOP_BIT_LAST:
begin
tx_o = 1'b1;
baudgen_en = 1'b1;
if (bit_done)
begin
NS = IDLE;
end
end
default:
NS = IDLE;
endcase
end
always_ff @(posedge clk_i or negedge rstn_i)
begin
if (rstn_i == 1'b0)
begin
CS <= IDLE;
reg_data <= 8'hFF;
reg_bit_count <= 'h0;
parity_bit <= 1'b0;
end
else
begin
if(bit_done)
begin
parity_bit <= parity_bit_next;
end
if(sampleData)
begin
reg_data <= reg_data_next;
end
reg_bit_count <= reg_bit_count_next;
if(cfg_en_i)
CS <= NS;
else
CS <= IDLE;
end
end
always_ff @(posedge clk_i or negedge rstn_i)
begin
if (rstn_i == 1'b0)
begin
baud_cnt <= 'h0;
bit_done <= 1'b0;
end
else
begin
if(baudgen_en)
begin
if(baud_cnt == cfg_div_i)
begin
baud_cnt <= 'h0;
bit_done <= 1'b1;
end
else
begin
baud_cnt <= baud_cnt + 1;
bit_done <= 1'b0;
end
end
else
begin
baud_cnt <= 'h0;
bit_done <= 1'b0;
end
end
end
endmodule

View File

@@ -0,0 +1,614 @@
module vgachargen
import vgachargen_pkg::*;
#(
parameter int unsigned CLK_FACTOR_25M = 100 / 25,
parameter CH_T_RO_INIT_FILE_NAME = "lab12_vga_ch_t_ro.mem",
parameter bit CH_T_RO_INIT_FILE_IS_BIN = 1,
parameter CH_T_RW_INIT_FILE_NAME = "lab12_vga_ch_t_rw.mem",
parameter bit CH_T_RW_INIT_FILE_IS_BIN = 1,
parameter CH_MAP_INIT_FILE_NAME = "lab12_vga_ch_map.mem",
parameter bit CH_MAP_INIT_FILE_IS_BIN = 0,
parameter COL_MAP_INIT_FILE_NAME = "lab12_vga_col_map.mem",
parameter bit COL_MAP_INIT_FILE_IS_BIN = 0
) (
input logic clk_i, // системный синхроимпульс
input logic clk100m_i, // клок с частотой 100МГц
input logic rst_i, // сигнал сброса
/*
Интерфейс записи выводимого символа
*/
input logic [ 9:0] char_map_addr_i, // адрес позиции выводимого символа
input logic char_map_we_i, // сигнал разрешения записи кода
input logic [ 3:0] char_map_be_i, // сигнал выбора байтов для записи
input logic [31:0] char_map_wdata_i, // ascii-код выводимого символа
output logic [31:0] char_map_rdata_o, // сигнал чтения кода символа
/*
Интерфейс установки цветовой схемы
*/
input logic [ 9:0] col_map_addr_i, // адрес позиции устанавливаемой схемы
input logic col_map_we_i, // сигнал разрешения записи схемы
input logic [ 3:0] col_map_be_i, // сигнал выбора байтов для записи
input logic [31:0] col_map_wdata_i, // код устанавливаемой цветовой схемы
output logic [31:0] col_map_rdata_o, // сигнал чтения кода схемы
/*
Интерфейс установки шрифта.
*/
input logic [ 9:0] char_tiff_addr_i, // адрес позиции устанавливаемого шрифта
input logic char_tiff_we_i, // сигнал разрешения записи шрифта
input logic [ 3:0] char_tiff_be_i, // сигнал выбора байтов для записи
input logic [31:0] char_tiff_wdata_i, // отображаемые пиксели в текущей позиции шрифта
output logic [31:0] char_tiff_rdata_o, // сигнал чтения пикселей шрифта
output logic [3:0] vga_r_o, // красный канал vga
output logic [3:0] vga_g_o, // зеленый канал vga
output logic [3:0] vga_b_o, // синий канал vga
output logic vga_hs_o, // линия горизонтальной синхронизации vga
output logic vga_vs_o // линия вертикальной синхронизации vga
);
logic [3:0] char_map_be_gated;
assign char_map_be_gated = char_map_be_i & {4{char_map_we_i}};
logic [3:0] col_map_be_gated;
assign col_map_be_gated = col_map_be_i & {4{col_map_we_i}};
logic arstn_i;
assign arstn_i = ~rst_i;
logic [VGA_MAX_H_WIDTH-1:0] hcount_pixels;
logic [VGA_MAX_V_WIDTH-1:0] vcount_pixels;
logic pixel_enable;
logic pixel_enable_delayed;
delay #(
.DATA_WIDTH (1),
.DELAY_BY (2)
) pixel_enable_delay (
.clk_i (clk100m_i),
.arstn_i (arstn_i),
.data_i (pixel_enable),
.data_o (pixel_enable_delayed)
);
logic vga_vs_delayed;
logic vga_vs;
delay #(
.DATA_WIDTH (1),
.DELAY_BY (2)
) vga_vs_delay (
.clk_i (clk100m_i),
.arstn_i (arstn_i),
.data_i (vga_vs),
.data_o (vga_vs_delayed)
);
logic vga_hs_delayed;
logic vga_hs;
delay #(
.DATA_WIDTH (1),
.DELAY_BY (2)
) vga_hs_delay (
.clk_i (clk100m_i),
.arstn_i (arstn_i),
.data_i (vga_hs),
.data_o (vga_hs_delayed)
);
vga_block #(
.CLK_FACTOR_25M (CLK_FACTOR_25M)
) vga_block (
.clk_i (clk100m_i),
.arstn_i (arstn_i),
.hcount_o (hcount_pixels),
.vcount_o (vcount_pixels),
.pixel_enable_o (pixel_enable),
.vga_hs_o (vga_hs),
.vga_vs_o (vga_vs)
);
logic [CH_MAP_ADDR_WIDTH-1:0] ch_map_addr_internal;
logic [BITMAP_ADDR_WIDTH-1:0] bitmap_addr;
logic [BITMAP_ADDR_WIDTH-1:0] bitmap_addr_delayed;
delay #(
.DATA_WIDTH (BITMAP_ADDR_WIDTH),
.DELAY_BY (2)
) bitmap_delay (
.clk_i (clk100m_i),
.arstn_i (arstn_i),
.data_i (bitmap_addr),
.data_o (bitmap_addr_delayed)
);
index_generator index_generator (
.vcount_i (vcount_pixels),
.hcount_i (hcount_pixels),
.ch_map_addr_o (ch_map_addr_internal),
.bitmap_addr_o (bitmap_addr)
);
logic [CH_T_ADDR_WIDTH:0] ch_t_addr_internal;
logic [3:0][7:0] ch_map_data_word;
assign ch_t_addr_internal = ch_map_data_word[ch_map_addr_internal[1:0]];
true_dual_port_rw_bram #(
.INIT_FILE_NAME (CH_MAP_INIT_FILE_NAME),
.INIT_FILE_IS_BIN (CH_MAP_INIT_FILE_IS_BIN),
.ADDR_WIDTH (10)
) ch_map (
.clka_i (clk_i),
.clkb_i (clk100m_i),
.addra_i (char_map_addr_i),
.addrb_i (ch_map_addr_internal[$left(ch_map_addr_internal):2]),
.wea_i (char_map_be_gated),
.dina_i (char_map_wdata_i),
.douta_o (char_map_rdata_o),
.doutb_o (ch_map_data_word)
);
logic [CH_T_ADDR_WIDTH-1:0] ch_t_ro_addr_internal;
assign ch_t_ro_addr_internal = ch_t_addr_internal[CH_T_ADDR_WIDTH-1:0];
logic [CH_T_DATA_WIDTH-1:0] ch_t_ro_data_internal;
single_port_ro_bram #(
.INIT_FILE_NAME (CH_T_RO_INIT_FILE_NAME),
.INIT_FILE_IS_BIN (CH_T_RO_INIT_FILE_IS_BIN),
.DATA_WIDTH (CH_T_DATA_WIDTH),
.ADDR_WIDTH (CH_T_ADDR_WIDTH)
) ch_t_ro (
.clk_i (clk100m_i),
.addr_i(ch_t_ro_addr_internal),
.dout_o(ch_t_ro_data_internal)
);
logic [CH_T_ADDR_WIDTH-1:0] ch_t_rw_addr_internal;
assign ch_t_rw_addr_internal = ch_t_ro_addr_internal;
logic [CH_T_DATA_WIDTH-1:0] ch_t_rw_data_internal;
true_dual_port_rw_bram #(
.INIT_FILE_NAME (CH_T_RW_INIT_FILE_NAME),
.INIT_FILE_IS_BIN (CH_T_RW_INIT_FILE_IS_BIN),
.NUM_COLS (1),
.COL_WIDTH (CH_T_DATA_WIDTH),
.ADDR_WIDTH (CH_T_ADDR_WIDTH)
) ch_t_rw (
.clka_i (clk_i),
.clkb_i (clk100m_i),
// .addra_i (ch_t_rw_addr_i),
.addra_i (),
.addrb_i (ch_t_rw_addr_internal),
// .wea_i (ch_t_rw_wen_i),
.wea_i (),
// .dina_i (ch_t_rw_data_i),
.dina_i (),
// .douta_o (ch_t_rw_data_o),
.douta_o (),
.doutb_o (ch_t_rw_data_internal)
);
logic [CH_T_DATA_WIDTH-1:0] ch_t_data_internal;
assign ch_t_data_internal = ch_t_addr_internal[CH_T_ADDR_WIDTH] ? ch_t_rw_data_internal
: ch_t_ro_data_internal;
logic [7:0] col_map_data_internal;
logic [7:0] col_map_data_internal_delayed;
logic [3:0][7:0] col_map_data_internal_word;
assign col_map_data_internal = col_map_data_internal_word[ch_map_addr_internal[1:0]];
delay #(
.DATA_WIDTH (8),
.DELAY_BY (1)
) col_map_data_delay (
.clk_i (clk100m_i),
.arstn_i (arstn_i),
.data_i (col_map_data_internal),
.data_o (col_map_data_internal_delayed)
);
logic [3:0] fg_col_map_data;
logic [3:0] bg_col_map_data;
assign fg_col_map_data = col_map_data_internal_delayed[7:4];
assign bg_col_map_data = col_map_data_internal_delayed[3:0];
true_dual_port_rw_bram #(
.INIT_FILE_NAME (COL_MAP_INIT_FILE_NAME),
.INIT_FILE_IS_BIN (COL_MAP_INIT_FILE_IS_BIN),
.ADDR_WIDTH (10)
) col_map (
.clka_i (clk_i),
.clkb_i (clk100m_i),
.addra_i (col_map_addr_i),
.addrb_i (ch_map_addr_internal[$left(ch_map_addr_internal):2]),
.wea_i (col_map_be_gated),
.dina_i (col_map_wdata_i),
.douta_o (col_map_rdata_o),
.doutb_o (col_map_data_internal_word)
);
logic currentPixel;
assign currentPixel = ch_t_data_internal[bitmap_addr_delayed];
logic [11:0] fg_color;
assign fg_color = color_decode(fg_col_map_data);
logic [11:0] bg_color;
assign bg_color = color_decode(bg_col_map_data);
// register outputs
logic [3:0] vga_r_ff;
logic [3:0] vga_r_next;
logic [3:0] vga_g_ff;
logic [3:0] vga_g_next;
logic [3:0] vga_b_ff;
logic [3:0] vga_b_next;
logic vga_vs_ff;
logic vga_vs_next;
logic vga_hs_ff;
logic vga_hs_next;
assign vga_r_next = pixel_enable_delayed ? (currentPixel ? fg_color[11:8]: bg_color[11:8]) : '0;
assign vga_g_next = pixel_enable_delayed ? (currentPixel ? fg_color[7:4] : bg_color[7:4]) : '0;
assign vga_b_next = pixel_enable_delayed ? (currentPixel ? fg_color[3:0] : bg_color[3:0]) : '0;
assign vga_vs_next = vga_vs_delayed;
assign vga_hs_next = vga_hs_delayed;
always_ff @(posedge clk100m_i or negedge arstn_i) begin
if (!arstn_i) begin
vga_r_ff <= '0;
vga_g_ff <= '0;
vga_b_ff <= '0;
vga_hs_ff <= '0;
vga_vs_ff <= '0;
end else begin
vga_r_ff <= vga_r_next;
vga_g_ff <= vga_g_next;
vga_b_ff <= vga_b_next;
vga_hs_ff <= vga_hs_next;
vga_vs_ff <= vga_vs_next;
end
end
assign vga_r_o = vga_r_ff;
assign vga_g_o = vga_g_ff;
assign vga_b_o = vga_b_ff;
assign vga_hs_o = vga_hs_ff;
assign vga_vs_o = vga_vs_ff;
endmodule
module clk_divider # (
parameter int unsigned DIVISOR = 2
) (
input logic clk_i,
input logic arstn_i,
output logic strb_o
);
localparam int unsigned COUNTER_WIDTH = (DIVISOR > 1) ? $clog2(DIVISOR) : 1;
logic [COUNTER_WIDTH-1:0] counter_next;
logic [COUNTER_WIDTH-1:0] counter_ff;
assign counter_next = ~|counter_ff ? COUNTER_WIDTH'(DIVISOR - 1) : (counter_ff - COUNTER_WIDTH'(1));
always_ff @(posedge clk_i or negedge arstn_i) begin
if (~arstn_i) counter_ff <= '0;
else counter_ff <= counter_next;
end
logic strb_ff;
logic strb_next;
assign strb_next = ~|counter_ff;
always_ff @(posedge clk_i or negedge arstn_i) begin
if (~arstn_i) strb_ff <= '0;
else strb_ff <= strb_next;
end
assign strb_o = strb_ff;
endmodule
module delay #(
parameter int unsigned DATA_WIDTH = 8,
parameter int unsigned DELAY_BY = 2
) (
input logic clk_i,
input logic arstn_i,
input logic [DATA_WIDTH-1:0] data_i,
output logic [DATA_WIDTH-1:0] data_o
);
logic [DELAY_BY-1:0][DATA_WIDTH-1:0] data_ff ;
logic [DELAY_BY-1:0][DATA_WIDTH-1:0] data_next;
if (DELAY_BY == 1) begin
assign data_next = data_i;
assign data_o = data_ff;
end else begin
assign data_next = {data_ff[DELAY_BY-2:0], data_i};
assign data_o = data_ff[DELAY_BY-1];
end
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) data_ff <= '0;
else data_ff <= data_next;
end
endmodule
module index_generator
import vgachargen_pkg::*;
(
input logic [VGA_MAX_V_WIDTH -1:0] vcount_i,
input logic [VGA_MAX_H_WIDTH -1:0] hcount_i,
output logic [CH_MAP_ADDR_WIDTH-1:0] ch_map_addr_o,
output logic [BITMAP_ADDR_WIDTH-1:0] bitmap_addr_o
);
logic [CH_H_WIDTH-1:0] haddr_chars;
logic [CH_V_WIDTH-1:0] vaddr_chars;
assign haddr_chars = CH_H_WIDTH'(hcount_i >> BITMAP_H_WIDTH);
assign vaddr_chars = CH_V_WIDTH'(vcount_i >> BITMAP_V_WIDTH);
`define _MULT_BY_80(_x) ((_x << 6) + (_x << 4))
assign ch_map_addr_o = `_MULT_BY_80(vaddr_chars) + haddr_chars;
`undef _MULT_BY_80
logic [BITMAP_H_WIDTH-1:0] haddr_pixels;
logic [BITMAP_V_WIDTH-1:0] vaddr_pixels;
assign haddr_pixels = hcount_i[BITMAP_H_WIDTH-1:0];
assign vaddr_pixels = vcount_i[BITMAP_V_WIDTH-1:0];
`define _MULT_BY_8(_x) (_x << 3)
assign bitmap_addr_o = `_MULT_BY_8(vaddr_pixels) + haddr_pixels;
`undef _MULT_BY_8
endmodule
module single_port_ro_bram #(
parameter INIT_FILE_NAME = "",
parameter INIT_FILE_IS_BIN = 0,
parameter int unsigned DATA_WIDTH = 2,
parameter int unsigned ADDR_WIDTH = 4,
localparam int unsigned DEPTH_WORDS = 2 ** ADDR_WIDTH
) (
input logic clk_i,
input logic [ADDR_WIDTH-1:0] addr_i,
output logic [DATA_WIDTH-1:0] dout_o
);
logic [DATA_WIDTH-1:0] mem[DEPTH_WORDS];
if (INIT_FILE_IS_BIN) initial $readmemb(INIT_FILE_NAME, mem, 0, DEPTH_WORDS-1);
else initial $readmemh(INIT_FILE_NAME, mem, 0, DEPTH_WORDS-1);
always_ff @(posedge clk_i) begin
dout_o <= mem[addr_i];
end
endmodule
module timing_generator
import vgachargen_pkg::*;
(
input logic clk_i,
input logic arstn_i,
input logic en_i,
output logic vga_hs_o,
output logic vga_vs_o,
// Display timing counters
output logic [VGA_MAX_H_WIDTH-1:0] hcount_o,
output logic [VGA_MAX_V_WIDTH-1:0] vcount_o,
output logic pixel_enable_o
);
logic [VGA_MAX_H_WIDTH-1:0] hcount_ff;
logic hcount_en;
logic [VGA_MAX_H_WIDTH-1:0] hcount_next;
logic [VGA_MAX_V_WIDTH-1:0] vcount_ff;
logic vcount_en;
logic [VGA_MAX_V_WIDTH-1:0] vcount_next;
// Horizontal counter
assign hcount_next = ( hcount_ff < ( HTOTAL - 1 ) ) ? ( hcount_ff + 1 ) : ( '0 );
always_ff @ ( posedge clk_i or negedge arstn_i )
if ( ~arstn_i ) hcount_ff <= '0;
else if (en_i) hcount_ff <= hcount_next;
// Vertical counter
assign vcount_en = ( hcount_ff == ( HTOTAL - 1 ) ) & en_i;
assign vcount_next = ( vcount_ff < ( VTOTAL - 1 ) ) ? ( vcount_ff + 1 ) : ( '0 );
always_ff @( posedge clk_i or negedge arstn_i )
if ( ~arstn_i ) vcount_ff <= '0;
else if ( vcount_en ) vcount_ff <= vcount_next;
enum {
DISPLAY_S,
FRONT_S,
SYNC_S,
BACK_S
} hstate_ff, hstate_next,
vstate_ff, vstate_next;
always_ff @( posedge clk_i or negedge arstn_i )
if( ~arstn_i ) begin
hstate_ff <= DISPLAY_S;
vstate_ff <= DISPLAY_S;
end else if (en_i) begin
hstate_ff <= hstate_next;
vstate_ff <= vstate_next;
end
always_comb begin
hstate_next = hstate_ff;
unique case( hstate_ff)
DISPLAY_S: if( hcount_ff == HD - 1 ) hstate_next = FRONT_S;
FRONT_S: if( hcount_ff == HD + HF - 1 ) hstate_next = SYNC_S;
SYNC_S: if( hcount_ff == HD + HF + HR - 1 ) hstate_next = BACK_S;
BACK_S: if( hcount_ff == HTOTAL - 1 ) hstate_next = DISPLAY_S;
default: hstate_next = DISPLAY_S;
endcase
end
always_comb begin
vstate_next = vstate_ff;
if( vcount_en ) begin
unique case( vstate_ff)
DISPLAY_S: if( vcount_ff == VD - 1 ) vstate_next = FRONT_S;
FRONT_S: if( vcount_ff == VD + VF - 1 ) vstate_next = SYNC_S;
SYNC_S: if( vcount_ff == VD + VF + VR - 1 ) vstate_next = BACK_S;
BACK_S: if( vcount_ff == VTOTAL - 1 ) vstate_next = DISPLAY_S;
default: vstate_next = DISPLAY_S;
endcase
end
end
logic vga_vs_ff;
logic vga_vs_next;
assign vga_vs_next = vstate_next inside {DISPLAY_S, FRONT_S, BACK_S};
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) vga_vs_ff <= 1'b1;
else if (en_i) vga_vs_ff <= vga_vs_next;
end
logic vga_hs_ff;
logic vga_hs_next;
assign vga_hs_next = hstate_next inside {DISPLAY_S, FRONT_S, BACK_S};
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) vga_hs_ff <= 1'b1;
else if (en_i) vga_hs_ff <= vga_hs_next;
end
logic pixel_enable_ff;
logic pixel_enable_next;
assign pixel_enable_next = ( vstate_next == DISPLAY_S ) && ( hstate_next == DISPLAY_S );
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) pixel_enable_ff <= 1'b0;
else if (en_i) pixel_enable_ff <= pixel_enable_next;
end
assign vga_hs_o = vga_hs_ff;
assign vga_vs_o = vga_vs_ff;
assign pixel_enable_o = pixel_enable_ff;
assign hcount_o = hcount_ff;
assign vcount_o = vcount_ff;
endmodule
module true_dual_port_rw_bram #(
parameter INIT_FILE_NAME = "",
parameter INIT_FILE_IS_BIN = 0,
parameter int unsigned COL_WIDTH = 8,
parameter int unsigned NUM_COLS = 4,
parameter int unsigned ADDR_WIDTH = 4,
localparam int unsigned DATA_WIDTH = NUM_COLS * COL_WIDTH,
localparam int unsigned DEPTH_WORDS = 2 ** ADDR_WIDTH
) (
input logic clka_i,
input logic clkb_i,
input logic [ADDR_WIDTH-1:0] addra_i,
input logic [ADDR_WIDTH-1:0] addrb_i,
input logic [NUM_COLS -1:0] wea_i,
input logic [DATA_WIDTH-1:0] dina_i,
output logic [DATA_WIDTH-1:0] douta_o,
output logic [DATA_WIDTH-1:0] doutb_o
);
logic [DATA_WIDTH-1:0] mem[DEPTH_WORDS];
if (INIT_FILE_NAME != "") begin : use_init_file
if (INIT_FILE_IS_BIN) initial $readmemb(INIT_FILE_NAME, mem, 0, DEPTH_WORDS-1);
else initial $readmemh(INIT_FILE_NAME, mem, 0, DEPTH_WORDS-1);
end else begin : init_bram_to_zero
initial begin
for (int unsigned i = 0; i < DEPTH_WORDS; ++i) mem[i] = '0;
end
end
always_ff @(posedge clka_i) begin
for (int i = 0; i < NUM_COLS; ++i) begin
if (wea_i[i]) mem[addra_i][i*COL_WIDTH+:COL_WIDTH] <= dina_i[i*COL_WIDTH+:COL_WIDTH];
end
end
always_ff @(posedge clka_i) begin
douta_o <= mem[addra_i];
end
always_ff @(posedge clkb_i) begin
doutb_o <= mem[addrb_i];
end
endmodule
module vga_block
import vgachargen_pkg::*;
#(
parameter int unsigned CLK_FACTOR_25M = 4
) (
input logic clk_i,
input logic arstn_i,
output logic [VGA_MAX_H_WIDTH-1:0] hcount_o,
output logic [VGA_MAX_V_WIDTH-1:0] vcount_o,
output logic pixel_enable_o,
output logic vga_hs_o,
output logic vga_vs_o
);
logic clk_divider_strb;
clk_divider # (
.DIVISOR (CLK_FACTOR_25M)
) clk_divider (
.clk_i,
.arstn_i,
.strb_o (clk_divider_strb)
);
timing_generator timing_generator (
.clk_i,
.arstn_i,
.en_i (clk_divider_strb),
.vga_hs_o,
.vga_vs_o,
.hcount_o,
.vcount_o,
.pixel_enable_o
);
endmodule

View File

@@ -0,0 +1,78 @@
package vgachargen_pkg;
parameter int unsigned HD = 640; // Display area
parameter int unsigned HF = 16; // Front porch
parameter int unsigned HR = 96; // Retrace/Sync
parameter int unsigned HB = 48; // Back Porch
parameter int unsigned VD = 480;
parameter int unsigned VF = 10;
parameter int unsigned VR = 2;
parameter int unsigned VB = 33;
parameter int unsigned HTOTAL = HD + HF + HR + HB;
parameter int unsigned VTOTAL = VD + VF + VR + VB;
parameter int unsigned VGA_MAX_H_WIDTH = $clog2(HTOTAL);
parameter int unsigned VGA_MAX_V_WIDTH = $clog2(VTOTAL);
parameter int unsigned BITMAP_H_PIXELS = 8;
parameter int unsigned BITMAP_V_PIXELS = 16;
parameter int unsigned BITMAP_H_WIDTH = $clog2(BITMAP_H_PIXELS);
parameter int unsigned BITMAP_V_WIDTH = $clog2(BITMAP_V_PIXELS);
parameter int unsigned CH_T_DATA_WIDTH = BITMAP_H_PIXELS * BITMAP_V_PIXELS;
parameter int unsigned BITMAP_ADDR_WIDTH = $clog2(CH_T_DATA_WIDTH);
parameter int unsigned CHARSET_COUNT = 256;
parameter int unsigned CH_T_ADDR_WIDTH = $clog2(CHARSET_COUNT/2);
parameter int unsigned CH_H_PIXELS = HD / BITMAP_H_PIXELS;
parameter int unsigned CH_V_PIXELS = VD / BITMAP_V_PIXELS;
parameter int unsigned CH_V_WIDTH = $clog2(CH_V_PIXELS);
parameter int unsigned CH_H_WIDTH = $clog2(CH_H_PIXELS);
parameter int unsigned CH_MAP_ADDR_WIDTH = CH_V_WIDTH + CH_H_WIDTH;
parameter int unsigned CH_MAP_DATA_WIDTH = CH_T_ADDR_WIDTH + 1;
parameter int unsigned COL_MAP_ADDR_WIDTH = CH_MAP_ADDR_WIDTH;
typedef enum logic [23:0] {
COL_0 = 24'h000000,
COL_1 = 24'h0000d8,
COL_2 = 24'h00d800,
COL_3 = 24'h00d8d8,
COL_4 = 24'hd80000,
COL_5 = 24'hd800d8,
COL_6 = 24'hd8d800,
COL_7 = 24'hd8d8d8,
COL_9 = 24'h0000ff,
COL_10 = 24'h00ff00,
COL_11 = 24'h00ffff,
COL_12 = 24'hff0000,
COL_13 = 24'hff00ff,
COL_14 = 24'hffff00,
COL_15 = 24'hffffff
} rgb_t;
function automatic logic [11:0] rgb2half(rgb_t rgb_i);
return {rgb_i[23:20], rgb_i[15:12], rgb_i[7:4]};
endfunction
function automatic logic [11:0] color_decode(logic [3:0] color_encoded_i);
unique case (color_encoded_i)
4'h0 : return rgb2half(COL_0 );
4'h1 : return rgb2half(COL_1 );
4'h2 : return rgb2half(COL_2 );
4'h3 : return rgb2half(COL_3 );
4'h4 : return rgb2half(COL_4 );
4'h5 : return rgb2half(COL_5 );
4'h6 : return rgb2half(COL_6 );
4'h7 : return rgb2half(COL_7 );
4'h8 : return rgb2half(COL_0 );
4'h9 : return rgb2half(COL_9 );
4'ha : return rgb2half(COL_10);
4'hb : return rgb2half(COL_11);
4'hc : return rgb2half(COL_12);
4'hd : return rgb2half(COL_13);
4'he : return rgb2half(COL_14);
4'hf : return rgb2half(COL_15);
default: return rgb2half(COL_0 );
endcase
endfunction
endpackage

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 [DIV_WIDTH-1:0] sys_rstn_buf;
logic ex_arstn_buffered;
assign ex_arstn_buffered = ex_arstn_buf[1];
assign sys_reset_o = !sys_rstn_buf[DIV_WIDTH-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-1;
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[DIV_WIDTH-2:0], 1'b1};
end
end
endmodule

View File

@@ -0,0 +1,125 @@
//////////////////////////////////////////////////////////////////////////////////
// Company: MIET
// Engineer: Andrei Solodovnikov
// Module Name: tb_riscv_unit
// Project Name: RISCV_practicum
// Target Devices: Nexys A7-100T
// Description: tb for peripheral units
//
//////////////////////////////////////////////////////////////////////////////////
module tb_riscv_unit();
logic clk;
logic ps2_clk;
logic ps2_dat;
logic resetn;
logic [15:0] sw_i;
logic [15:0] led_o;
logic parity;
logic starter;
logic [ 6:0] hex_led_o;
logic [ 7:0] hex_sel_o;
logic rx_i;
logic tx_o;
logic [3:0] cntr;
initial begin clk = 0; ps2_clk = 0; end
always #5ns clk = ~clk;
always #50000 if(starter || (cntr > 0)) ps2_clk = ~ps2_clk; else ps2_clk = 1;
logic [11:0] data, uart_data;
initial #6ms $finish();
initial begin
resetn = 1;
repeat(20)@(posedge clk);
resetn = 0;
repeat(20) @(posedge clk);
resetn = 1;
end
riscv_unit dut(
.clk_i (clk ),
.resetn_i (resetn ),
.sw_i (sw_i ),
.led_o (led_o ),
.kclk_i (ps2_clk ),
.kdata_i (ps2_dat ),
.hex_led_o(hex_led_o),
.hex_sel_o(hex_sel_o),
.rx_i (rx_i ),
.tx_o (tx_o )
);
initial begin: sw_block
sw_i = 16'd0;
repeat(1000) @(posedge clk);
sw_i = 16'hdead;
repeat(1000) @(posedge clk);
sw_i = 16'h5555;
repeat(1000) @(posedge clk);
sw_i = 16'hbeef;
repeat(1000) @(posedge clk);
sw_i = 16'haaaa;
end
always @(negedge ps2_clk) begin: ps2_always_block
if(starter || (cntr > 0))
if(cntr == 10)
cntr <= 0;
else
cntr <= cntr + 1;
end
assign ps2_dat = cntr>0? data[cntr-1] : 1;
initial begin: ps2_initial_block
cntr = 0;
starter = 0;
data = 0;
repeat(10000) @(posedge clk);
ps2_send_scan_code(8'h1c);
ps2_send_scan_code(8'he0);
ps2_send_scan_code(8'hf0);
ps2_send_scan_code(8'h1c);
ps2_send_scan_code(8'h5c);
end
task ps2_send_scan_code(input logic [7:0] code);
data = {2'b11, !(^code), code, 1'b0};
starter = 1;
@(posedge ps2_clk);
starter = 0;
repeat(10) @(posedge ps2_clk);
endtask
initial begin: uart_rx_initial_block
uart_data = '1;
repeat(1000) @(posedge clk);
uart_rx_send_char(8'h1c, 115200);
uart_rx_send_char(8'h0D, 115200);
uart_rx_send_char(8'h0D, 115200);
uart_rx_send_char(8'h7F, 115200);
uart_rx_send_char(8'h7F, 115200);
end
assign rx_i = uart_data[0];
int uart_cntr;
task uart_rx_send_char(input logic [7:0] char, input logic [31:0] baudrate);
uart_data = {2'b11, (^char), char, 1'b0};
uart_cntr = 0;
while(uart_cntr <= 15) begin
#(1s/baudrate);
uart_data = {1'b1, uart_data[11:1]};
uart_cntr++;
end
endtask
endmodule