mirror of
https://github.com/MPSU/APS.git
synced 2025-09-16 01:30:10 +00:00
Merge pull request #55 from MPSU/svg-transition
Перенос drawio-изображений в svg-формат
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
|
||||
Давайте начнем с примера и сложим в столбик какую-нибудь пару чисел, например 42 и 79:
|
||||
|
||||

|
||||

|
||||
|
||||
```text
|
||||
2 + 9 = 11 ➨ 1 пишем, 1 "в уме"
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
Теперь попробуем сделать то же самое, только в двоичной системе исчисления. К примеру, над числами 3 и 5. Три в двоичной системе записывается как 011. Пять записывается как 101.
|
||||
|
||||

|
||||

|
||||
|
||||
Поскольку в двоичной системе всего две цифры: 0 и 1, один разряд не может превысить 1. Складывая числа 1 и 1, вы получаете 2, что не умещается в один разряд, поэтому мы пишем 0 и держим 1 "в уме". Это снова перенос разряда. Поскольку в двоичной арифметике разряд называют битом, перенос разряда называют переносом бита, а сам разряд, который перенесли — битом переноса.
|
||||
|
||||
@@ -58,25 +58,25 @@
|
||||
|
||||

|
||||
|
||||
*Таблица истинности одноразрядного сложения*
|
||||
_Таблица истинности одноразрядного сложения._
|
||||
|
||||
`S` — это цифра, записываемая в столбце сложения под числами `a` и `b`. `C` (*carry*, перенос) — это цифра, записываемая левее, если произошел перенос разряда. Как мы видим, перенос разряда происходит только в случае, когда оба числа одновременно равны единице. При этом в этот момент значение `S` обращается в `0`, и результат записывается как `10`, что в двоичной системе означает `2`. Кроме того, `S = 0` и в случае, когда оба операнда одновременно равны нулю. Вы можете заметить, что `S` равно нулю в тех случаях, когда `а` и `b` равны, и не равно нулю в противоположном случае. Подобным свойством обладает логическая операция **Исключающее ИЛИ** (**eXclusive OR**, **XOR**):
|
||||
`S` — это цифра, записываемая в столбце сложения под числами `a` и `b`. `C` (_carry_, перенос) — это цифра, записываемая левее, если произошел перенос разряда. Как мы видим, перенос разряда происходит только в случае, когда оба числа одновременно равны единице. При этом в этот момент значение `S` обращается в `0`, и результат записывается как `10`, что в двоичной системе означает `2`. Кроме того, `S = 0` и в случае, когда оба операнда одновременно равны нулю. Вы можете заметить, что `S` равно нулю в тех случаях, когда `а` и `b` равны, и не равно нулю в противоположном случае. Подобным свойством обладает логическая операция **Исключающее ИЛИ** (**eXclusive OR**, **XOR**):
|
||||
|
||||

|
||||
|
||||
*Таблица истинности операции Исключающее ИЛИ (XOR)*
|
||||
_Таблица истинности операции Исключающее ИЛИ (XOR)._
|
||||
|
||||
Для бита переноса всё ещё проще — он описывается операцией логическое И:
|
||||
|
||||

|
||||
|
||||
*Таблица истинности операции И*
|
||||
_Таблица истинности операции И._
|
||||
|
||||
Давайте нарисуем цифровую схему, связывающую входные и выходные сигналы с помощью логических элементов, соответствующих ожидаемому поведению:
|
||||
|
||||

|
||||

|
||||
|
||||
*Рисунок 1. Цифровая схема устройства, складывающего два операнда с сохранением переноса (полусумматора)*
|
||||
_Рисунок 1. Цифровая схема устройства, складывающего два операнда с сохранением переноса (полусумматора)._
|
||||
|
||||
Вроде все замечательно, но есть проблема. В описании полного однобитного сумматора сказано, что у него есть три входа, а в наших таблицах истинности и на схеме выше их только два. На самом деле, на каждом этапе сложения в столбик мы всегда складывали три числа: цифру верхнего числа, цифру нижнего числа, и единицу в случае переноса разряда из предыдущего столбца (если с предыдущего разряда не было переноса, прибавление нуля неявно опускалось).
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||

|
||||
|
||||
*Таблица истинности сигналов полного однобитного сумматора*
|
||||
_Таблица истинности сигналов полного однобитного сумматора._
|
||||
|
||||
Поскольку теперь у нас есть и входной и выходной биты переноса, для их различия добавлены индексы “in” и “out”.
|
||||
|
||||
@@ -98,9 +98,9 @@
|
||||
|
||||
Цифровая схема устройства с описанным поведением выглядит следующим образом:
|
||||
|
||||

|
||||

|
||||
|
||||
*Рисунок 2. Цифровая схема полного однобитного сумматора*
|
||||
_Рисунок 2. Цифровая схема полного однобитного сумматора._
|
||||
|
||||
## Практика
|
||||
|
||||
@@ -150,15 +150,15 @@ module half_adder(
|
||||
endmodule
|
||||
```
|
||||
|
||||
*Листинг 1. SystemVerilog-код модуля half_adder*
|
||||
_Листинг 1. SystemVerilog-код модуля half_adder._
|
||||
|
||||
По данному коду, САПР может реализовать следующую схему:
|
||||
|
||||

|
||||
|
||||
*Рисунок 3. Цифровая схема модуля half_adder, сгенерированная САПР Vivado*
|
||||
_Рисунок 3. Цифровая схема модуля half_adder, сгенерированная САПР Vivado._
|
||||
|
||||
Схема похожа на рис. 1, но как проверить, что эта схема не содержит ошибок и делает именно то, что от нее ожидается?
|
||||
Схема похожа на _рис. 1_, но как проверить, что эта схема не содержит ошибок и делает именно то, что от нее ожидается?
|
||||
|
||||
Для этого необходимо провести моделирование этой схемы. Во время моделирования на вход схемы подаются входные воздействия. Каждое изменение входных сигналов схемы приводит к каскадному изменению состояния внутренних цепей, которые в итоге меняют выходные сигналы.
|
||||
|
||||
@@ -191,13 +191,13 @@ module testbench(); // <- Не имеет ни входов, ни
|
||||
endmodule
|
||||
```
|
||||
|
||||
*Листинг 2. SystemVerilog-код тестбенча для модуля example*
|
||||
_Листинг 2. SystemVerilog-код тестбенча для модуля example._
|
||||
|
||||

|
||||
|
||||
*Рисунок 4. Временная диаграмма, моделирующая работу схемы с рис.3*
|
||||
_Рисунок 4. Временная диаграмма, моделирующая работу схемы с рис. 3._
|
||||
|
||||
В данной лабораторной работе вам предстоит реализовать схему полного однобитного сумматора (*рис. 2*).
|
||||
В данной лабораторной работе вам предстоит реализовать схему полного однобитного сумматора (_рис. 2_).
|
||||
|
||||
### Полный четырехбитный сумматор
|
||||
|
||||
@@ -207,18 +207,19 @@ endmodule
|
||||
|
||||
Давайте посмотрим, как это будет выглядеть на схеме (для простоты, внутренняя логика однобитного сумматора скрыта, но вы должны помнить, что каждый прямоугольник — это та же самая схема с рис. 2).
|
||||
|
||||

|
||||
*Рисунок 5. Схема четырехбитного сумматора*
|
||||

|
||||
|
||||
_Рисунок 5. Схема четырехбитного сумматора._
|
||||
|
||||
Фиолетовой линией на схеме показаны провода, соединяющие выходной бит переноса сумматора предыдущего разряда, с входным битом переноса сумматора следующего разряда.
|
||||
|
||||
Как же реализовать модуль, состоящий из цепочки других модулей? Половину этой задачи мы уже сделали, когда писали тестбенч к однобитному полусумматору в *Листинге 2* — мы создавали модуль внутри другого модуля и подключали к нему провода. Теперь надо сделать то же самое, только с чуть большим числом модулей.
|
||||
Как же реализовать модуль, состоящий из цепочки других модулей? Половину этой задачи мы уже сделали, когда писали тестбенч к однобитному полусумматору в _Листинге 2_ — мы создавали модуль внутри другого модуля и подключали к нему провода. Теперь надо сделать то же самое, только с чуть большим числом модулей.
|
||||
|
||||
Для того, чтобы описать четырехбитный сумматор, необходимо подключить четыре однобитных подобно тому, как было описано в [`документе`](../../Basic%20Verilog%20structures/Modules.md#иерархия-модулей), который вы изучали перед лабораторной работой.
|
||||
|
||||

|
||||
|
||||
*Рисунок 6. Схема четырехбитного сумматора, сгенерированная САПР Vivado*
|
||||
_Рисунок 6. Схема четырехбитного сумматора, сгенерированная САПР Vivado._
|
||||
|
||||
Схема может показаться запутанной, но (если присмотреться) вы увидите, как от шин A, B и S отходят линии к каждому из сумматоров, а бит переноса передается от предыдущего сумматора к следующему.
|
||||
|
||||
@@ -242,7 +243,7 @@ module fulladder4(
|
||||
|
||||

|
||||
|
||||
*Рисунок 7. Пример использования конструкции generate for*
|
||||
_Рисунок 7. Пример использования конструкции generate for._
|
||||
|
||||
Как вы можете догадаться, в этом примере создано 3 модуля, имена которых оканчиваются на значение итератора, по которому шел цикл, а к самим модулям подключены соответствующие итератору провода из шин. Разумеется, для своих целей вы можете использовать и **i+1** и двойные циклы.
|
||||
|
||||
@@ -275,13 +276,13 @@ module fulladder32(
|
||||
1. Согласно [руководству по созданию проекта в Vivado](../../Vivado%20Basics/Vivado%20trainer.md):
|
||||
1. Создайте проект;
|
||||
2. В `Design Sources` проекта создайте `SystemVerilog`-файл `fulladder`.
|
||||
2. Опишите в файле модуль `fulladder`, схема которого представлена на *[Рис. 2](../../.pic/Labs/lab_01_adder/fig_02.drawio.png)*.
|
||||
2. Опишите в файле модуль `fulladder`, схема которого представлена на _[Рис. 2](../../.pic/Labs/lab_01_adder/fig_02.drawio.svg)_.
|
||||
3. В `Simulation Sources` проекта создайте `SystemVerilog`-файл `tb_fulladder`.
|
||||
4. Вставьте содержимое файла [`tb_fulladder.sv`](tb_fulladder.sv), расположенного рядом с данным документом.
|
||||
5. Запустите моделирование. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||||
6. Убедитесь по сигналам временной диаграммы, что модуль работает корректно.
|
||||
7. В `Design Sources` проекта создайте `SystemVerilog`-файл `fulladder4`.
|
||||
8. Опишите модуль `fulladder4`, схема которого представлена на *Рис. 5 и 6*, используя [`иерархию модулей`](../../Basic%20Verilog%20structures/Modules.md#%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%8F-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B5%D0%B9), чтобы в нем выполнялось поразрядное сложение двух 4-разрядных чисел и входного бита переноса. Некоторые входы и выходы модуля будет необходимо описать в виде `векторов`.
|
||||
8. Опишите модуль `fulladder4`, схема которого представлена на _Рис. 5 и 6_, используя [`иерархию модулей`](../../Basic%20Verilog%20structures/Modules.md#%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%8F-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B5%D0%B9), чтобы в нем выполнялось поразрядное сложение двух 4-разрядных чисел и входного бита переноса. Некоторые входы и выходы модуля будет необходимо описать в виде `векторов`.
|
||||
9. Обратите внимание, что входной бит переноса должен подаваться на сумматор, выполняющий сложение нулевого разряда, выходной бит переноса соединяется с выходным битом переноса сумматора, выполняющего сложение 4-го разряда.
|
||||
10. В `Simulation Sources` проекта создайте `SystemVerilog`-файл `tb_fulladder4`.
|
||||
11. Вставьте содержимое файла [`tb_fulladder4.sv`](tb_fulladder4.sv). Нажмите по нему в окне `Sources` ПКМ и выберите `Set as Top`.
|
||||
|
@@ -26,27 +26,27 @@
|
||||
|
||||
Обычно АЛУ представляет собой комбинационную схему (то есть без элементов памяти), на входы которой поступают информационные (операнды) и управляющие (код операции) сигналы, в ответ на что на выходе появляется результат заданной операции. АЛУ бывает не комбинационной схемой, но это скорее исключение.
|
||||
|
||||

|
||||

|
||||
|
||||
*Рисунок 1. Структурное обозначение элемента АЛУ[1, стр. 305].*
|
||||
_Рисунок 1. Структурное обозначение элемента АЛУ[1, стр. 305]._
|
||||
|
||||
На рис. 1 изображен пример АЛУ, используемый в книге "Цифровая схемотехника и архитектура компьютера" Харрис и Харрис. На входы `A` и `B` поступают операнды с разрядностью *N*. На трехбитный вход `F` подается код операции. Например, если туда подать `000`, то на выходе `Y` появится результат операции *логическое И* между битами операндов `A` и `B`. Если на `F` подать `010`, то на выходе появится результат сложения. Это лишь пример, разрядность и коды могут отличаться в зависимости от количества выполняемых операций и архитектуры.
|
||||
На рис. 1 изображен пример АЛУ, используемый в книге "Цифровая схемотехника и архитектура компьютера" Харрис и Харрис. На входы `A` и `B` поступают операнды с разрядностью _N_. На трехбитный вход `F` подается код операции. Например, если туда подать `000`, то на выходе `Y` появится результат операции _логическое И_ между битами операндов `A` и `B`. Если на `F` подать `010`, то на выходе появится результат сложения. Это лишь пример, разрядность и коды могут отличаться в зависимости от количества выполняемых операций и архитектуры.
|
||||
|
||||
Существует несколько подходов к реализации АЛУ, отличающиеся внутренней организацией. В лабораторных работах применяется повсеместно используемый подход мультиплексирования операций, то есть подключения нескольких операционных устройств (которые выполняют какие-то операции, например сложения, логическое И и т.п.) к мультиплексору, который будет передавать результат нужного операционного устройства на выходы АЛУ.
|
||||
|
||||
Рассмотрим на примере все того же АЛУ MIPS из книги Харрисов. На рис. 2, в левой его части, изображена внутренняя организация этого АЛУ, справа – таблица соответствия кодов операциям. На выходе схемы (внизу) стоит четырехвходовый мультиплексор, управляемый двумя из трех битов `F`. К его входам подключены *N* логических И (побитовое И *N*-разрядных операндов), *N* логических ИЛИ, *N*-разрядный сумматор и Zero Extend – устройство делающее из однобитного числа *N*-битное число, дополняя нулями слева.
|
||||
Рассмотрим на примере все того же АЛУ MIPS из книги Харрисов. На рис. 2, в левой его части, изображена внутренняя организация этого АЛУ, справа – таблица соответствия кодов операциям. На выходе схемы (внизу) стоит четырехвходовый мультиплексор, управляемый двумя из трех битов `F`. К его входам подключены _N_ логических И (побитовое И _N_-разрядных операндов), _N_ логических ИЛИ, _N_-разрядный сумматор и Zero Extend – устройство делающее из однобитного числа _N_-битное число, дополняя нулями слева.
|
||||
|
||||
К одному из входов этих операционных устройств подключен `A` без изменений, а ко второму подключен выход двухвходового мультиплексора, управляемого оставшимся битом *F*. То есть `F[2]` определяет, что будет вторым операндом: `B` или `~B`. Вдобавок `F[2]` подается на входной перенос сумматора, то есть, когда `F[2] == 1` на выходе сумматора появляется результат операции `A + ~B + 1`, что (с учетом [дополнительного кода](https://ru.wikipedia.org/wiki/Дополнительный_код)) эквивалентно `A – B`.
|
||||
К одному из входов этих операционных устройств подключен `A` без изменений, а ко второму подключен выход двухвходового мультиплексора, управляемого оставшимся битом _F_. То есть `F[2]` определяет, что будет вторым операндом: `B` или `~B`. Вдобавок `F[2]` подается на входной перенос сумматора, то есть, когда `F[2] == 1` на выходе сумматора появляется результат операции `A + ~B + 1`, что (с учетом [дополнительного кода](https://ru.wikipedia.org/wiki/Дополнительный_код)) эквивалентно `A – B`.
|
||||
|
||||

|
||||

|
||||
|
||||
*Рисунок 2. Структурная схема АЛУ MIPS[1, стр. 305].*
|
||||
_Рисунок 2. Структурная схема АЛУ MIPS[1, стр. 305]._
|
||||
|
||||
Посмотрим, что произойдет, если на вход `F` такого АЛУ подать `111`. Будет выполняться операция `SLT`(сокращение от `Set Less Then`) – выдать `1`, если `A` меньше `B`, в противном случае — выдать `0`. Биты `F[1:0]` переключат мультиплексор на выход блока Zero Extend. На вход Zero Extend поступает старший бит выхода сумматора, этот бит отвечает за знак результата. Так как `F[2] == 1`, сумматор вычисляет `A + ~B + 1`, то есть `A – B`, значит, если `A < B`, то результат вычитания будет отрицательный, а старший бит `Y[N-1] == 1`. Если `A` не меньше `B`, то разность будет неотрицательна, а `Y[N-1] == 0`, как и требуется от этой операции.
|
||||
|
||||

|
||||

|
||||
|
||||
*Рисунок 3. Пример исполнения операции АЛУ.*
|
||||
_Рисунок 3. Пример исполнения операции АЛУ._
|
||||
|
||||
Преимущество такой организации АЛУ в его простой модификации, настройке под нужные коды операций, читаемости кода и масштабируемости. Можно легко добавить или убрать требуемые операции. Подумайте, как бы вы обновили данную схему, если бы от вас потребовалось расширить её функционал операциями XOR (Исключающее ИЛИ) и (SGE операция "больше либо равно")?
|
||||
|
||||
@@ -224,7 +224,7 @@ endmodule
|
||||
| OR | 0 0 110 |result_o = a_i \| b_i | Побитовое логическое **ИЛИ** |
|
||||
| AND | 0 0 111 |result_o = a_i & b_i | Побитовое логическое **И** |
|
||||
|
||||
*Таблица 1. Список вычислительных операций.*
|
||||
_Таблица 1. Список вычислительных операций._
|
||||
|
||||
В первой таблице перечислены операции, вычисляющие значение сигнала `flag_o`. **При любом коде операции `alu_op_i` не входящим в эту таблицу, сигнал `flag_o` должен быть равен нулю**.
|
||||
|
||||
@@ -237,11 +237,11 @@ endmodule
|
||||
| LTU | 1 1 110 | flag_o = a_i < b_i | Беззнаковое сравнение **<** |
|
||||
| GEU | 1 1 111 | flag_o = a_i ≥ b_i | Беззнаковое сравнение **≥** |
|
||||
|
||||
*Таблица 2. Список операций сравнения.*
|
||||
_Таблица 2. Список операций сравнения._
|
||||
|
||||
**Выражения в этих двух таблицах приведены для примера. Не все из них можно просто переписать — часть этих выражений надо дополнить. Чтобы вы не копировали выражения, в них вставлены неподдерживаемые символы.**
|
||||
|
||||
Несмотря на разделение на вычислительные операции, и операции сравнения, в *Таблице 1* (вычислительных операция) оказалось две операции `SLTS` и `SLTU`, которые выполняют сравнения. В итоге у нас есть две похожие пары инструкций:
|
||||
Несмотря на разделение на вычислительные операции, и операции сравнения, в _Таблице 1_ (вычислительных операция) оказалось две операции `SLTS` и `SLTU`, которые выполняют сравнения. В итоге у нас есть две похожие пары инструкций:
|
||||
|
||||
- `LTS`
|
||||
- `LTU`
|
||||
|
@@ -50,9 +50,9 @@
|
||||
|
||||
Так же возможна реализация, в которой вход `write_data` и выход `read_data` объединены в единый вход/выход `data`. В этом случае операции чтения и записи разделены во времени и используют для этого один единый порт ввода-вывода (`inout`, двунаправленный порт) `data`.
|
||||
|
||||

|
||||

|
||||
|
||||
*Рисунок 1. Примеры блоков ПЗУ и ОЗУ.*
|
||||
_Рисунок 1. Примеры блоков ПЗУ и ОЗУ._
|
||||
|
||||
Кроме того, различают память с **синхронным** и **асинхронным** чтением. В первом случае, перед выходным сигналом шины данных ставится дополнительный регистр, в который по тактовому синхроимпульсу записываются запрашиваемые данные. Такой способ может очень сильно сократить **критический путь** цифровой схемы, но требует дополнительный такт на доступ в память. В свою очередь, асинхронное чтение позволяет получить данные, не дожидаясь очередного синхроимпульса, но такой способ увеличивает критический путь.
|
||||
|
||||
@@ -64,15 +64,15 @@
|
||||
|
||||

|
||||
|
||||
*Рисунок 2. Структурная схема логического блока в ПЛИС[[1]](https://en.wikipedia.org/wiki/Field-programmable_gate_array).*
|
||||
_Рисунок 2. Структурная схема логического блока в ПЛИС[[1]](https://en.wikipedia.org/wiki/Field-programmable_gate_array)._
|
||||
|
||||
В логическом блоке есть **таблицы подстановки** (Look Up Table, LUT), которые представляют собой не что иное как память, которая переконфигурируется под нужды хранения, а не реализацию логики. Таким образом, трехвходовой LUT может выступать в роли восьмиразрядной памяти.
|
||||
|
||||
Однако LUT будет сложно приспособить под многопортовую память: посмотрим на схему еще раз: три входа LUT формируют адрес одной из восьми ячеек. Это означает, что среди этих восьми ячеек нельзя обратиться к двум из них одновременно.
|
||||
|
||||
Для реализации многопортовой памяти небольшого размера лучше воспользоваться расположенным в логическом блоке D-триггером (**DFF** на *рис. 2*). Несмотря на то, что D-триггер позволяет воспроизвести только 1 разряд элемента памяти, он не ограничивает реализацию по портам.
|
||||
Для реализации многопортовой памяти небольшого размера лучше воспользоваться расположенным в логическом блоке D-триггером (**DFF** на _рис. 2_). Несмотря на то, что D-триггер позволяет воспроизвести только 1 разряд элемента памяти, он не ограничивает реализацию по портам.
|
||||
|
||||
Таким образом, плюс распределенной памяти относительно регистровой заключается в лучшей утилизации ресурсов: одним трёхвходовым LUT можно описать до 8 бит распределенной памяти, в то время как одним D-триггером можно описать только один бит регистровой памяти. Предположим, что в ПЛИС размещены логические блоки, структура которых изображена на *рис. 2* и нам необходимо реализовать 1KiB памяти. Мы можем реализовать распределенную память, используя 64 логических блока (в каждом блоке два трёхвходовых LUT), либо регистровую память, используя 1024 логических блока.
|
||||
Таким образом, плюс распределенной памяти относительно регистровой заключается в лучшей утилизации ресурсов: одним трёхвходовым LUT можно описать до 8 бит распределенной памяти, в то время как одним D-триггером можно описать только один бит регистровой памяти. Предположим, что в ПЛИС размещены логические блоки, структура которых изображена на _рис. 2_ и нам необходимо реализовать 1KiB памяти. Мы можем реализовать распределенную память, используя 64 логических блока (в каждом блоке два трёхвходовых LUT), либо регистровую память, используя 1024 логических блока.
|
||||
|
||||
Минусом является ограниченность в реализации многопортовой памяти.
|
||||
|
||||
|
@@ -75,17 +75,19 @@ SYSTEM-инструкции используются для доступа к с
|
||||
|
||||

|
||||
|
||||
*Таблица 3. Инструкции набора RV32I с приведением их типов, функционального описания и примеров использования.*
|
||||
_Таблица 3. Инструкции набора RV32I с приведением их типов, функционального описания и примеров использования._
|
||||
|
||||
Обратите внимание на операции `slli`, `srli` и `srai` (операции сдвига на константную величину). У этих инструкций немного измененный формат кодирования **I\***. Формат кодирования **I** предоставляет 12-битную константу. Сдвиг 32-битного числа более, чем на 31 не имеет смысла. Для кодирования числа 31 требуется всего 5 бит. Выходит, что из 12 бит константы используется только 5 бит для операции сдвига, а оставшиеся 7 бит – не используются. А, главное (какое совпадение!), эти 7 бит находятся ровно в том же месте, где у других инструкций находится поле `func7`. Поэтому, чтобы у инструкций `slli`, `srli` и `srai` использующих формат **I** не пропадала эта часть поля, к ней относятся как к полю `func7`.
|
||||
|
||||
### Предлагаемая микроархитектура процессора RISC-V
|
||||
|
||||
Ниже приводится микроархитектура процессора RISC-V. Регистр `PC` (Program Counter – счетчик команд) подключен к адресному входу памяти инструкций. Считываемая инструкция декодируется основным дешифратором, после чего он выставляет управляющие сигналы для всех блоков процессора (мультиплексоры, АЛУ, интерфейс взаимодействия с памятью).
|
||||
На _рис. 1_ приводится микроархитектура ядра процессора RISC-V. Регистр `PC` (Program Counter – счетчик команд) подключен к адресному входу памяти инструкций. Считываемая инструкция декодируется основным дешифратором, после чего он выставляет управляющие сигналы для всех блоков процессора (мультиплексоры, АЛУ, интерфейс взаимодействия с памятью).
|
||||
|
||||
Приведенная архитектура не является заданием для текущей лабораторной работы, лишь отражает то, как в дальнейшем будет подключаться и использоваться реализуемый в данной лабораторной основной дешифратор.
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 1. Микроархитектура будущего процессорного ядра._
|
||||
|
||||
Предложенная микроархитектура процессора `CYBERcobra 3000 Pro 2.0` из прошлой лабораторной имеет схожую структуру, с некоторыми изменениями.
|
||||
|
||||
|
@@ -40,7 +40,9 @@ module riscv_core (
|
||||
endmodule
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 1. Микроархитектура ядра процессора RISC-V._
|
||||
|
||||
В отличие от реализованного ранее процессора с архитектурой CYBERcobra, в данном модуле отсутствует память (она подключается извне, а значит у этого модуля должны быть сигналы интерфейса памяти).
|
||||
|
||||
@@ -67,7 +69,9 @@ module riscv_unit(
|
||||
endmodule
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 2. Микроархитектура процессора._
|
||||
|
||||
Обратите внимание на регистр `stall`. Этот регистр и будет управлять разрешением на запись в программный счетчик `PC`. Поскольку мы используем блочную память, расположенную прямо в ПЛИС, доступ к ней осуществляется за 1 такт, а значит, что при обращении в память, нам необходимо "отключить" программный счетчик ровно на 1 такт. Если бы использовалась действительно "внешняя" память (например чип DDR3), то вместо этого регистра появилась бы другая логика, выставляющая на вход ядра `stall_i` единицу пока идет обращение в память.
|
||||
|
||||
|
@@ -31,9 +31,9 @@
|
||||
|
||||
Модуль загрузки и сохранения (**Load/Store Unit** – **LSU**) служит для исполнения инструкций типа `LOAD` и `STORE`: является прослойкой между внешним устройством – памятью, и ядром процессора. **LSU** считывает содержимое из памяти данных или записывает в нее требуемые значения, преобразуя 8- и 16-битные данные в знаковые или беззнаковые 32-битные числа для регистров процессора. В процессорах с **RISC** архитектурой с помощью **LSU** осуществляется обмен данными между регистрами общего назначения и памятью данных.
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 1. Место LSU в микроархитектуре RISC-процессора_
|
||||
_Рисунок 1. Место LSU в микроархитектуре RISC-процессора._
|
||||
|
||||
### Интерфейс процессора и блока загрузки/сохранения
|
||||
|
||||
@@ -177,11 +177,11 @@ _Рисунок 1. Место LSU в микроархитектуре RISC-пр
|
||||
- стать равным единице в тот же такт, когда пришел сигнал `core_req_i`
|
||||
- удерживать это значение до тех пор, пока не придет сигнал `mem_ready_i`, но не менее 1 такта (т.е. даже если сигнал `mem_ready_i` будет равен единице, `core_req_i` должен подняться хотя бы на 1 такт).
|
||||
|
||||
Для реализации подобного функционала вам потребуется вспомогательный регистр `stall_reg`, каждый такт записывающий значение выхода `core_stall_o` и следующая таблица истинности для этого выхода:
|
||||
Для реализации подобного функционала вам потребуется вспомогательный регистр `stall_reg`, каждый такт записывающий значение выхода `core_stall_o` и таблица истинности для этого выхода, представленная на _рис. 2_.
|
||||
|
||||

|
||||
|
||||
_Рисунок 2. Таблица истинности выхода `core_stall_o`_
|
||||
_Рисунок 2. Таблица истинности выхода `core_stall_o`._
|
||||
|
||||
---
|
||||
|
||||
@@ -215,9 +215,9 @@ module riscv_lsu(
|
||||
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 3. Структурная схема модуля `riscv_lsu`_
|
||||
_Рисунок 3. Структурная схема модуля `riscv_lsu`._
|
||||
|
||||
---
|
||||
|
||||
@@ -234,4 +234,3 @@ _Рисунок 3. Структурная схема модуля `riscv_lsu`_
|
||||
2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||||
3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_lsu`).
|
||||
4. Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста!
|
||||
|
||||
|
@@ -1,8 +1,10 @@
|
||||
# Лабораторная работа 9 "Интеграция блока загрузки и сохранения"
|
||||
|
||||
После реализации блока загрузки и сохранения, его необходимо интегрировать в процессорную систему. Ниже представлена схема, иллюстрирующая интеграцию компонентов:
|
||||
После реализации блока загрузки и сохранения, его необходимо интегрировать в процессорную систему. На _рис. 1_ представлена схема, иллюстрирующая интеграцию компонентов:
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 1. Подключение LSU в процессорную систему._
|
||||
|
||||
## Задание
|
||||
|
||||
|
@@ -96,7 +96,7 @@ _Таблица 1. Регистры контроля и состояния ма
|
||||
|1110011 | 110 | I | csrrsi rd, csr, rs1 | Чтение и Установка бит CSR| rd = csr, csr = csr \| imm |
|
||||
|1110011 | 111 | I | csrrci rd, csr, rs1 | Чтение и Очистка бит CSR | rd = csr, csr = csr & ~imm |
|
||||
|
||||
_Таблица 2. Список инструкций для работы с регистрами контроля и статуса_
|
||||
_Таблица 2. Список инструкций для работы с регистрами контроля и статуса._
|
||||
|
||||
Для удобства программирования на языке ассемблера RISC-V существуют псевдоинструкции для работы с CS-регистрами.
|
||||
|
||||
@@ -105,7 +105,7 @@ _Таблица 2. Список инструкций для работы с ре
|
||||
| csrr rd, csr | csrrs rd, csr, x0 | Чтение CSR | rd = csr |
|
||||
| csrw csr, rs1 | csrrw x0, csr, rs1 | Запись CSR | csr = rs1 |
|
||||
|
||||
_Таблица 3. Псевдоинструкции для работы с регистрами контроля и статуса_
|
||||
_Таблица 3. Псевдоинструкции для работы с регистрами контроля и статуса._
|
||||
|
||||
Операция логического ИЛИ нулевого регистра с содержимым CS-регистра не меняет его содержимого, поэтому при использовании инструкции `csrr` происходит только операция чтения. Подобным образом реализована псевдоинструкция `csrw`.
|
||||
|
||||
@@ -120,7 +120,7 @@ _Таблица 3. Псевдоинструкции для работы с ре
|
||||
|0x341 | MRW | mepc | Регистр, хранящий адрес перехваченной инструкции. |
|
||||
|0x342 | MRW | mcause | Причина перехвата |
|
||||
|
||||
_Таблица 4. Список регистров, подлежащих реализации в рамках лабораторной работы_
|
||||
_Таблица 4. Список регистров, подлежащих реализации в рамках лабораторной работы._
|
||||
|
||||
По адресу `0x304` должен располагаться регистр, позволяющий маскировать прерывания. Например, если на 5-ом входе системы прерывания генерируется прерывание, то процессор отреагирует на него только в том случае, если 5-ый бит регистра `mie` будет равен 1.
|
||||
|
||||
@@ -143,7 +143,7 @@ _Таблица 4. Список регистров, подлежащих реа
|
||||
|
||||

|
||||
|
||||
_Таблица 5. Кодирование причины перехвата в регистре `mcause`_
|
||||
_Таблица 5. Кодирование причины перехвата в регистре `mcause`._
|
||||
|
||||
Нас интересуют части, выделенные красным. В первую очередь то, как кодируется старший бит регистра `mcause`. Он зависит от типа причины перехвата (`1` в случае прерывания, `0` в случае исключения). Оставшиеся 31 бит регистра отводятся под коды различных причин. Поскольку мы создаем учебный процессор, который не будет использован в реальной жизни, он не будет поддерживать большую часть прерываний/исключений (таких как невыровненный доступ к памяти, таймеры и т.п.). В рамках данного курса мы должны поддерживать исключение по нелегальной инструкции (код 0x02) и должны уметь поддерживать прерывания периферийных устройств (под которые зарезервированы коды начиная с 16-го). В рамках данной лабораторной работы процессор будет поддерживать только один источник прерывания, поэтому для кодирования причины прерывания нам потребуется только первый код из диапазона _"Designated for platform use"_.
|
||||
|
||||
@@ -187,7 +187,7 @@ _Таблица 5. Кодирование причины перехвата в
|
||||
|
||||
Контроллер прерываний позволит обрабатывать входящие запросы на прерывания: маски́ровать их, выбирать один запрос из нескольких, а также игнорировать запросы во время обработки текущего прерывания.
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 3. Место разрабатываемых блоков в структуре процессора._
|
||||
|
||||
@@ -197,9 +197,9 @@ _Рисунок 3. Место разрабатываемых блоков в с
|
||||
|
||||
Рассмотрим один из возможных вариантов организации блока **Control and Status Registers**. Основная работа по описанию схемы блока состоит в описании мультиплексора и демультиплексора. Мультиплексор подает на выход **read_data_o** значение регистра, который соответствует пришедшему адресу. В свою же очередь, демультиплексор маршрутизирует сигнал разрешения на запись **write_enable_i** (en) на тот же регистр.
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 4. Структурная схема контроллера CS-регистров_
|
||||
_Рисунок 4. Структурная схема контроллера CS-регистров._
|
||||
|
||||
3-битный вход **opcode_i** определяет операцию, которая будет производиться над содержимым CSR по адресу **addr_i**.
|
||||
|
||||
@@ -211,9 +211,9 @@ _Рисунок 4. Структурная схема контроллера CS-
|
||||
|
||||
Рассмотрим один из возможных способов реализации простейшего контроллера прерываний, представленного на _рис. 5_.
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 5. Структурная схема контроллера прерываний_
|
||||
_Рисунок 5. Структурная схема контроллера прерываний._
|
||||
|
||||
Контроллер состоит из логики:
|
||||
|
||||
|
@@ -1,13 +1,16 @@
|
||||
# Лабораторная работа 11 "Интеграция подсистемы прерываний"
|
||||
|
||||
После реализации подсистемы прерываний, её необходимо интегрировать в процессорную систему. Для этого необходимо обновить модуль `riscv_core` по приведенной ниже схеме:
|
||||
После реализации подсистемы прерываний, её необходимо интегрировать в процессорную систему. Для этого необходимо обновить модуль `riscv_core` по схеме, приведенной на _рис. 1_:
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 1. Интеграция подсистемы прерываний в ядро процессора._
|
||||
|
||||
<details>
|
||||
<summary>Схема без выделения новых частей относительно старой версии модуля</summary>
|
||||
|
||||

|
||||

|
||||
_Рисунок 1. Схема без выделения новых частей относительно старой версии модуля._
|
||||
|
||||
</details>
|
||||
|
||||
|
@@ -50,7 +50,7 @@
|
||||
|
||||
На рисунке ниже представлен способ подключения процессора к памяти инструкций и данных, а также 255 периферийным устройствам.
|
||||
|
||||

|
||||

|
||||
|
||||
_Рисунок 1. Итоговая структура процессорной системы._
|
||||
|
||||
|
Reference in New Issue
Block a user