mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
WIP: APS cumulative update (#98)
* WIP: APS cumulative update * Update How FPGA works.md * Перенос раздела "Последовательностная логика" в отдельный док * Исправление картинки * Исправление оформления индексов * Переработка раздела Vivado Basics * Добавление картинки в руководство по созданию проекта * Исправление ссылок в анализе rtl * Обновление изображения в sequential logic * Исправление ссылок в bug hunting * Исправление ссылок * Рефактор руководства по прошивке ПЛИС * Mass update * Update fig_10 * Restore fig_02
This commit is contained in:
committed by
GitHub
parent
78bb01ef95
commit
a28002e681
@@ -6,23 +6,23 @@
|
||||
|
||||
Описать память данных, с побайтовой адресацией.
|
||||
|
||||
## Материал для подготовки к лабораторной работе
|
||||
## Материалы для подготовки к лабораторной работе
|
||||
|
||||
Для успешного выполнения лабораторной работы, вам необходимо использовать навыки, полученные при написании [лабораторной работы №3](../03.%20Register%20file%20and%20memory/) "Регистровый файл и память инструкций";
|
||||
Для успешного выполнения лабораторной работы, вам необходимо использовать навыки, полученные при написании [ЛР№3](../03.%20Register%20file%20and%20memory/) "Регистровый файл и память инструкций";
|
||||
|
||||
## Теория
|
||||
|
||||
В задании по реализации памяти инструкций [лабораторной работы №3](../03.%20Register%20file%20and%20memory/) байтовая адресация была описана следующим образом:
|
||||
В задании по реализации памяти инструкций [ЛР№3](../03.%20Register%20file%20and%20memory/) байтовая адресация была описана следующим образом:
|
||||
|
||||
> Байтовая адресация означает, что процессор способен обращаться к отдельным байтам в памяти (за каждым байтом памяти закреплен свой индивидуальный адрес).
|
||||
> Байтовая адресация означает, что процессор способен обращаться к отдельным байтам в памяти (за каждым байтом памяти закреплён свой индивидуальный адрес).
|
||||
|
||||
Данное описание было дано не совсем корректным образом, чтобы в третьей лабораторной работе было более четкое понимание задания. В чем заключается некорректность? Процессор должен быть способен не только **обращаться** к отдельным байтам в памяти, но и **обновлять** в памяти любой отдельный байт, а также **считывать** отдельные байты.
|
||||
Данное описание было дано не совсем корректным образом, чтобы в третьей лабораторной работе было более чёткое понимание задания. В чём заключается некорректность? Процессор должен быть способен не только **обращаться** к отдельным байтам в памяти, но и **обновлять** в памяти любой отдельный байт, а также **считывать** отдельные байты.
|
||||
|
||||
Вопрос считывания отдельного байта будет решаться специальным модулем **загрузки и сохранения**. Памяти данных при этом будет достаточно возвращать всё слово, содержащее запрашиваемый байт как это уже было сделано памяти инструкций.
|
||||
|
||||
Нас интересует возможность памяти обновлять любой из байт в слове. Подобный функционал часто используется при реализации памяти и в системных интерфейсах, например AXI4 или APB. Для этого используется специальный сигнал, который называется `byte enable`. Разрядность этого сигнала равна числу байт в шине данных (в нашем случае разрядность `byte enable` составляет 4). Вы можете представить этот сигнал, как 4 провода, каждый из которых является сигналом разрешения записи для отдельной памяти с шириной данных в 1 байт.
|
||||
|
||||
Давайте разберемся как это будет работать. Допустим, мы хотим записать значение `0xA5` по адресу `0x6`. Поскольку мы работаем с байтовой адресацией, а ячейки памяти 32-битные — как и при реализации памяти инструкций, пришедший адрес необходимо будет разделить на 4 (см. _рис. 1_). В итоге мы получим указатель на первую 32-битную ячейку памяти (`6 / 4 = 1`). Однако, чтобы пришедшие данные были в итоге записаны не в нулевой байт первого слова (четвертый байт памяти), а во второй, мы будем использовать сигнал `byte enable`, второй бит которого будет равен `1`. Это значит, что лучше разделить запись в отдельные байты памяти и для каждого байта проверять отдельно соответствующий бит `byte enable`, независимо от остальных.
|
||||
Давайте разберёмся как это будет работать. Допустим, мы хотим записать значение `0xA5` по адресу `0x6`. Поскольку мы работаем с байтовой адресацией, а ячейки памяти 32-битные — как и при реализации памяти инструкций, пришедший адрес необходимо будет разделить на 4 (см. _рис. 1_). В итоге мы получим указатель на первую 32-битную ячейку памяти (`6 / 4 = 1`). Однако, чтобы пришедшие данные были в итоге записаны не в нулевой байт первого слова (четвёртый байт памяти), а во второй, мы будем использовать сигнал `byte enable`, второй бит которого будет равен `1`. Это значит, что лучше разделить запись в отдельные байты памяти и для каждого байта проверять отдельно соответствующий бит `byte enable`, независимо от остальных.
|
||||
|
||||

|
||||
|
||||
@@ -30,7 +30,7 @@ _Рисунок 1. Связь адреса байта с индексом сло
|
||||
|
||||
Чтобы данные остальных байт не были испорчены, при описании памяти на SystemVerilog нужно разделить запись в отдельные байты. Для того, чтобы получить доступ к отдельным диапазонам бит ячейки памяти, после указания индекса ячейки необходимо указать диапазон бит, к которым вы хотите получить доступ. К примеру, чтобы получить доступ к битам с 5-го по 3-ий 18-ой ячейки памяти, необходимо использовать следующую запись:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
mem[18][5:3];
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ mem[18][5:3];
|
||||
|
||||
Прототип модуля следующий:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module data_mem
|
||||
import memory_pkg::DATA_MEM_SIZE_BYTES;
|
||||
import memory_pkg::DATA_MEM_SIZE_WORDS;
|
||||
@@ -99,28 +99,24 @@ _Рисунок 2. Операции запросов на чтение._
|
||||
|
||||
Если `mem_req_i == 1` и `write_enable_i == 1`, то происходит запрос на запись в память. В этом случае, необходимо записать значение `write_data_i` в ячейку по, на которую указывает `addr_i`. Во всех других случаях (любой из сигналов `mem_req_i`, `write_enable_i` равен нулю), запись в память не производится. Запись необходимо производить только в те байты указанной ячейки, которым соответствуют биты сигнала `byte_enable_i`, равные 1.
|
||||
|
||||
На _рис. 3_ показан пример записей по различным адресам. Т.к. деление на 4 любого из приведенных на _рис. 3_ адресов дает результат 2, на рисунке показано только содержимое второй 32-битной ячейки памяти и то, как оно менялось в зависимости от комбинации сигналов `write_data_i` и `byte_enable_i`.
|
||||
На _рис. 3_ показан пример записей по различным адресам. Т.к. деление на 4 любого из приведенных на _рис. 3_ адресов даёт результат 2, на рисунке показано только содержимое второй 32-битной ячейки памяти и то, как оно менялось в зависимости от комбинации сигналов `write_data_i` и `byte_enable_i`.
|
||||
|
||||

|
||||
|
||||
_Рисунок 3. Операции запросов на запись._
|
||||
|
||||
Выход `ready_o` в данном модуле должен всегда быть равен 1, поскольку данные всегда будут выдаваться на следующий такт. В реальности, обращение в память может занимать сотни тактов процессора, причем их число бывает недетерминированным (нельзя заранее предсказать сколько тактов займет очередной запрос в память). Именно поэтому стандартные интерфейсы обычно используют такие сигналы как `ready` или `valid`, позволяющие синхронизировать разные блоки системы. Сигнал `ready_o` в нашем интерфейсе используется сигнала о задержке в выдаче данных. В случае, если устройству нужно больше одного такта, чтобы выдать данные, он устанавливает на данный сигнал значение `0` до тех пор, пока данные не будут готовы.
|
||||
Выход `ready_o` в данном модуле должен всегда быть равен 1, поскольку данные всегда будут выдаваться на следующий такт. В реальности, обращение в память может занимать сотни тактов процессора, причём их число бывает недетерминированным (нельзя заранее предсказать сколько тактов займёт очередной запрос в память). Именно поэтому стандартные интерфейсы обычно используют такие сигналы как `ready` или `valid`, позволяющие синхронизировать разные блоки системы. Сигнал `ready_o` в нашем интерфейсе используется сигнала о задержке в выдаче данных. В случае, если устройству нужно больше одного такта, чтобы выдать данные, он устанавливает на данный сигнал значение `0` до тех пор, пока данные не будут готовы.
|
||||
|
||||
## Порядок выполнения работы
|
||||
|
||||
1. Внимательно ознакомьтесь с заданием. В случае возникновения вопросов, проконсультируйтесь с преподавателем.
|
||||
2. Реализуйте память данных. Для этого:
|
||||
1. В `Design Sources` проекта создайте `SystemVerilog`-файл `data_mem.sv`.
|
||||
2. Опишите в нем модуль памяти данных с таким же именем и портами, как указано в задании.
|
||||
1. Описание модуля будет схожим с описанием модуля памяти инструкций, однако порт чтения в этот раз будет **синхронным** (запись в него будет происходить в блоке `always_ff`). Количество ячеек памяти данных определяется параметром `DATA_MEM_SIZE_WORDS`, определенным в `memory_pkg`. Кроме того, необходимо будет описать логику записи данных в память.
|
||||
2. Запись в ячейки памяти описывается подобно записи данных в [регистры](../../Basic%20Verilog%20structures/Registers.md), только при этом, происходит доступ к конкретной ячейке памяти с помощью входа `addr_i`.
|
||||
3. Перед тем как обратиться к ячейке памяти, значение с `addr_i` необходимо преобразовать по аналогии с памятью инструкций.
|
||||
4. Обратите внимание что работа с памятью должна осуществляться только когда сигнал `mem_req_i == 1`. В противном случае запись не должна производиться, а на шине `read_data_o` должен оставаться результат предыдущего чтения.
|
||||
5. При этом запись должна вестись только в те байты выбранной ячейки памяти, которым соответствуют биты сигнала `byte_enable_i`, выставленные в `1`.
|
||||
6. У памяти есть дополнительный выход `ready_o`, который всегда равен единице.
|
||||
3. После описания модуля его необходимо проверить с помощью тестового окружения.
|
||||
1. Тестовое окружение находится [`здесь`](tb_data_mem.sv).
|
||||
2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||||
3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_data_mem`).
|
||||
4. **По завершению симуляции убедитесь, что в логе есть сообщение о завершении теста!**
|
||||
1. Опишите память данных с таким же именем и портами, как указано в задании.
|
||||
1. Обратите внимание, что имя памяти (не название модуля, а имя массива регистров внутри модуля) должно быть **ram**. Такое имя необходимо для корректной работы верификационного окружения
|
||||
2. Описание модуля будет схожим с описанием модуля памяти инструкций, однако порт чтения в этот раз будет **синхронным** (запись в него будет происходить в блоке `always_ff`). Количество ячеек памяти данных определяется параметром `DATA_MEM_SIZE_WORDS`, определенным в `memory_pkg`. Кроме того, необходимо будет описать логику записи данных в память.
|
||||
3. Запись в ячейки памяти описывается подобно записи данных в [регистры](../../Basic%20Verilog%20structures/Registers.md), только при этом, происходит доступ к конкретной ячейке памяти с помощью входа `addr_i`.
|
||||
4. Перед тем как обратиться к ячейке памяти, значение с `addr_i` необходимо преобразовать по аналогии с памятью инструкций.
|
||||
5. Обратите внимание что работа с памятью должна осуществляться только когда сигнал `mem_req_i == 1`. В противном случае запись не должна производиться, а на шине `read_data_o` должен оставаться результат предыдущего чтения.
|
||||
6. При этом запись должна вестись только в те байты выбранной ячейки памяти, которым соответствуют биты сигнала `byte_enable_i`, выставленные в `1`.
|
||||
7. У памяти есть дополнительный выход `ready_o`, который всегда равен единице.
|
||||
2. Проверьте модуль с помощью верификационного окружения, представленного в файле [`lab_06.tb_data_mem.sv`](lab_06.tb_data_mem.sv). В случае, если в TCL-консоли появились сообщения об ошибках, вам необходимо [найти](../../Vivado%20Basics/05.%20Bug%20hunting.md) и исправить их.
|
||||
1. Перед запуском моделирования, убедитесь, что у вас выбран корректный модуль верхнего уровня в `Simulation Sources`.
|
||||
3. Данная лабораторная работа не предполагает проверки в ПЛИС.
|
||||
|
Reference in New Issue
Block a user