mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 09:10:10 +00:00
Стилистические правки
This commit is contained in:
@@ -127,7 +127,7 @@ endmodule
|
||||
|
||||
_Листинг 1. SystemVerilog-код модуля half_adder._
|
||||
|
||||
По данному коду, САПР может реализовать следующую схему:
|
||||
По данному коду, САПР может реализовать схему, представленную на рисунке 3.
|
||||
|
||||

|
||||
|
||||
@@ -137,7 +137,7 @@ _Рисунок 3. Цифровая схема модуля half_adder, сген
|
||||
|
||||
Для этого необходимо провести моделирование этой схемы. Во время моделирования на входы подаются тестовые воздействия. Каждое изменение входных сигналов приводит к каскадному изменению состояний внутренних цепей, что в свою очередь приводит к изменению значений на выходных сигналах схемы.
|
||||
|
||||
Подаваемые на схему входные воздействия формируются верификационным окружением. Верификационное окружение (в дальнейшем будет использован термин "**тестбенч**") — это особый несинтезируемый модуль, который не имеет входных или выходных сигналов. Ему не нужны входные сигналы, поскольку он сам является генератором всех своих внутренних сигналов, и ему не нужны выходные сигналы, поскольку этот модуль ничего не вычисляет, только подаёт входные воздействия на проверяемый модуль.
|
||||
Подаваемые на схему входные воздействия формируются верификационным окружением. Верификационное окружение (в дальнейшем будет использован термин "**тестбенч**") — это особый несинтезируемый модуль, который не имеет входных или выходных сигналов. Эти сигналы ему не нужны, потому что он сам является генератором всех своих внутренних сигналов, и данный модуль не передаёт ничего вовне — только проверяет тестируемый модуль внутри себя.
|
||||
|
||||
Внутри тестбенча можно использовать конструкции из несинтезируемого подмножества языка SystemVerilog, в частности программный блок `initial`, в котором команды выполняются последовательно, что делает этот блок чем-то отдалённо похожим на проверяющую программу. Поскольку изменение внутренних цепей происходит с некоторой задержкой относительно изменений входных сигналов, при моделировании есть возможность делать паузы между командами. Это делается с помощью специального символа #, за которым указывается количество времени симуляции, которое нужно пропустить перед следующей командой.
|
||||
|
||||
@@ -158,11 +158,11 @@ module testbench(); // <- Не имеет ни входов, ни
|
||||
|
||||
initial begin
|
||||
a = 1'b0; b = 1'b0; // <- Подаём на входы модуля тестовые
|
||||
#10; // воздействия
|
||||
#10ns; // воздействия
|
||||
a = 1'b0; b = 1'b1;
|
||||
#10; // <- Делаем паузу в десять отсчётов
|
||||
a = 1'b1; b = 1'b0; // времени симуляции перед очередным
|
||||
#10; // изменением входных сигналов
|
||||
#10ns; // <- Делаем паузу в десять наносекунд
|
||||
a = 1'b1; b = 1'b0; // перед очередным изменением
|
||||
#10ns; // входных сигналов
|
||||
a = 1'b1; b = 1'b1;
|
||||
end
|
||||
endmodule
|
||||
@@ -178,7 +178,7 @@ _Рисунок 4. Временная диаграмма, моделирующа
|
||||
|
||||
### Полный 4-битный сумматор
|
||||
|
||||
До этого мы реализовали только сложение одного столбца в столбик, теперь мы хотим реализовать всю операцию сложения в столбик. Как это сделать? Сделать ровно то, что делается при сложении в столбик: сначала сложить младший столбец, получить бит переноса для следующего столбца, сложить следующий и т.д.
|
||||
До этого мы реализовали сложение в столбик только для одного разряда, теперь мы хотим реализовать всю операцию сложения в столбик. Как это сделать? Сделать ровно то, что делается при сложении в столбик: сначала сложить младший разряд, получить бит переноса для следующего разряда, сложить следующий и т.д.
|
||||
|
||||
Давайте посмотрим, как это будет выглядеть на схеме (для простоты, внутренняя логика 1-битного сумматора скрыта, но вы должны помнить, что каждый прямоугольник — это та же самая схема с рис. 2).
|
||||
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
Доп. задание, выполняемое дома:
|
||||
|
||||
6. Написать программу для процессора и на модели убедиться в корректности её выполнения ([Индивидуальное задание](Индивидуальное%20задание)).
|
||||
6. Написать программу для процессора и убедиться на моделировании в корректности её выполнения ([Индивидуальное задание](Индивидуальное%20задание)).
|
||||
|
||||
## Теория про программируемое устройство
|
||||
|
||||
@@ -252,7 +252,9 @@ _Таблица 5. Кодирование безусловного перехо
|
||||
Для реализации безусловного перехода, нам необходимо добавить дополнительную логику управления мультиплексором перед сумматором. Итоговая логика его работы звучит так:
|
||||
|
||||
1. если сейчас инструкция безусловного перехода, _или_
|
||||
2. если сейчас инструкция условного перехода _и_ условие перехода выполнилось
|
||||
2. если сейчас инструкция условного перехода _и_ условие перехода выполнилось,
|
||||
|
||||
то к `PC` прибавляется знакорасширенная константа, умноженная на 4. В противном случае, к `PC` прибавляется 4.
|
||||
|
||||
Кроме того, при безусловном переходе в регистровый файл также ничего не пишется. А значит, необходимо обновить логику работы сигнала разрешения записи `WE`, который будет равен 0 если сейчас инструкция условного или безусловного перехода.
|
||||
|
||||
@@ -270,7 +272,7 @@ _Рисунок 5. Реализация безусловного переход
|
||||
2. Инструкция загрузки константы `0 0 00 const WA`
|
||||
3. Инструкция загрузки из внешних устройств `0 0 10 xxx xxxx xxxx xxxx xxxx xxxx WA`
|
||||
4. Безусловный переход `1 x xx xxx xxxx xxxx xxxx const xxxxx`
|
||||
5. 6 инструкций условного перехода `0 1 xx alu_op RA1 RA2 const x xxxx`
|
||||
5. 6 инструкций условного перехода `0 1 xx alu_op RA1 RA2 const xxxxx`
|
||||
|
||||
При кодировании инструкций используются следующие поля:
|
||||
|
||||
|
@@ -258,11 +258,11 @@ SYSTEM-инструкции используются для доступа к с
|
||||
|
||||
Перечисленные выше инструкции являются "дополнительными" — их добавили сверх стандартного набора инструкций, чтобы обеспечить требуемый нашей системе функционал. Однако осталось ещё две SYSTEM-инструкции, которые мы должны уметь декодировать, поскольку они есть в стандартном наборе инструкций.
|
||||
|
||||
Инструкции `ECALL` и `EBREAK` вызывают исключение. Подробнее исключения и прерывания будут разобраны в ЛР№10.
|
||||
Инструкции `ECALL` и `EBREAK` вызывают исключение. Подробнее исключения и прерывания будут разобраны в ЛР№10, пока что надо знать лишь то, что в нашей процессорной системе все исключения будут реализованы через выставление 1 на сигнале `illegal_instr_o`.
|
||||
|
||||
#### MISC-MEM инструкции
|
||||
|
||||
В базовом наборе инструкций **RISC-V** к `MISC-MEM`-операциям относятся инструкции `FENCE`, `FENCE.TSO`, `PAUSE` (которые объединены в таблице 5 в одну инструкцию `FENCE`). В реализуемом процессорном ядре эта инструкция не должна приводить к изменениям. Инструкция `FENCE` в **RISC-V** необходима при работе с несколькими аппаратными потоками, или "хартами" (hart – «hardware thread»). Она помогает согласовать доступ к данным между ними. В **RISC-V** используется "расслабленная модель" памяти (**relaxed memory model**): которая позволяет потокам видеть операции других потоков, но не обязательно в том порядке, в каком они были записаны в коде программы. Инструкция `FENCE`, использованная между двумя инструкциями чтения и/или записи гарантирует, что остальные потоки увидят первую инструкцию перед второй. Реализация `FENCE` является опциональной в **RISC-V** и в данном случае в ней нет необходимости, так как в системе не предполагается наличия нескольких аппаратных потоков. Данная инструкция должна быть реализована как `NOP` (**n**o **op**eration).
|
||||
В базовом наборе инструкций **RISC-V** к `MISC-MEM`-операциям относятся инструкции `FENCE`, `FENCE.TSO`, `PAUSE` (которые объединены в таблице 5 в одну инструкцию `FENCE`). В реализуемом процессорном ядре эта инструкция не должна приводить к изменениям. Инструкция `FENCE` в **RISC-V** необходима при работе с несколькими аппаратными потоками, или "хартами" (hart – «**har**dware **t**hread»). Она помогает согласовать доступ к данным между ними. В **RISC-V** используется "расслабленная модель" памяти (**relaxed memory model**): которая позволяет потокам видеть операции других потоков, но не обязательно в том порядке, в каком они были записаны в коде программы. Инструкция `FENCE`, использованная между двумя инструкциями чтения и/или записи гарантирует, что остальные потоки увидят первую инструкцию перед второй. Реализация `FENCE` является опциональной в **RISC-V** и в данном случае в ней нет необходимости, так как в системе не предполагается наличия нескольких аппаратных потоков. Данная инструкция должна быть реализована как `NOP` (**n**o **op**eration).
|
||||
|
||||
В _таблице 6_ представлены инструкции из таблицы 3 с приведением их типов, значениями полей `opcode`, `func3`, `func7`, функциональным описанием и примерами использования.
|
||||
|
||||
@@ -286,6 +286,8 @@ _Таблица 6. Расширенное описание инструкций
|
||||
- `b_sel_o = 3'd1`,
|
||||
- `alu_op_o= ALU_ADD`.
|
||||
|
||||
(см. _рисунок 1_).
|
||||
|
||||
Кроме того, для самой операции записи в основную память, декодер должен сформировать управляющие сигналы интерфейса памяти (запрос на обращение в память, размер передаваемых данных и сигнал разрешения записи):
|
||||
|
||||
- `mem_req_o = 1'b1`,
|
||||
@@ -338,13 +340,13 @@ _Таблица 7. Описание портов дешифратора кома
|
||||
|
||||
**SystemVerilog** – это язык описания аппаратуры. С помощью этого языка человек объясняет либо синтезатору какое он хочет получить устройство, либо симулятору – как он хочет это устройство проверить. Синтезатор – это программа, которая создает из логических элементов цифровое устройство по описанию, предоставляемому человеком. Синтезатору внутри **Vivado** нужно объяснить, что от него нужно. Например, чтобы спросить дорогу у испанца, придется делать это на испанском языке, иначе он ничем не сможет помочь. А если вы хорошо знаете испанский, то скорее всего сможете это сделать еще и разными способами. В **SystemVerilog** точно также – одно и то же устройство можно описать разным кодом, но результат синтеза будет одним и тем же. Однако, часто два разных кода, одинаковые по смыслу, могут синтезироваться в разную аппаратуру, хотя функционально они будут идентичны, но могут отличаться, например, скоростью работы. Или одни и те же специальные языковые конструкции могут применяться для синтезирования разных цифровых элементов.
|
||||
|
||||
Декодер – комбинационная схема. Это значит, что каждый раз подавая на вход одни и те же значения, вы будете получать на выходе один и тот же результат, потому что комбинационные схемы не содержат элементов памяти.
|
||||
Декодер – комбинационная схема. Это значит, что каждый раз подавая на вход одни и те же значения, вы будете получать на выходе один и тот же результат.
|
||||
|
||||
Можно по-разному описывать комбинационные схемы. Например — через конструкцию `assign`. Для описания декодера отлично подойдет конструкция `case`, которая превратится не в мультиплексор, а в комбинационную схему с оптимальными параметрами критического пути. В доверилоговую эпоху разработчикам пришлось бы строить гигантские таблицы истинности и [карты Карно](https://ru.wikipedia.org/wiki/Карта_Карно), искать оптимальные схемы реализации. Сегодня эту задачу решает синтезатор, по описанию устройства он сам находит наиболее эффективное решение.
|
||||
Можно по-разному описывать комбинационные схемы. Например — через оператор непрерывного присваивания `assign`. Для описания декодера отлично подойдет конструкция `case`, которая превратится не в мультиплексор, а в комбинационную схему с оптимальными параметрами критического пути. В доверилоговую эпоху разработчикам пришлось бы строить гигантские таблицы истинности и [карты Карно](https://ru.wikipedia.org/wiki/Карта_Карно), искать оптимальные схемы реализации. Сегодня эту задачу решает синтезатор, по описанию устройства он сам находит наиболее эффективное решение.
|
||||
|
||||
Разница с реализацией мультиплексора в том, что в этом случае справа от знака равно всегда стоит константа. Получается это такой способ описать таблицу истинности. В такой код легко вносить правки и искать интересующие фрагменты.
|
||||
|
||||
Рассмотрим _листинг 1_. Внутри конструкции `always_comb`, перед конструкцией `case` указываются значения по умолчанию. Благодаря этому пропадает необходимость указывать все сигналы внутри каждого обработчика `case`, достаточно указать только те, что имеют значение отличное от значения по умолчанию. Представленный пример реализует комбинационную схему, которая при `control_signal== 4'b1100` будет выставлять сигнал `c == 1'b0`, то есть отличное, от значения по умолчанию. Сигнал `a` никак не меняется, поэтому он не указан в соответствующем обработчике. Если `sub_signal == 1'b0`, то `b` будет равен 1, а `d` равен 0. Если `sub_signal == 1'b1`, то наоборот – `b` будет равен 0, а `d` равен 1.
|
||||
Рассмотрим _листинг 1_. Внутри конструкции `always_comb`, перед конструкцией `case` указываются значения по умолчанию. Благодаря этому пропадает необходимость указывать все сигналы внутри каждого обработчика `case`, достаточно указать только те, что имеют значение отличное от значения по умолчанию. Представленный пример реализует комбинационную схему, которая при `control_signal== 4'b1100` будет выставлять сигнал `c = 1'b0`, то есть отличное, от значения по умолчанию. Сигнал `a` никак не меняется, поэтому он не указан в соответствующем обработчике. Если `sub_signal == 1'b0`, то `b` будет равен 1, а `d` равен 0. Если `sub_signal == 1'b1`, то наоборот – `b` будет равен 0, а `d` равен 1.
|
||||
|
||||
```Verilog
|
||||
module example (
|
||||
@@ -382,7 +384,7 @@ endmodule
|
||||
|
||||
_Листинг 1. Пример описания декодера._
|
||||
|
||||
Имейте в виду, что значения по умолчанию, описанные в начале блока `always_comb` можно использовать таким образом при помощи **блокирующих присваиваний** (которые [следует](../../Basic%20Verilog%20structures/Assignments.md) использовать только в комбинационных блоках).
|
||||
Имейте в виду, что значения по умолчанию, описанные в начале блока `always_comb`, можно использовать таким образом только при помощи **блокирующих присваиваний** (которые [следует](../../Basic%20Verilog%20structures/Assignments.md) использовать только в комбинационных блоках).
|
||||
|
||||
Кроме того, использование вложенных блоков `case` обосновано только в ситуации создания блока декодера (т.е. в случаях, когда справа от всех присваиваний будут использованы константы, а не другие сигналы). В случае описания мультиплексора, вложенные блоки `case` могут быть синтезированы в каскад мультиплексоров, что негативно скажется на временных характеристиках схемы.
|
||||
|
||||
|
Reference in New Issue
Block a user