Переработка лабораторных работ, связанных с памятью (#89)

* Переработка лабораторных работ, связанных с памятью

Существенно переработаны ЛР3 и ЛР7:

Из ЛР3 убрано задание реализовать память данных. Эта память
использовалась только студентами ИВТ и только в рамках одной лабы.
В итоге использовалась готовая память, и ничего не мешает использовать
ее с самого начала.

Задание по реализации памяти инструкций также претерпело изменения.
Теперь код памяти инструкций предоставляется сразу. Это объясняется тем,
что код модуля состоит в общем-то из 4х строк, на которые тратится
слишком много времени (с учетом добавления тестбенча и проверок).
Кроме того, использование готового кода позволяет дать модуль чуть
посложнее (с параметризацией размера).

По итогу правок, третья лабораторная работа превращается чисто в
лабораторную по написанию регистрового файла, что должно положительно
сказаться на кривой сложности лаб. После второй лабы происходит слишком
резкий скачок в объемах работы.

Соответственно, в связи с тем, что память данных больше не делается на
третьей лабе, дополнительная ЛР по памяти данных с byte enable
необходимо перенести до реализации тракта данных.

* ЛР3, 5, 6. Правки из ревью

* ЛР7. Добавление иллюстраций
This commit is contained in:
Andrei Solodovnikov
2024-07-02 10:24:41 +03:00
committed by GitHub
parent 06dc07c03f
commit 85883858ac
36 changed files with 278 additions and 368 deletions

207
Labs/07. Datapath/README.md Normal file
View File

@@ -0,0 +1,207 @@
# Лабораторная работа 6 "Тракт данных"
Микроархитектуру можно разделить на две части: тракт данных и устройство управления. По тракту данных перемещаются данные (из памяти инструкций, регистрового файла, АЛУ, памяти данных, мультиплексоров), а устройство управления (основной дешифратор команд) получает текущую инструкцию из тракта и в ответ говорит ему как именно выполнить эту инструкцию, то есть управляет тем, как эти данные будут через тракт данных проходить.
## Цель
Описать на языке **SystemVerilog** процессор с архитектурой **RISC-V**, реализовав его тракт данных, используя разработанные ранее блоки, и подключив к нему устройство управления. Итогом текущей лабораторной работы станет процессор RISC-V, который пока что сможет работать с памятью данных лишь посредством 32-битных слов (то есть БЕЗ инструкций, связанных с байтами и полусловами: `lh`, `lhu`, `lb`, `lbu`, `sh`, `sb`).
## Ход работы
1. Изучить микроархитектурную реализацию однотактного процессора RISC-V (без поддержки команд загрузки/сохранения байт/полуслов)
2. Реализовать тракт данных с подключенным к нему устройством управления([#задание](#задание))
3. Подготовить программу по индивидуальному заданию и загрузить ее в память инструкций
4. Сравнить результат работы процессора на модели в **Vivado** и в симуляторе программы ассемблера
## Микроархитектура RISC-V
### riscv_core
Рассмотрим микроархитектуру процессорного ядра `riscv_core`. Данный модуль обладает следующим прототипом и микроархитектурой:
```SystemVerilog
module riscv_core (
input logic clk_i,
input logic rst_i,
input logic stall_i,
input logic [31:0] instr_i,
input logic [31:0] mem_rd_i,
output logic [31:0] instr_addr_o,
output logic [31:0] mem_addr_o,
output logic [ 2:0] mem_size_o,
output logic mem_req_o,
output logic mem_we_o,
output logic [31:0] mem_wd_o
);
endmodule
```
![../../.pic/Labs/lab_07_dp/fig_01.drawio.svg](../../.pic/Labs/lab_07_dp/fig_01.drawio.svg)
_Рисунок 1. Микроархитектура ядра процессора RISC-V._
В отличие от реализованного ранее процессора с архитектурой CYBERcobra, в данном модуле отсутствует память (она подключается извне, а значит у этого модуля должны быть сигналы интерфейса памяти).
Кроме того, в данной микроархитектуре используется пять различных видов констант (соответствующих определенным типам инструкций).
Константы `I`,`U`,`S` используются для вычисления адресов и значений. Поэтому все эти константы должны быть подключены к АЛУ. А значит теперь, для выбора значения для операндов требуются мультиплексоры, определяющие что именно будет подаваться на АЛУ.
Обратите внимание на константу `imm_U`. В отличие от всех остальных констант, она не знакорасширяется, вместо этого к ней приклеивается справа 12 нулевых бит.
Программный счетчик (`PC`) теперь также изменяется более сложным образом. Поскольку появился еще один вид безусловного перехода (`jalr`), программный счетчик может не просто увеличиться на значение константы из инструкции, но и получить совершенно новое значение в виде суммы константы и значения из регистрового файла (см. на самый левый мультиплексор схемы). Обратите внимание, что младший бит этой суммы должен быть обнулен — таково требование спецификации.
Поскольку обращение во внешнюю память требует времени, необходимо останавливать программный счетчик, чтобы до конца обращения в память не начались исполняться последующие инструкции. Для этого у программного счетчика появился управляющий сигнал `stall_i`. Программный счетчик может меняться только когда этот сигнал равен нулю (иными словами, инверсия этого сигнала является сигналом `enable` для регистра `PC`).
### riscv_unit
После реализации процессорного ядра, к нему необходимо подключить память. Это происходит в модуле `riscv_unit`.
```SystemVerilog
module riscv_unit(
input logic clk_i,
input logic rst_i
);
endmodule
```
![../../.pic/Labs/lab_07_dp/fig_02.drawio.svg](../../.pic/Labs/lab_07_dp/fig_02.drawio.svg)
_Рисунок 2. Микроархитектура процессора._
Обратите внимание на регистр `stall`. Этот регистр и будет управлять разрешением на запись в программный счетчик `PC`. Поскольку мы используем блочную память, расположенную прямо в ПЛИС, доступ к ней осуществляется за 1 такт, а значит, что при обращении в память, нам необходимо "отключить" программный счетчик ровно на 1 такт. Если бы использовалась действительно "внешняя" память (например чип DDR3), то вместо этого регистра появилась бы другая логика, выставляющая на вход ядра `stall_i` единицу пока идет обращение в память.
## Задание
Реализовать ядро процессора `riscv_core` архитектуры RISC-V по предложенной микроархитектуре. Подключить к нему память инструкций и память данных в модуле `riscv_unit`. Проверить работу процессора с помощью программы, написанной на ассемблере RISC-V по индивидуальному заданию, которое использовалось для написания программы для процессора архитектуры CYBERcobra.
<!--
### Как инициализировать память инструкций новой программой
Поскольку теперь ваш процессор почти полностью соответствует спецификации RISC-V, вы можете пользоваться существующими компиляторами, а значит, теперь для написании программы можно воспользоваться языком ассемблера RISC-V (помните, что пока вы не поддерживаете инструкции `lh`, `lhu`, `lb`, `lbu`, `sh`, `sb`).
Обычно ассемблеры выдают код собранной программы в виде шестнадцатеричных строк. При записи программы в файл инициализации, вы должны убрать префикс `0x`, если таковой имеется, поскольку системная функция инициализации памяти `$readmemh` и так уже настроена читать в шестнадцатеричном формате.
Кроме того, поскольку каждая ячейка памяти занимает 8 бит, необходимо разбить строки инструкции на отдельные байты. Однако после того как вы это сделаете, нарушится порядок байт. Микроархитектурная реализация процессора построена с использованием порядка байт под названием **Little endian**. Это означает, что старший байт инструкции должен располагаться по старшему адресу, младший байт инструкции — по младшему (привязка к **Little endian** вытекает из двух модулей: памяти инструкций и декодера инструкций). Проблема заключается в том, что функция `$readmemh` загружает байты, начиная с младших адресов.
Предположим, мы описываем содержимое памяти инструкций и у нас есть очередная инструкция `0xDEADBEEF` (`jal`). Если она должна быть размещена в памяти, начиная с адреса `4`, то байт `EF` должен находиться по 4-ому адресу, байт `BE` — по пятому и т.п. Допустим, мы разделили байты инструкций символами переноса строк (и что строки в файле нумеруются с нуля). Тогда соответствие между строкой, байтом инструкции и адресом в памяти, где этот байт должен быть расположен будет следующим:
![../../.pic/Labs/lab_07_dp/fig_02.excel.png](../../.pic/Labs/lab_07_dp/fig_02.excel.png)
Если после разделения инструкции переносами, мы не изменим порядок байт в файле, при считывании файла САПР будет инициализировать память наоборот: ячейка с младшим адресом будет проинициализирована строкой с младшим номером. Если оставить все как есть, процессор считает из памяти инструкцию `0xEFBEADDE` (вместо jal получаем нелегальную инструкцию, т.к. младшие 2 бита не равны 1).
Чтобы данные легли в память в нужном порядке, **необходимо изменить порядок следования байт в текстовом файле**. Современные текстовые редакторы поддерживают режим множественных курсоров, что позволяет довольно быстро выполнить данную процедуру.
<details>
<summary> Пример такого редактирования </summary>
В VSCode дополнительные курсоры создаются либо через `alt+ЛКМ`, либо через `alt+ctrl+UP`, `alt+ctrl+DOWN`. Vivado так же поддерживает множественные курсоры (проведя мышью с зажатой ЛКМ вдоль нужных строк при зажатой клавише `Ctrl`).
![Пример создания и использования множественных курсоров](../../../technical/Other/Pic/multicursor_edit_example.gif)
</details>
-->
Напишем простую программу, которая использует все типы инструкций для проверки нашего процессора. Сначала напишем программу на ассемблере:
```assembly
00: addi x1, x0, 0x75С
04: addi x2, x0, 0x8A7
08: add x3, x1, x2
0C: and x4, x1, x2
10: sub x5, x4, x3
14: mul x6, x3, x4 // неподдерживаемая инструкция
18: jal x15, 0x00050 // прыжок на адрес 0x68
1C: jalr x15, 0x0(x6)
20: slli x7, x5, 31
24: srai x8, x7, 1
28: srli x9, x8, 29
2C: lui x10, 0xfadec
30: addi x10, x10,-1346
34: sw x10, 0x0(x4)
38: sh x10, 0x6(x4)
3C: sb x10, 0xb(x4)
40: lw x11, 0x0(x4)
44: lh x12, 0x0(x4)
48: lb x13, 0x0(x4)
4С: lhu x14, 0x0(x4)
50: lbu x15, 0x0(x4)
54: auipc x16, 0x00004
58: bne x3, x4, 0x08 // перескок через
5С: // нелегальную нулевую инструкцию
60: jal x17, 0x00004
64: jalr x14, 0x0(x17)
68: jalr x18, 0x4(x15)
```
Теперь в соответствии с кодировкой инструкций переведем программу в машинные коды:
```text
00: 011101011100 00000 000 00001 0010011 (0x75C00093)
04: 100010100111 00000 000 00010 0010011 (0x8A700113)
08: 0000000 00010 00001 000 00011 0110011 (0x002081B3)
0C: 0000000 00010 00001 111 00100 0110011 (0x0020F233)
10: 0100000 00011 00100 000 00101 0110011 (0x403202B3)
14: 0000001 00100 00011 000 00110 0110011 (0x02418333)
18: 00000101000000000000 01111 1101111 (0x050007EF)
1C: 000000000000 00110 000 01111 1100111 (0x000307E7)
20: 0000000 11111 00101 001 00111 0010011 (0x01F29393)
24: 0100000 00001 00111 101 01000 0010011 (0x4013D413)
28: 0000000 11101 01000 101 01001 0010011 (0x01D45493)
2C: 11111010110111101100 01010 0110111 (0xFADEC537)
30: 101010111110 01010 000 01010 0010011 (0xABE50513)
34: 0000000 01010 00100 010 00000 0100011 (0x00A22023)
38: 0000000 01010 00100 001 00110 0100011 (0x00A21323)
3C: 0000000 01010 00100 000 01011 0100011 (0x00A205A3)
40: 000000000000 00100 010 01011 0000011 (0x00022583)
44: 000000000000 00100 001 01100 0000011 (0x00021603)
48: 000000000000 00100 000 01101 0000011 (0x00020683)
4C: 000000000000 00100 101 01110 0000011 (0x00025703)
50: 000000000000 00100 100 01111 0000011 (0x00024783)
54: 00000000000000000100 10000 0010111 (0x00004817)
58: 0000000 00011 00100 001 01000 1100011 (0x00321463)
5C: 00000000 00000000 00000000 00000000 (0x00000000)
60: 00000000010000000000 10001 1101111 (0x004008EF)
64: 000000000000 10001 000 01110 1100111 (0x00088767)
68: 000000000100 01111 000 10010 1100111 (0x00478967)
```
Данная программа, представленная в шестнадцатеричном формате находится в файле [program.mem](program.mem).
## Порядок выполнения задания
1. Внимательно ознакомьтесь микроархитектурной реализацией. В случае возникновения вопросов, проконсультируйтесь с преподавателем.
2. Реализуйте модуль `riscv_core`. Для этого:
1. В `Design Sources` проекта с предыдущих лаб, создайте `SystemVerilog`-файл `riscv_core.sv`.
2. Опишите в нем модуль процессор `riscv_core` с таким же именем и портами, как указано в [задании](#задание).
1. Процесс реализации модуля очень похож на процесс описания модуля cybercobra, однако теперь появляется:
1. декодер
2. дополнительные мультиплексоры и знакорасширители.
3. Создайте в проекте новый `SystemVerilog`-файл `riscv_unit.sv` и опишите в нем модуль `riscv_unit`, объединяющий ядро процессора (`riscv_core`) с памятями инструкция и данных.
1. **При создании объекта модуля `riscv_core` в модуле `riscv_unit` вы должны использовать имя сущности `core` (т.е. создать объект в виде: `riscv_core core(...`)**
3. После описания модуля, его необходимо проверить с помощью тестового окружения.
1. Тестовое окружение находится [`здесь`](tb_riscv_unit.sv).
2. Программа, которой необходимо проинициализировать память инструкций находится в файле [`program.mem`](program.mem).
3. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
4. Перед запуском симуляции убедитесь, что выбран правильный модуль верхнего уровня.
5. **Во время симуляции убедитесь, что в логе есть сообщение о завершении теста!**
6. Вполне возможно, что после первого запуска вы столкнетесь с сообщениями о множестве ошибок. Вам необходимо [исследовать](../../Vivado%20Basics/Debug%20manual.md) эти ошибки на временной диаграмме и исправить их в вашем модуле.
4. Проверьте работоспособность вашей цифровой схемы в ПЛИС. Для этого:
1. Добавьте файлы из папки [`board files`](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files) в проект.
1. Файл [nexys_riscv_unit.sv](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files/nexys_riscv_unit.sv) необходимо добавить в `Design Sources` проекта.
2. Файл [nexys_a7_100t.xdc](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files/nexys_a7_100t.xdc) необходимо добавить в `Constraints` проекта. В случае, если вы уже добавляли одноименный файл в рамках предыдущих лабораторных работ, его содержимое необходимо заменить содержимым нового файла.
2. Выберите `nexys_riscv_unit` в качестве модуля верхнего уровня (`top-level`).
3. Выполните генерацию битстрима и сконфигурируйте ПЛИС. Для этого воспользуйтесь [следующей инструкцией](../../Vivado%20Basics/How%20to%20program%20an%20fpga%20board.md).
4. Описание логики работы модуля верхнего уровня и связи периферии ПЛИС с реализованным модулем находится в папке [`board files`](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files).
---
<details>
<summary>Прочти меня, когда выполнишь.</summary>
Поздравляю, ты сделал(а) свой первый взрослый процессор! Теперь ты можешь говорить:
>Я способен(на) на всё! Я сам(а) полностью, с нуля, сделал(а) процессор с архитектурой RISC-V! Что? Не знаешь, что такое архитектура? Пф, щегол! Подрастешь узнаешь
</details>

View File

@@ -0,0 +1,38 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Andrei Solodovnikov
* Email(s) : hepoh@org.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
package alu_opcodes_pkg;
localparam ALU_OP_WIDTH = 5;
localparam ALU_ADD = 5'b00000;
localparam ALU_SUB = 5'b01000;
localparam ALU_XOR = 5'b00100;
localparam ALU_OR = 5'b00110;
localparam ALU_AND = 5'b00111;
// shifts
localparam ALU_SRA = 5'b01101;
localparam ALU_SRL = 5'b00101;
localparam ALU_SLL = 5'b00001;
// comparisons
localparam ALU_LTS = 5'b11100;
localparam ALU_LTU = 5'b11110;
localparam ALU_GES = 5'b11101;
localparam ALU_GEU = 5'b11111;
localparam ALU_EQ = 5'b11000;
localparam ALU_NE = 5'b11001;
// set lower than operations
localparam ALU_SLTS = 5'b00010;
localparam ALU_SLTU = 5'b00011;
endpackage

View File

@@ -0,0 +1,46 @@
# Проверка работы riscv_unit на ПЛИС
После того, как вы проверили на моделировании дизайн, вам необходимо проверить его работу на прототипе в ПЛИС.
Инструкция по реализации прототипа описана [здесь](../../../Vivado%20Basics/How%20to%20program%20an%20fpga%20board.md).
На _рис. 1_ представлена схема прототипа в ПЛИС.
![../../../.pic/Labs/board%20files/nexys_riscv_unit_structure.drawio.svg](../../../.pic/Labs/board%20files/nexys_riscv_unit_structure.drawio.svg)
_Рисунок 1. Структурная схема модуля `nexys_riscv_unit`._
Прототип позволяет потактово исполнять программу, прошитую в память инструкций. Также прототип отображает операцию исполняемую в данный момент.
> [!NOTE]
> Объект модуля `riscv_core` в модуле `riscv_unit` **должен** называться `core`. Т.е. строка создания сущности модуля должна выглядеть следующим образом: `riscv_core core(...)`.
## Описание используемой периферии
- ### Кнопки
- `BTND` — при нажатии создает тактовый импульс, поступающий на порт тактирования `clk_i` модуля дизайна. Стоит помнить то, что инструкции, работающие с внешней памятью, требуют несколько тактов для своего выполнения.
- `CPU_RESET` — соединен со входом `rst_i` модуля дизайна. Поскольку в модуле `riscv_unit` используется синхронный сброс (то есть сигнал сброса учитывается только во время восходящего фронта тактового сигнала), то для сброса модуля `riscv_unit` и вложенных в него модулей необходимо при зажатой кнопке сброса еще нажать кнопку тактирования.
- ### Семисегментные индикаторы
Семисегментные индикаторы разбиты на 2 блока (см. _рис. 1_):
- `PC` — отображают в виде шестнадцатеричного числа младшие 16 бит программного счетчика, которые вычисляются на основе выхода `instr_addr_o` модуля процессорного ядра.
- `operation` — отображают [операцию](#операции-отображаемые-прототипом), исполняемую процессором на текущем такте.
## Операции, отображаемые прототипом
Прототип определяет тип операции по младшим 7 битам инструкции.
Если тип операции является легальным в рамках процессорного устройства, реализуемого на лабораторных работах, то отображается соответствующий опкод. Опкоды описаны в [decoder_pkg.sv](../../05.%20Main%20decoder/decoder_pkg.sv). Если определенный прототипом тип операции является нелегальным, то на семисегментных индикаторах отображается `ILL` (от **ill**egal).
Соответствие операции ее отображению на семисегментных индикаторах представлено на _рис. 2_:
!['../../../.pic/Labs/board%20files/nexys_riscv_unit_operations.drawio.svg'](../../../.pic/Labs/board%20files/nexys_riscv_unit_operations.drawio.svg)
_Рисунок 2. Соответствие операции ее отображению на семисегментных индикаторах._
## Демонстрационная программа
В качестве демонстрационной программы, предлагается использовать [program.mem](../program.mem). Описание ее работы можно прочитать в разделе [#задание](../README.md#задание).

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 }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk_i}];
#Switches
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { SW[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
#set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { SW[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { SW[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { SW[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { SW[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { SW[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { SW[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { SW[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
#set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { SW[8] }]; #IO_L24N_T3_34 Sch=sw[8]
#set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { SW[9] }]; #IO_25_34 Sch=sw[9]
#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { SW[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { SW[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { SW[12] }]; #IO_L24P_T3_35 Sch=sw[12]
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { SW[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13]
#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { SW[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14]
#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { SW[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15]
### LEDs
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
#set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { LED[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { LED[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { LED[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { LED[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { LED[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { LED[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { LED[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { LED[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]
### RGB LEDs
#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { LED16_B }]; #IO_L5P_T0_D06_14 Sch=led16_b
#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { LED16_G }]; #IO_L10P_T1_D14_14 Sch=led16_g
#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { LED16_R }]; #IO_L11P_T1_SRCC_14 Sch=led16_r
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { LED17_B }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led17_b
#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { LED17_G }]; #IO_0_14 Sch=led17_g
#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { LED17_R }]; #IO_L11N_T1_SRCC_14 Sch=led17_r
##7 segment display
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { ca_o }]; #IO_L24N_T3_A00_D16_14 Sch=ca
set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { cb_o }]; #IO_25_14 Sch=cb
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { cc_o }]; #IO_25_15 Sch=cc
set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { cd_o }]; #IO_L17P_T2_A26_15 Sch=cd
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ce_o }]; #IO_L13P_T2_MRCC_14 Sch=ce
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { cf_o }]; #IO_L19P_T3_A10_D26_14 Sch=cf
set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { cg_o }]; #IO_L4P_T0_D04_14 Sch=cg
set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { dp_o }]; #IO_L19N_T3_A21_VREF_15 Sch=dp
set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { an_o[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0]
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { an_o[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1]
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { an_o[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2]
set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { an_o[3] }]; #IO_L19P_T3_A22_15 Sch=an[3]
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { an_o[4] }]; #IO_L8N_T1_D12_14 Sch=an[4]
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { an_o[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5]
set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { an_o[6] }]; #IO_L23P_T3_35 Sch=an[6]
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { an_o[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7]
##Buttons
set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { arstn_i }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn
#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_i }]; #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[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0]
#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1]
#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2]
#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3]
#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0]
#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1]
#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2]
#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3]
#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0]
#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[1] }]; #IO_L4N_T0_35 Sch=vga_b[1]
#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2]
#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[3] }]; #IO_L4P_T0_35 Sch=vga_b[3]
#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { VGA_HS }]; #IO_L4P_T0_15 Sch=vga_hs
#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { VGA_VS }]; #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 { UART_TXD_IN }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in
#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { UART_RXD_OUT }]; #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 { PS2_CLK }]; #IO_L13P_T2_MRCC_35 Sch=ps2_clk
#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { PS2_DATA }]; #IO_L10N_T1_AD15N_35 Sch=ps2_data
##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,334 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Alexander Kharlamov
* Email(s) : sasha_xarlamov@org.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
typedef enum {
INSTR_ALU , // branch and computational
INSTR_LI , // const load
INSTR_IN , // periphery load
INSTR_JUMP ,
INSTR_NOP // ws == 3
} Instruction_type;
typedef enum {
CH_0 = 0,
CH_1,
CH_2,
CH_3,
CH_4,
CH_5,
CH_6,
CH_7,
CH_8,
CH_9,
CH_A,
CH_b,
CH_c,
CH_d,
CH_E,
CH_F,
CH_G,
CH_L,
CH_n,
CH_o,
CH_r,
CH_S,
CH_t,
CH_u,
CH_X,
CH_P,
CH_J,
CH_q,
CH_i,
CH_m,
CH_y,
CH_h,
CH_SPACE
} Char;
typedef struct {
logic ca;
logic cb;
logic cc;
logic cd;
logic ce;
logic cf;
logic cg;
logic dp;
} Semseg;
module nexys_riscv_unit(
input logic clk_i,
input logic arstn_i,
input logic btnd_i,
output logic ca_o,
output logic cb_o,
output logic cc_o,
output logic cd_o,
output logic ce_o,
output logic cf_o,
output logic cg_o,
output logic dp_o,
output logic [ 7:0] an_o
);
logic btnd_sync;
sync sync (
.clk_i ,
.data_i (btnd_i ),
.data_o (btnd_sync)
);
logic btnd_debounce;
debounce debounce (
.clk_i ,
.arstn_i (1'b1 ),
.data_i (btnd_sync ),
.data_o (btnd_debounce)
);
logic bufg_clk;
BUFG dut_bufg(
.I (btnd_debounce),
.O (bufg_clk )
);
riscv_unit unit(
.clk_i (bufg_clk),
.rst_i (!arstn_i)
);
logic [31:0] instr_addr;
logic [31:0] instr;
assign instr_addr = unit.core.instr_addr_o;
assign instr = unit.core.instr_i;
import alu_opcodes_pkg::*;
logic illegal_instr;
logic [6:0] opcode;
assign opcode = instr[6:0];
Char op_chars[0:3];
import decoder_pkg::*;
always_comb begin
op_chars = '{4{CH_SPACE}};
case (opcode)
{LOAD_OPCODE , 2'b11}: op_chars = '{CH_L, CH_o, CH_A, CH_d};
{MISC_MEM_OPCODE, 2'b11}: op_chars = '{CH_m, CH_i, CH_S, CH_c};
{OP_IMM_OPCODE , 2'b11}: op_chars = '{CH_o, CH_P, CH_i, CH_m};
{AUIPC_OPCODE , 2'b11}: op_chars = '{CH_A, CH_u, CH_i, CH_P};
{STORE_OPCODE , 2'b11}: op_chars = '{CH_S, CH_t, CH_o, CH_r};
{OP_OPCODE , 2'b11}: op_chars[0:1] = '{CH_o, CH_P};
{LUI_OPCODE , 2'b11}: op_chars[0:2] = '{CH_L, CH_u, CH_i};
{BRANCH_OPCODE , 2'b11}: op_chars = '{CH_b, CH_r, CH_c, CH_h};
{JALR_OPCODE , 2'b11}: op_chars = '{CH_J, CH_A, CH_L, CH_r};
{JAL_OPCODE , 2'b11}: op_chars[0:2] = '{CH_J, CH_A, CH_L};
{SYSTEM_OPCODE , 2'b11}: op_chars[0:2] = '{CH_S, CH_y, CH_S};
default : op_chars[0:2] = '{CH_i, CH_L, CH_L};
endcase
end
Char all_chars[0:7];
assign all_chars[0:3] = {
Char'(instr_addr[15:12]),
Char'(instr_addr[11: 8]),
Char'(instr_addr[ 7: 4]),
Char'(instr_addr[ 3: 0])
};
assign all_chars[4:7] = op_chars;
Char current_char;
logic [7:0] an;
semseg_one2many #(
.DATA_T (Char)
) semseg_one2many (
.clk100m_i (clk_i ),
.arstn_i (arstn_i ),
.all_semsegs_i (all_chars ),
.current_semseg_o (current_char),
.an_o (an )
);
Semseg current_semseg;
char2semseg char2semseg (
.char_i (current_char ),
.semseg_o (current_semseg)
);
assign ca_o = current_semseg.ca;
assign cb_o = current_semseg.cb;
assign cc_o = current_semseg.cc;
assign cd_o = current_semseg.cd;
assign ce_o = current_semseg.ce;
assign cf_o = current_semseg.cf;
assign cg_o = current_semseg.cg;
assign dp_o = current_semseg.dp;
assign an_o = an;
endmodule
module char2semseg #(
parameter bit HEX_ONLY = 1'b0
) (
input Char char_i,
output Semseg semseg_o
);
localparam bit [6:0] BLANK = '1;
logic [6:0] semseg;
always_comb begin
case (char_i)
CH_0 : semseg = ~7'h3F;
CH_1 : semseg = ~7'h06;
CH_2 : semseg = ~7'h5B;
CH_3 : semseg = ~7'h4F;
CH_4 : semseg = ~7'h66;
CH_5 : semseg = ~7'h6D;
CH_6 : semseg = ~7'h7D;
CH_7 : semseg = ~7'h07;
CH_8 : semseg = ~7'h7F;
CH_9 : semseg = ~7'h6F;
CH_A : semseg = ~7'h5F;
CH_b : semseg = ~7'h7C;
CH_c : semseg = ~7'h58;
CH_d : semseg = ~7'h5E;
CH_E : semseg = ~7'h79;
CH_F : semseg = ~7'h71;
CH_G : semseg = ~7'h3D;
CH_L : semseg = ~7'h38;
CH_n : semseg = ~7'h54;
CH_o : semseg = ~7'h5C;
CH_r : semseg = ~7'h50;
CH_S : semseg = ~7'h64;
CH_t : semseg = ~7'h78;
CH_u : semseg = ~7'h1C;
CH_X : semseg = ~7'h76;
CH_P : semseg = ~7'h73;
CH_J : semseg = ~7'h1E;
CH_q : semseg = ~7'h67;
CH_i : semseg = ~7'h30;
CH_m : semseg = ~7'h77;
CH_y : semseg = ~7'h6E;
CH_h : semseg = ~7'h74;
default : semseg = BLANK;
endcase
end
assign semseg_o.ca = semseg[0];
assign semseg_o.cb = semseg[1];
assign semseg_o.cc = semseg[2];
assign semseg_o.cd = semseg[3];
assign semseg_o.ce = semseg[4];
assign semseg_o.cf = semseg[5];
assign semseg_o.cg = semseg[6];
assign semseg_o.dp = 1'b1;
endmodule
module semseg_one2many #(
parameter int unsigned SEMSEGS_NUM = 8,
parameter type DATA_T
) (
input DATA_T all_semsegs_i[0:SEMSEGS_NUM-1],
input logic clk100m_i,
input logic arstn_i,
output DATA_T current_semseg_o,
output logic [7:0] an_o
);
logic clk_i;
assign clk_i = clk100m_i;
localparam int COUNTER_WIDTH = 10;
logic [COUNTER_WIDTH-1:0] counter_next;
logic [COUNTER_WIDTH-1:0] counter_ff;
assign counter_next = counter_ff + COUNTER_WIDTH'('b1);
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) counter_ff <= '0;
else counter_ff <= counter_next;
end
logic [7:0] an_ff;
logic [7:0] an_next;
logic an_en;
assign an_next = {an_ff[$left(an_ff)-1:0], an_ff[$left(an_ff)]};
assign an_en = ~|counter_ff;
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) an_ff <= ~8'b1;
else if (an_en) an_ff <= an_next;
end
DATA_T current_semseg;
always_comb begin
unique case (1'b0)
an_ff[0]: current_semseg = all_semsegs_i[7];
an_ff[1]: current_semseg = all_semsegs_i[6];
an_ff[2]: current_semseg = all_semsegs_i[5];
an_ff[3]: current_semseg = all_semsegs_i[4];
an_ff[4]: current_semseg = all_semsegs_i[3];
an_ff[5]: current_semseg = all_semsegs_i[2];
an_ff[6]: current_semseg = all_semsegs_i[1];
an_ff[7]: current_semseg = all_semsegs_i[0];
endcase
end
assign current_semseg_o = current_semseg;
assign an_o = an_ff;
endmodule
module debounce #(
parameter int unsigned MAX_COUNT = 10000
) (
input logic clk_i,
input logic arstn_i,
input logic data_i,
output logic data_o
);
localparam int COUNTER_WIDTH = $clog2(MAX_COUNT);
logic [COUNTER_WIDTH-1:0] counter_next;
logic [COUNTER_WIDTH-1:0] counter_ff;
assign counter_next = (data_o != data_i) ? counter_ff - COUNTER_WIDTH'('b1) :
COUNTER_WIDTH'(MAX_COUNT);
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) counter_ff <= COUNTER_WIDTH'(MAX_COUNT);
else counter_ff <= counter_next;
end
always_ff @(posedge clk_i or negedge arstn_i) begin
if (!arstn_i) data_o <= '0;
else if (~|counter_ff) data_o <= data_i;
end
endmodule
module sync #(
parameter int unsigned SYNC_STAGES = 3
) (
input logic clk_i,
input logic data_i,
output logic data_o
);
logic [SYNC_STAGES-1:0] sync_buffer_ff;
logic [SYNC_STAGES-1:0] sync_buffer_next;
assign sync_buffer_next = {sync_buffer_ff[$left(sync_buffer_ff)-1:0], data_i};
always_ff @(posedge clk_i) begin
sync_buffer_ff <= sync_buffer_next;
end
assign data_o = sync_buffer_ff[$left(sync_buffer_ff)];
endmodule

View File

@@ -0,0 +1,26 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Andrei Solodovnikov
* Email(s) : hepoh@org.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
package csr_pkg;
localparam CSR_RW = 3'b001;
localparam CSR_RS = 3'b010;
localparam CSR_RC = 3'b011;
localparam CSR_RWI = 3'b101;
localparam CSR_RSI = 3'b110;
localparam CSR_RCI = 3'b111;
localparam MIE_ADDR = 12'h304;
localparam MTVEC_ADDR = 12'h305;
localparam MSCRATCH_ADDR = 12'h340;
localparam MEPC_ADDR = 12'h341;
localparam MCAUSE_ADDR = 12'h342;
endpackage

View File

@@ -0,0 +1,54 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Andrei Solodovnikov
* Email(s) : hepoh@org.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
package decoder_pkg;
import alu_opcodes_pkg::*;
export alu_opcodes_pkg::*;
import csr_pkg::*;
export csr_pkg::*;
// opcodes
localparam LOAD_OPCODE = 5'b00_000;
localparam MISC_MEM_OPCODE = 5'b00_011;
localparam OP_IMM_OPCODE = 5'b00_100;
localparam AUIPC_OPCODE = 5'b00_101;
localparam STORE_OPCODE = 5'b01_000;
localparam OP_OPCODE = 5'b01_100;
localparam LUI_OPCODE = 5'b01_101;
localparam BRANCH_OPCODE = 5'b11_000;
localparam JALR_OPCODE = 5'b11_001;
localparam JAL_OPCODE = 5'b11_011;
localparam SYSTEM_OPCODE = 5'b11_100;
// dmem type load store
localparam LDST_B = 3'b000;
localparam LDST_H = 3'b001;
localparam LDST_W = 3'b010;
localparam LDST_BU = 3'b100;
localparam LDST_HU = 3'b101;
// operand a selection
localparam OP_A_RS1 = 2'b00;
localparam OP_A_CURR_PC = 2'b01;
localparam OP_A_ZERO = 2'b10;
// operand b selection
localparam OP_B_RS2 = 3'b000;
localparam OP_B_IMM_I = 3'b001;
localparam OP_B_IMM_U = 3'b010;
localparam OP_B_IMM_S = 3'b011;
localparam OP_B_INCR = 3'b100;
// writeback source selection
localparam WB_EX_RESULT = 2'd0;
localparam WB_LSU_DATA = 2'd1;
localparam WB_CSR_DATA = 2'd2;
endpackage

View File

@@ -0,0 +1,18 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Andrei Solodovnikov
* Email(s) : hepoh@org.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
package memory_pkg;
localparam INSTR_MEM_SIZE_BYTES = 512;
localparam INSTR_MEM_SIZE_WORDS = INSTR_MEM_SIZE_BYTES / 4;
localparam DATA_MEM_SIZE_BYTES = 512;
localparam DATA_MEM_SIZE_BYTES = DATA_MEM_SIZE_BYTES / 4;
endpackage

View File

@@ -0,0 +1,27 @@
75C00093
8A700113
002081B3
0020F233
403202B3
02418333
050007EF
000307E7
01F29393
4013D413
01D45493
fadec537
abe50513
00A22023
00A21323
00A205A3
00022583
00021603
00020683
00025703
00024783
00004817
00321463
00000000
004008EF
00088767
00478967

View File

@@ -0,0 +1,42 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Nikita Bulavin
* Email(s) : nekkit6@edu.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
module tb_riscv_unit();
reg clk;
reg rst;
riscv_unit unit(
.clk_i(clk),
.rst_i(rst)
);
initial clk = 0;
always #10 clk = ~clk;
initial begin
$display( "\nStart test: \n\n==========================\nCLICK THE BUTTON 'Run All'\n==========================\n"); $stop();
rst = 1;
#40;
rst = 0;
#800;
$display("\n The test is over \n See the internal signals of the module on the waveform \n");
$finish;
end
stall_seq: assert property (
@(posedge unit.core.clk_i) disable iff ( unit.core.rst_i )
unit.core.mem_req_o |-> (unit.core.stall_i || $past(unit.core.stall_i))
)else $error("\nincorrect implementation of stall signal\n");
stall_seq_fall: assert property (
@(posedge unit.core.clk_i) disable iff ( unit.core.rst_i )
(unit.core.stall_i) |=> !unit.core.stall_i
)else $error("\nstall must fall exact one cycle after rising\n");
endmodule