mirror of
https://github.com/MPSU/APS.git
synced 2026-06-13 12:33:33 +00:00
English version draft
Assisted-by: Claude:claude-4.6-sonnet
This commit is contained in:
@@ -1,172 +1,172 @@
|
||||
# Лабораторная работа №4 "Простейшее программируемое устройство"
|
||||
# Lab 4. Primitive Programmable Device
|
||||
|
||||
В этой лабораторной работе, на основе ранее разработанных блоков памяти и АЛУ, вы соберете простой учебный процессор с архитектурой `CYBERcobra 3000 Pro 2.1`. Это нужно для более глубокого понимания принципов работы программно-управляемых устройств, чтобы проще было понять архитектуру RISC-V в будущем.
|
||||
In this lab, using the previously developed memory blocks and ALU, you will build a simple educational processor with the `CYBERcobra 3000 Pro 2.1` architecture. This is needed for a deeper understanding of the principles of how program-controlled devices work, so that understanding the RISC-V architecture in the future will be easier.
|
||||
|
||||
## Материалы для подготовки к лабораторной работе
|
||||
## Preparation Materials
|
||||
|
||||
В дополнение к [материалам](../../Basic%20Verilog%20structures/), изученным в ходе предыдущих работ, вам рекомендуется ознакомиться с:
|
||||
In addition to the [materials](../../Basic%20Verilog%20structures/) studied in previous labs, you are recommended to review:
|
||||
|
||||
- Оператором конкатенации ([Concatenation.md](../../Basic%20Verilog%20structures/Concatenation.md)).
|
||||
- The concatenation operator ([Concatenation.md](../../Basic%20Verilog%20structures/Concatenation.md)).
|
||||
|
||||
## Цель
|
||||
## Goal
|
||||
|
||||
Реализовать простейшее программируемое устройство.
|
||||
Implement a primitive programmable device.
|
||||
|
||||
## Ход работы
|
||||
## Workflow
|
||||
|
||||
1. Изучить принцип работы процессоров (соответствующий раздел [#теории](#Теория-про-программируемое-устройство))
|
||||
2. Познакомиться с архитектурой и микроархитектурой `CYBERcobra 3000 Pro 2.1` (раздел про эту [#архитектуру](#Архитектура-cybercobra-3000-pro-21-и-её-микроархитектура))
|
||||
3. Изучить необходимые для описания процессора конструкции SystemVerilog (раздел [#инструменты](#Инструменты-для-реализации-процессора))
|
||||
4. Реализовать процессор с архитектурой `CYBERcobra 3000 Pro 2.1` ([#задание по разработке аппаратуры](#Задание-по-реализации-процессора))
|
||||
5. Проверить работу процессора в ПЛИС.
|
||||
1. Study the operating principles of processors (see the corresponding [#theory](#Theory-on-programmable-devices) section)
|
||||
2. Learn about the architecture and microarchitecture of `CYBERcobra 3000 Pro 2.1` (see the [#architecture](#CYBERcobra-3000-Pro-21-Architecture-and-Microarchitecture) section)
|
||||
3. Study the SystemVerilog constructs required to describe the processor (see the [#tools](#Tools-for-Processor-Implementation) section)
|
||||
4. Implement the processor with the `CYBERcobra 3000 Pro 2.1` architecture ([#hardware design task](#Processor-Implementation-Task))
|
||||
5. Verify the processor operation on the FPGA.
|
||||
|
||||
Доп. задание, выполняемое дома:
|
||||
Additional task (to be completed at home):
|
||||
|
||||
6. Написать программу для процессора и убедиться на моделировании в корректности её выполнения ([Индивидуальное задание](Индивидуальное%20задание)).
|
||||
6. Write a program for the processor and verify its correct execution in simulation ([Individual Assignment](Индивидуальное%20задание)).
|
||||
|
||||
## Теория про программируемое устройство
|
||||
## Theory on Programmable Devices
|
||||
|
||||
В обобщенном виде, процессор включает в себя память, АЛУ, устройство управления и интерфейсную логику для организации ввода/вывода. Также, в процессоре есть специальный регистр `PC` (**Program Counter** – счётчик команд), который хранит в себе число – адрес ячейки памяти, где хранится инструкция, которую нужно выполнить. Инструкция тоже представляет собой число, в котором закодировано `что нужно сделать` и `с чем это нужно сделать`.
|
||||
In general terms, a processor includes memory, an ALU, a control unit, and interface logic for organizing input/output. A processor also has a special register `PC` (**Program Counter**), which holds a number — the address of the memory cell containing the instruction to be executed. An instruction is also a number that encodes `what needs to be done` and `what it needs to be done with`.
|
||||
|
||||
Алгоритм работы процессора следующий:
|
||||
The processor operates according to the following algorithm:
|
||||
|
||||
1. из памяти считывается инструкция по адресу `PC`;
|
||||
2. устройство управления декодирует полученную инструкцию (то есть определяет какую операцию нужно сделать, где взять операнды и куда разместить результат);
|
||||
3. декодировав инструкцию, устройство управления выдает всем блокам процессора (АЛУ, регистровый файл, мультиплексоры) соответствующие управляющие сигналы, тем самым выполняя эту инструкцию;
|
||||
4. изменяется значение `PC`;
|
||||
5. цикл повторяется с `п.1`.
|
||||
1. an instruction is fetched from memory at address `PC`;
|
||||
2. the control unit decodes the received instruction (i.e., determines what operation needs to be performed, where to get the operands, and where to place the result);
|
||||
3. having decoded the instruction, the control unit issues corresponding control signals to all processor blocks (ALU, register file, multiplexers), thereby executing the instruction;
|
||||
4. the value of `PC` is updated;
|
||||
5. the cycle repeats from step 1.
|
||||
|
||||
Любая инструкция приводит к изменению состояния памяти. В случае процессора, рассматриваемого в данной лабораторной работе, есть два класса инструкций: одни изменяют содержимое регистрового файла — это инструкции записи. Другие изменяют значение `PC` — это инструкции перехода. В первом случае используются вычислительные инструкции и инструкции загрузки данных из других источников. Во втором случае используются инструкции перехода.
|
||||
Every instruction leads to a change in the memory state. In the case of the processor considered in this lab, there are two classes of instructions: those that modify the register file — these are write instructions. Others change the value of `PC` — these are branch instructions (conditional and unconditional). The first class includes computational instructions and instructions for loading data from other sources. The second class includes branch instructions.
|
||||
|
||||
Если процессор обрабатывает вычислительную инструкцию, то `PC` перейдет к следующей по порядку инструкции. В ЛР№3 мы реализовали память инструкций с [побайтовой адресацией](../03.%20Register%20file%20and%20memory/#1-Память-инструкций). Это означает, что каждый байт памяти имеет свой собственный адрес. Поскольку длина инструкции составляет `4 байта`, для перехода к следующей инструкции `PC` должен быть увеличен на `4` (`PC = PC + 4`). При этом, регистровый файл сохранит результат некоторой операции на АЛУ или данные с порта входных данных.
|
||||
If the processor is executing a computational instruction, `PC` advances to the next instruction in sequence. In Lab 3, we implemented an instruction memory with [byte addressing](../03.%20Register%20file%20and%20memory/#1-Память-инструкций). This means each byte of memory has its own address. Since an instruction is `4 bytes` long, `PC` must be incremented by `4` to advance to the next instruction (`PC = PC + 4`). In this case, the register file saves the result of some ALU operation or data from the input data port.
|
||||
|
||||
Если же обрабатывается инструкция перехода, то возможно два варианта. В случае безусловного или успешного условного перехода, значение `PC` увеличится на значение константы, закодированной внутри инструкции `PC = PC + const*4` (иными словами, `const` говорит о том, через сколько инструкций перепрыгнет `PC`, `const` может быть и отрицательной). В случае же неуспешного условного перехода `PC`, как и после вычислительных команд, просто перейдет к следующей инструкции, то есть `PC = PC + 4`.
|
||||
If a branch instruction is being executed, there are two possible outcomes. In the case of an unconditional or successful conditional branch, `PC` is incremented by the value of the constant encoded within the instruction: `PC = PC + const*4` (in other words, `const` specifies how many instructions `PC` will jump over; `const` can also be negative). In the case of an unsuccessful conditional branch, `PC`, as with computational instructions, simply advances to the next instruction: `PC = PC + 4`.
|
||||
|
||||
> Строго говоря `PC` меняется при выполнении любой инструкции (кроме случая `const = 0`, то есть перехода инструкции на саму себя `PC = PC + 0*4`). Разница в том, на какое значение `PC` изменится. В вычислительных инструкциях это всегда адрес следующей инструкции, программа не управляет `PC`, он "сам знает", что ему делать. В инструкциях перехода программа и контекст определяют, что произойдет с `PC`.
|
||||
> Strictly speaking, `PC` changes on every instruction (except when `const = 0`, meaning a self-loop `PC = PC + 0*4`). The difference lies in what value `PC` changes to. For computational instructions, it is always the address of the next instruction — the program does not control `PC`, it "knows on its own" what to do. For branch instructions, the program and context determine what happens to `PC`.
|
||||
|
||||
## Архитектура CYBERcobra 3000 Pro 2.1 и её микроархитектура
|
||||
## CYBERcobra 3000 Pro 2.1 Architecture and Microarchitecture
|
||||
|
||||

|
||||
|
||||
В качестве первого разрабатываемого программируемого устройства предлагается использовать архитектуру специального назначения `CYBERcobra 3000 Pro 2.1` (далее "CYBERcobra"), которая была разработана в **МИЭТ**. Главным достоинством данной архитектуры является простота её понимания и реализации. Главным её минусом является неоптимальность ввиду неэффективной реализации кодирования инструкций, что приводит к наличию неиспользуемых битов в программах. Но это неважно, так как основная цель разработки процессора с архитектурой `CYBERcobra` — это более глубокое понимание принципов работы программируемых устройств, которое поможет при разработке более сложного процессора с архитектурой **RISC-V**.
|
||||
As the first programmable device to be developed, the special-purpose architecture `CYBERcobra 3000 Pro 2.1` (hereinafter "CYBERcobra"), developed at **MIET**, is proposed. The main advantage of this architecture is the simplicity of understanding and implementing it. Its main drawback is inefficiency due to a suboptimal instruction encoding scheme, which results in unused bits in programs. However, this is not important, since the primary goal of developing a processor with the `CYBERcobra` architecture is to gain a deeper understanding of the principles of programmable devices, which will help when developing a more complex processor with the **RISC-V** architecture.
|
||||
|
||||
Простота архитектуры `CYBERcobra` проявляется, в том числе, за счёт отсутствия памяти данных. Это значит, что данные c которыми работает программа могут храниться только в регистровом файле. Также в таком процессоре почти полностью отсутствует устройство управления (формально оно существует, но состоит только из проводов и пары логических вентилей).
|
||||
The simplicity of the `CYBERcobra` architecture is partly due to the absence of a data memory. This means that data the program works with can only be stored in the register file. The control unit is also nearly absent in such a processor (formally it exists, but consists only of wires and a couple of logic gates).
|
||||
|
||||
Архитектурой предусмотрена поддержка 19 инструкций (5 типов команд):
|
||||
The architecture supports 19 instructions (5 instruction types):
|
||||
|
||||
Первые два типа содержат 16 инструкций, которые выполняются на АЛУ:
|
||||
The first two types contain 16 instructions executed on the ALU:
|
||||
|
||||
- 10 вычислительных
|
||||
- 6 операций сравнения для условного перехода
|
||||
- 10 computational
|
||||
- 6 comparison operations for conditional branching
|
||||
|
||||
Кроме того, есть инструкции:
|
||||
In addition, there are instructions for:
|
||||
|
||||
- безусловного перехода
|
||||
- загрузки константы
|
||||
- загрузки данных с внешнего устройства.
|
||||
- unconditional branch
|
||||
- loading a constant
|
||||
- loading data from an external device.
|
||||
|
||||
К классу инструкций записи, то есть тех, которые меняют значение регистрового файла, можно отнести: 10 вычислительных, загрузки константы и загрузки данных с внешнего устройства. К классу инструкций перехода: 6 операций сравнения для условного перехода и безусловный переход.
|
||||
The write instruction class (those that modify the register file) includes: 10 computational instructions, load constant, and load data from external device. The branch instruction class includes: 6 comparison operations for conditional branching and unconditional branch.
|
||||
|
||||
### Последовательное считывание инструкций
|
||||
### Sequential Instruction Fetch
|
||||
|
||||
Будем рассматривать архитектуру (функциональные возможности процессора) и микроархитектуру (реализацию процессора) одновременно, прослеживая рассуждения их разработчика.
|
||||
We will consider the architecture (the functional capabilities of the processor) and the microarchitecture (the implementation of the processor) simultaneously, following the reasoning of their designer.
|
||||
|
||||
Для начала реализуем базовый функционал, подключив счётчик команд `PC` к памяти инструкций `instr_mem` и сумматору, прибавляющему 4 к `PC`. Выход сумматора подключим ко входу `PC`.
|
||||
First, let us implement the basic functionality by connecting the program counter `PC` to the instruction memory `instr_mem` and to an adder that adds 4 to `PC`. The output of the adder is connected to the input of `PC`.
|
||||
|
||||
Каждый раз, когда будет происходить тактовый импульс (переключение `clk_i` из 0 в 1), значение `PC` будет увеличиваться на `4`, тем самым указывая на следующую инструкцию. Последовательное считывание программы из памяти готово.
|
||||
Each time a clock edge occurs (transition of `clk_i` from 0 to 1), the value of `PC` increments by `4`, thereby pointing to the next instruction. Sequential program fetch from memory is now complete.
|
||||
|
||||
Так как операции будут выполняться только над данными в регистровом файле, то его можно сразу подключить к АЛУ, соединив порты чтения `read_data1_o` и `read_data2_o` со входами операндов АЛУ, а результат операции АЛУ подключив к порту на запись `write_data_i`. Полученный результат изображен на _рис. 0_.
|
||||
Since operations will only be performed on data in the register file, it can be immediately connected to the ALU by wiring the read ports `read_data1_o` and `read_data2_o` to the ALU operand inputs, and connecting the ALU operation result to the write port `write_data_i`. The resulting schematic is shown in _Fig. 0_.
|
||||
|
||||
> Для того чтобы номера таблиц и рисунков лучше соотносились друг с другом и сопутствующим текстом, первая схема разрабатываемой микроархитектуры будет обозначена как _Рисунок 0_. Все последующие схемы будут совпадать по нумерации с таблицами, обозначающими способ кодирования реализуемого типа инструкций.
|
||||
> To make figure and table numbering correspond better to each other and to the accompanying text, the first schematic of the microarchitecture under development is labeled _Figure 0_. All subsequent schematics will share numbering with the tables that describe the encoding of the corresponding instruction type.
|
||||
|
||||

|
||||
|
||||
_Рисунок 0. Размещение на схеме основных блоков._
|
||||
_Figure 0. Placement of the main blocks on the schematic._
|
||||
|
||||
Для компактности схемы названия портов регистрового файла сокращены (`RA1` обозначает `read_addr1_i` и т.п.).
|
||||
For compactness, register file port names are abbreviated (`RA1` stands for `read_addr1_i`, etc.).
|
||||
|
||||
### Кодирование вычислительных инструкций
|
||||
### Computational Instruction Encoding
|
||||
|
||||
Чтобы добавить поддержку каких-либо инструкций, необходимо договориться **как** они будут кодироваться (эта часть относится к вопросам архитектуры). Вычислительные инструкции требуют следующую информацию:
|
||||
To add support for any instructions, it is necessary to agree on **how** they will be encoded (this part relates to architecture). Computational instructions require the following information:
|
||||
|
||||
1. по каким адресам регистрового файла лежат операнды?
|
||||
2. по какому адресу будет сохранен результат?
|
||||
3. какая операция должна быть выполнена?
|
||||
1. at which register file addresses are the operands located?
|
||||
2. at which address will the result be saved?
|
||||
3. what operation needs to be performed?
|
||||
|
||||
Для этого в инструкции были выбраны следующие поля: 5 бит (`[27:23]`) для кодирования операции на АЛУ, два раза по 5 бит для кодирования адресов операндов в регистровом файле (`[22:18]` и `[17:13]`) и 5 бит для кодирования адреса результата (`[4:0]`). _Таблица 1_ демонстрирует деление 32-битной инструкции на поля `alu_op`, `RA1`, `RA2` и `WA`.
|
||||
For this purpose, the following fields are selected in the instruction: 5 bits (`[27:23]`) for encoding the ALU operation, two groups of 5 bits for encoding operand addresses in the register file (`[22:18]` and `[17:13]`), and 5 bits for encoding the result address (`[4:0]`). _Table 1_ shows the division of the 32-bit instruction into the fields `alu_op`, `RA1`, `RA2`, and `WA`.
|
||||
|
||||

|
||||
|
||||
_Таблица 1. Кодирование вычислительных инструкций в архитектуре CYBERcobra._
|
||||
_Table 1. Computational instruction encoding in the CYBERcobra architecture._
|
||||
|
||||
``` C
|
||||
reg_file[WA] ← reg_file[RA1] {alu_op} reg_file[RA2]
|
||||
```
|
||||
|
||||
Запись выше является некоторой формализацией выполняемой функции, которая как бы отвечает на вопрос "а что, собственно, будет сделано?". В регистр по адресу WA (`reg_file[WA]`) будет записан (`←`) результат операции alu_op (`{alu_op}`) между регистрами по адресам RA1 (`reg_file[RA1]`) и RA2 (`reg_file[RA1]`).
|
||||
The expression above is a formalization of the function being performed, answering the question "what exactly will be done?". The result of the operation alu_op (`{alu_op}`) between the registers at addresses RA1 (`reg_file[RA1]`) and RA2 (`reg_file[RA2]`) will be written (`←`) into the register at address WA (`reg_file[WA]`).
|
||||
|
||||
### Реализация вычислительных инструкций
|
||||
### Implementing Computational Instructions
|
||||
|
||||
Чтобы процессор правильно реагировал на эти инструкции, требуется подключить ко входам адреса регистрового файла и управляющему входу АЛУ соответствующие биты выхода `read_data_o` памяти инструкции (**Instruction Memory**). Допустим, программный счётчик указывает на ячейку памяти, в которой хранится следующая 32-битная инструкция:
|
||||
For the processor to respond correctly to these instructions, the corresponding bits of the instruction memory (`Instruction Memory`) `read_data_o` output must be connected to the register file address inputs and the ALU control input. Suppose the program counter points to a memory cell containing the following 32-bit instruction:
|
||||
|
||||
```text
|
||||
0000|00111 |00100|01000|00000000|11100
|
||||
|alu_op| RA1 | RA2 | | WA
|
||||
```
|
||||
|
||||
В этом случае, будет выполнена операция:
|
||||
In this case, the following operation will be performed:
|
||||
|
||||
```text
|
||||
reg_file[28] = reg_file[4] | reg_file[8]
|
||||
reg_file[28] = reg_file[4] | reg_file[8]
|
||||
```
|
||||
|
||||
Здесь:
|
||||
Here:
|
||||
|
||||
- `alu_op = 00111`, что соответствует операции **логического ИЛИ** (см ЛР№2);
|
||||
- `WA = 11100`, то есть запись произойдёт в 28-ой регистр;
|
||||
- `RA1 = 00100` и `RA2 = 01000` — это значит что данные для АЛУ будут браться из 4-го и 8-го регистров соответственно.
|
||||
- `alu_op = 00111`, which corresponds to the **bitwise OR** operation (see Lab 2);
|
||||
- `WA = 11100`, meaning the result will be written to register 28;
|
||||
- `RA1 = 00100` and `RA2 = 01000` — this means the ALU operands will be taken from registers 4 and 8, respectively.
|
||||
|
||||
_Рис. 1_ иллюстрирует фрагмент микроархитектуры, поддерживающий вычислительные операции на АЛУ. Поскольку другие инструкции пока что не поддерживаются, то вход `WE` регистрового файла просто равен `1` (это временно).
|
||||
_Fig. 1_ illustrates the microarchitecture fragment supporting ALU computational operations. Since other instructions are not yet supported, the `WE` input of the register file is simply set to `1` (this is temporary).
|
||||
|
||||

|
||||
|
||||
_Рисунок 1. Подключение АЛУ и регистрового файла для реализации вычислительных инструкций._
|
||||
_Figure 1. Connecting the ALU and register file to implement computational instructions._
|
||||
|
||||
### Реализация загрузки константы в регистровый файл
|
||||
### Implementing Constant Load into the Register File
|
||||
|
||||
Обрабатываемая информация как-то должна попадать в регистровый файл, для этого добавим инструкцию загрузки константы по адресу `WA`. Чтобы аппаратура могла различать, когда ей нужно выполнять операцию на АЛУ, а когда загружать константу, назначим один бит инструкции определяющим "что именно будет записано в регистровый файл": результат с АЛУ или константа из инструкции. За это будет отвечать 28-ой бит инструкции `WS` (**Write Source**). Если `WS == 1`, значит выполняется вычислительная инструкция, а если `WS == 0`, значит нужно загрузить константу в регистровый файл.
|
||||
The data being processed must somehow enter the register file, so let us add an instruction to load a constant at address `WA`. For the hardware to distinguish between executing an ALU operation and loading a constant, one bit of the instruction is designated to indicate "what exactly will be written to the register file": the result from the ALU or a constant from the instruction. Bit 28 of the instruction, `WS` (**Write Source**), handles this. If `WS == 1`, a computational instruction is being executed; if `WS == 0`, a constant must be loaded into the register file.
|
||||
|
||||
Сама константа имеет разрядность **23 бита** ([27:5] биты инструкции) и должна быть **знакорасширена** до 32-х бит, то есть к 23-битной константе нужно приклеить слева 9 раз 23-ий знаковый бит константы (см. [оператор конкатенации](../../Basic%20Verilog%20structures/Concatenation.md)).
|
||||
The constant itself has a width of **23 bits** (bits `[27:5]` of the instruction) and must be **sign-extended** to 32 bits, meaning the 23-bit sign bit must be replicated 9 times to the left (see the [concatenation operator](../../Basic%20Verilog%20structures/Concatenation.md)).
|
||||
|
||||
Пример: если [27:5] биты инструкции равны:
|
||||
Example: if bits `[27:5]` of the instruction equal:
|
||||
|
||||
```text
|
||||
10100000111100101110111
|
||||
```
|
||||
|
||||
то после знакорасширения константа примет вид:
|
||||
then after sign extension the constant becomes:
|
||||
|
||||
```text
|
||||
11111111110100000111100101110111
|
||||
```
|
||||
|
||||
(если бы старший бит был равен нулю, то константа заполнилась бы слева нулями, а не единицами).
|
||||
(if the most significant bit were zero, the constant would be filled with zeros on the left instead of ones).
|
||||
|
||||
Нет ничего страшного в том, что биты константы попадают на те же поля, что и `alu_op`, `RA1` и `RA2` — когда выполняется инструкция загрузки константы не важно, что будет выдавать АЛУ в этот момент (ведь благодаря мультиплексору на вход регистрового файла приходит константа). А значит не важно и что приходит в этот момент на АЛУ в качестве операндов и кода операции. _Таблица 2_ демонстрирует деление 32-битной инструкции на поля `alu_op`, `RA1`, `RA2`, `WA`, `WS` и `rf_const`, **с перекрытием полей**.
|
||||
There is nothing wrong with the constant bits overlapping the same fields as `alu_op`, `RA1`, and `RA2` — when a constant load instruction is being executed, it does not matter what the ALU outputs at that moment (since the multiplexer routes the constant to the register file input). Therefore, it does not matter what arrives at the ALU as operands or operation code. _Table 2_ shows the division of the 32-bit instruction into the fields `alu_op`, `RA1`, `RA2`, `WA`, `WS`, and `rf_const`, **with overlapping fields**.
|
||||
|
||||

|
||||
|
||||
_Таблица 2. Добавление кодирования источника записи и 23-битной константы._
|
||||
_Table 2. Adding write source encoding and a 23-bit constant._
|
||||
|
||||
``` C
|
||||
reg_file[WA] ← rf_const
|
||||
```
|
||||
|
||||
На _рис. 2_ приводится фрагмент микроархитектуры, поддерживающий вычислительные операции на АЛУ и загрузку констант из инструкции в регистровый файл.
|
||||
_Fig. 2_ shows the microarchitecture fragment supporting ALU computational operations and loading constants from the instruction into the register file.
|
||||
|
||||
Так как вход записи уже занят результатом операции АЛУ, его потребуется мультиплексировать со значением константы из инструкции, которая предварительно **знакорасширяется** в блоке `SE`. На входе `WD` регистрового файла появляется мультиплексор, управляемый 28-м битом инструкции, который и определяет, что будет записано: константа или результат вычисления на АЛУ.
|
||||
Since the write input is already occupied by the ALU operation result, it must be multiplexed with the constant value from the instruction, which is first **sign-extended** in the `SE` block. A multiplexer controlled by bit 28 of the instruction appears at the `WD` input of the register file and determines what will be written: the constant or the ALU result.
|
||||
|
||||
Например, в такой реализации следующая 32-битная инструкция поместит константу `-1` в регистр по адресу `5`:
|
||||
For example, in this implementation, the following 32-bit instruction places the constant `-1` into the register at address `5`:
|
||||
|
||||
```text
|
||||
000 0 11111111111111111111111 00101
|
||||
@@ -175,45 +175,45 @@ _Таблица 2. Добавление кодирования источник
|
||||
|
||||

|
||||
|
||||
_Рисунок 2. Добавление константы из инструкции в качестве источников записи в регистровый файл._
|
||||
_Figure 2. Adding a constant from the instruction as a write source for the register file._
|
||||
|
||||
### Реализация загрузки в регистровый файл данных с внешних устройств
|
||||
### Implementing External Device Data Load into the Register File
|
||||
|
||||
Чтобы процессор мог взаимодействовать с внешним миром добавим возможность загрузки данных с внешних устройств в регистр по адресу `WA`. Появляется третий тип инструкции, который определяет третий источник ввода для регистрового файла. Одного бита `WS` для выбора одного из трех источников будет недостаточно, поэтому расширим это поле до 2 бит. Теперь, когда `WS == 0` будет загружаться константа, когда `WS == 1` – будет загружаться результат вычисления АЛУ, а при `WS == 2` будут загружаться данные с внешних устройств. Остальные поля (кроме `WA`) в данной инструкции не используются.
|
||||
To allow the processor to interact with the outside world, let us add the ability to load data from external devices into the register at address `WA`. A third instruction type appears, defining a third input source for the register file. A single `WS` bit is not enough to select among three sources, so the field is extended to 2 bits. Now, when `WS == 0`, a constant is loaded; when `WS == 1`, the ALU computation result is loaded; and when `WS == 2`, data from external devices is loaded. All other fields (except `WA`) are unused in this instruction.
|
||||
|
||||

|
||||
|
||||
_Таблица 3. Кодирование в инструкции большего числа источников записи._
|
||||
_Table 3. Encoding a larger number of write sources in the instruction._
|
||||
|
||||
``` C
|
||||
reg_file[WA] ← sw_i
|
||||
```
|
||||
|
||||
На _рис. 3_ приводится фрагмент микроархитектуры, поддерживающий вычислительные операции на АЛУ, загрузку констант из инструкции в регистровый файл и загрузку данных с внешних устройств.
|
||||
_Fig. 3_ shows the microarchitecture fragment supporting ALU computational operations, constant loads from the instruction into the register file, and data loads from external devices.
|
||||
|
||||
По аналогии с загрузкой констант увеличиваем входной мультиплексор до 4 входов и подключаем к нему управляющие сигналы – `[29:28]` биты инструкции. Последний вход используется, чтобы разрешить неопределённость на выходе при `WS == 3`(`default`-вход, см. [мультиплексор](../../Basic%20Verilog%20structures/Multiplexors.md)).
|
||||
By analogy with constant loading, the input multiplexer is expanded to 4 inputs and connected to the control signals — bits `[29:28]` of the instruction. The last input is used to resolve the output ambiguity when `WS == 3` (the `default` input; see [multiplexer](../../Basic%20Verilog%20structures/Multiplexors.md)).
|
||||
|
||||
Выход модуля `out_o` подключается к первому порту на чтение регистрового файла. Значение на выходе `out_o` будет определяться содержимым ячейки памяти по адресу `RA1`.
|
||||
The `out_o` output of the module is connected to the first read port of the register file. The value at the `out_o` output is determined by the contents of the register file cell at address `RA1`.
|
||||
|
||||

|
||||
|
||||
_Рисунок 3. Подключение к схеме источников ввода и вывода._
|
||||
_Figure 3. Connecting input and output sources to the schematic._
|
||||
|
||||
### Реализация условного перехода
|
||||
### Implementing Conditional Branch
|
||||
|
||||
С реализованным набором инструкций полученное устройство нельзя назвать процессором – пока что это продвинутый калькулятор. Добавим поддержку инструкции условного перехода, при выполнении которой программа будет перепрыгивать через заданное количество команд. Чтобы аппаратура отличала эту инструкцию от других будем использовать 30-ый бит `B` (`branch`). Если `B == 1`, значит это инструкция условного перехода и, если условие перехода выполняется, к `PC` надо прибавить константу. Если `B == 0`, значит это какая-то другая инструкция и к `PC` надо прибавить 4.
|
||||
With the current instruction set, the resulting device cannot be called a processor — at this point it is an advanced calculator. Let us add support for a conditional branch instruction, which causes the program to skip over a specified number of instructions. To distinguish this instruction from others, bit 30 `B` (`branch`) is used. If `B == 1`, this is a conditional branch instruction and, if the branch condition is met, the constant must be added to `PC`. If `B == 0`, this is some other instruction and 4 must be added to `PC`.
|
||||
|
||||

|
||||
|
||||
_Таблица 4.Кодирование условного перехода._
|
||||
_Table 4. Conditional branch encoding._
|
||||
|
||||
Для вычисления результата условного перехода, нам необходимо выполнить операцию на АЛУ и посмотреть на сигнал `flag`. Если он равен 1, переход выполняется, в противном случае — не выполняется. А значит, нам нужны операнды `A`, `B` и `alu_op`. Кроме того, нам необходимо указать насколько мы сместимся относительно текущего значения `PC` (константу смещения, `offset`). Для передачи этой константы лучше всего подойдут незадействованные биты инструкции `[12:5]`.
|
||||
To evaluate the result of a conditional branch, we need to perform an ALU operation and check the `flag` signal. If it equals 1, the branch is taken; otherwise it is not. This requires operands `A`, `B`, and `alu_op`. In addition, we need to specify by how much to offset relative to the current value of `PC` (the offset constant). Unused instruction bits `[12:5]` are best suited for passing this constant.
|
||||
|
||||
Обратим внимание на то, что `PC` 32-битный и должен быть всегда кратен четырем (`PC` не может указывать кроме как в начало инструкции, а каждая инструкция длиной в 32 бита). Кратные четырем двоичные числа всегда будут иметь в конце два нуля (так же, как и кратные ста десятичные числа). Поэтому для более эффективного использования битов константы смещения, эти два нуля будут неявно подразумеваться при её описании. При этом, перед увеличением программного счётчика на значение константы смещения, эти два нуля нужно будет к ней приклеить справа. Кроме того, чтобы разрядность константы совпадала с разрядностью `PC`, необходимо знакорасширить её до 32 бит.
|
||||
Note that `PC` is 32 bits wide and must always be a multiple of four (`PC` can only point to the start of an instruction, and each instruction is 32 bits long). Binary numbers that are multiples of four always end in two zeros (just as decimal numbers that are multiples of one hundred). Therefore, to make more efficient use of the offset constant bits, these two zeros are implicitly assumed in the encoding. Before adding the offset constant to the program counter, these two zeros must be appended to the right. Additionally, to match the bit width of `PC`, the constant must be sign-extended to 32 bits.
|
||||
|
||||
Предположим, мы хотим переместиться на две инструкции вперед. Это означает, что программный счётчик должен будет увеличиться на 8 ([2 инструкции] * [4 байта — размер одной инструкции в памяти]). Умножение константы смещения на 4 произойдет путем добавления к ней двух нулей справа, поэтому в поле `offset` мы просто записываем число инструкций, на которое мы переместим программный счётчик (на две): `0b00000010`.
|
||||
Suppose we want to jump forward by two instructions. This means the program counter must increase by 8 ([2 instructions] × [4 bytes — size of one instruction in memory]). Multiplying the offset constant by 4 happens by appending two zeros to the right, so in the `offset` field we simply write the number of instructions to jump (two): `0b00000010`.
|
||||
|
||||
Данный Си-подобный псевдокод (далее мы назовем его псевдоассемблером) демонстрирует кодирование инструкций с новым полем `B`:
|
||||
The following C-like pseudocode (referred to hereafter as pseudo-assembly) demonstrates instruction encoding with the new `B` field:
|
||||
|
||||
``` C
|
||||
if (reg_file[RA1] {alu_op} reg_file[RA2])
|
||||
@@ -222,94 +222,94 @@ _Таблица 4.Кодирование условного перехода._
|
||||
PC ← PC + 4
|
||||
```
|
||||
|
||||
Так как второй вход сумматора счётчика команд занят числом 4, то для реализации условного перехода этот вход надо мультиплексировать с константой. Мультиплексор при этом управляется 30-ым битом `B`, который и определяет, что будет прибавляться к `PC`.
|
||||
Since the second input of the program counter adder is already occupied by the value 4, this input must be multiplexed with the constant to implement a conditional branch. The multiplexer is controlled by bit 30 `B`, which determines what is added to `PC`.
|
||||
|
||||
Сигнальные линии, которые управляют АЛУ и подают на его входы операнды уже существуют. Поэтому на схему необходимо добавить только логику управления мультиплексором на входе сумматора счётчика команд. Эта логика работает следующим образом:
|
||||
The signal lines that control the ALU and supply its operands already exist. Therefore, only the control logic for the multiplexer at the program counter adder input needs to be added to the schematic. This logic operates as follows:
|
||||
|
||||
1. если сейчас инструкция условного перехода
|
||||
2. и если условие перехода выполнилось,
|
||||
1. if the current instruction is a conditional branch
|
||||
2. and if the branch condition is satisfied,
|
||||
|
||||
то к `PC` прибавляется знакорасширенная константа, умноженная на 4. В противном случае, к `PC` прибавляется 4.
|
||||
then the sign-extended constant multiplied by 4 is added to `PC`. Otherwise, 4 is added to `PC`.
|
||||
|
||||
Так как теперь не любая инструкция приводит к записи в регистровый файл, появляется необходимость управлять входом `WE` так, чтобы при операциях условного перехода запись в регистровый файл не производилась. Это можно сделать, подав на WE значение `!B` (запись происходит, если сейчас **не операция условного перехода**).
|
||||
Since not every instruction now leads to a write to the register file, the `WE` input must be controlled so that no write to the register file occurs during conditional branch operations. This can be done by driving `WE` with `!B` (a write occurs only when the current instruction is **not a conditional branch**).
|
||||
|
||||

|
||||
|
||||
_Рисунок 4. Реализация условного перехода._
|
||||
_Figure 4. Implementing the conditional branch._
|
||||
|
||||
### Реализация безусловного перехода
|
||||
### Implementing Unconditional Branch
|
||||
|
||||
Осталось добавить поддержку инструкции безусловного перехода, для идентификации которой используется оставшийся 31-ый бит `J`(jump). Если бит `J == 1`, то это безусловный переход, и мы прибавляем к `PC` знакорасширенную константу смещения, умноженную на 4 (как это делали и в условном переходе).
|
||||
All that remains is to add support for the unconditional branch instruction, identified by the remaining bit 31 `J` (jump). If bit `J == 1`, this is an unconditional branch, and we add the sign-extended offset constant multiplied by 4 to `PC` (exactly as done for conditional branch).
|
||||
|
||||

|
||||
|
||||
_Таблица 5. Кодирование безусловного перехода._
|
||||
_Table 5. Unconditional branch encoding._
|
||||
|
||||
``` C
|
||||
PC ← PC + const*4
|
||||
```
|
||||
|
||||
Для реализации безусловного перехода, нам необходимо добавить дополнительную логику управления мультиплексором перед сумматором. Итоговая логика его работы звучит так:
|
||||
To implement the unconditional branch, additional control logic for the multiplexer before the adder must be added. The final logic operates as follows:
|
||||
|
||||
1. если сейчас инструкция безусловного перехода, _или_
|
||||
2. если сейчас инструкция условного перехода _и_ условие перехода выполнилось,
|
||||
1. if the current instruction is an unconditional branch, _or_
|
||||
2. if the current instruction is a conditional branch _and_ the branch condition is satisfied,
|
||||
|
||||
то к `PC` прибавляется знакорасширенная константа, умноженная на 4. В противном случае, к `PC` прибавляется 4.
|
||||
then the sign-extended constant multiplied by 4 is added to `PC`. Otherwise, 4 is added to `PC`.
|
||||
|
||||
Кроме того, при безусловном переходе в регистровый файл также ничего не пишется. А значит, необходимо обновить логику работы сигнала разрешения записи `WE`, который будет равен 0 если сейчас инструкция условного или безусловного перехода.
|
||||
In addition, during an unconditional branch, nothing is written to the register file either. Therefore, the write-enable signal `WE` logic must be updated: `WE` equals 0 if the current instruction is a conditional or unconditional branch.
|
||||
|
||||
На _рис. 5_ приводится итоговый вариант микроархитектуры процессора `CYBERcobra`.
|
||||
_Fig. 5_ shows the final microarchitecture of the `CYBERcobra` processor.
|
||||
|
||||

|
||||
|
||||
_Рисунок 5. Реализация безусловного перехода._
|
||||
_Figure 5. Implementing the unconditional branch._
|
||||
|
||||
### Финальный обзор
|
||||
### Final Overview
|
||||
|
||||
Итого, архитектура `CYBERcobra` поддерживает 5 типов инструкций, которые кодируются следующим образом (символами `x` помечены биты, которые не задействованы в данной инструкции):
|
||||
In total, the `CYBERcobra` architecture supports 5 instruction types, encoded as follows (bits marked `x` are unused in the given instruction):
|
||||
|
||||
1. 10 вычислительных инструкций `0 0 01 alu_op RA1 RA2 xxxx xxxx WA`
|
||||
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 offset xxxxx`
|
||||
5. 6 инструкций условного перехода `0 1 xx alu_op RA1 RA2 offset xxxxx`
|
||||
1. 10 computational instructions: `0 0 01 alu_op RA1 RA2 xxxx xxxx WA`
|
||||
2. Load constant instruction: `0 0 00 const WA`
|
||||
3. Load from external devices instruction: `0 0 10 xxx xxxx xxxx xxxx xxxx xxxx WA`
|
||||
4. Unconditional branch: `1 x xx xxx xxxx xxxx xxxx offset xxxxx`
|
||||
5. 6 conditional branch instructions: `0 1 xx alu_op RA1 RA2 offset xxxxx`
|
||||
|
||||
При кодировании инструкций используются следующие поля:
|
||||
The following fields are used when encoding instructions:
|
||||
|
||||
- J – 1-битный сигнал, указывающий на выполнение безусловного перехода;
|
||||
- B – 1-битный сигнал, указывающий на выполнение условного перехода;
|
||||
- WS – 2-битный сигнал, указывающий источник данных для записи в регистровый файл:
|
||||
- 0 – константа из инструкции;
|
||||
- 1 – результат с АЛУ;
|
||||
- 2 – внешние данные;
|
||||
- 3 – не используется;
|
||||
- alu_op – 5-битный сигнал кода операции АЛУ (в соответствии с таблицей из лабораторной по АЛУ);
|
||||
- RA1 и RA2 – 5-битные адреса операндов из регистрового файла;
|
||||
- offset – 8-битная константа для условного / безусловного перехода;
|
||||
- const — 23-битная константа для загрузки в регистровый файл;
|
||||
- WA – 5-битный адрес регистра, в который будет записан результат.
|
||||
- J — 1-bit signal indicating an unconditional branch;
|
||||
- B — 1-bit signal indicating a conditional branch;
|
||||
- WS — 2-bit signal indicating the data source for writing to the register file:
|
||||
- 0 — constant from the instruction;
|
||||
- 1 — result from the ALU;
|
||||
- 2 — external data;
|
||||
- 3 — unused;
|
||||
- alu_op — 5-bit ALU operation code (as defined in the ALU lab table);
|
||||
- RA1 and RA2 — 5-bit addresses of operands in the register file;
|
||||
- offset — 8-bit constant for conditional/unconditional branch;
|
||||
- const — 23-bit constant for loading into the register file;
|
||||
- WA — 5-bit address of the register where the result will be written.
|
||||
|
||||
Напишем простую программу для этого процессора, которая циклично увеличивает значение первого регистра на 1 до тех пор, пока его значение не превысит число, введенное на переключателях. Сначала напишем программу на псевдоассемблере (используя предложенную мнемонику):
|
||||
Let us write a simple program for this processor that cyclically increments the value of the first register by 1 until it exceeds the number entered on the switches. First, the program is written in pseudo-assembly (using the proposed mnemonics):
|
||||
|
||||
``` C
|
||||
reg_file[1] ← -1 // загрузить константу -1 в регистр 1
|
||||
reg_file[2] ← sw_i // загрузить значение с входа sw_i в регистр 2
|
||||
reg_file[3] ← 1 // загрузить константу 1 в регистр 3
|
||||
reg_file[1] ← -1 // load constant -1 into register 1
|
||||
reg_file[2] ← sw_i // load value from input sw_i into register 2
|
||||
reg_file[3] ← 1 // load constant 1 into register 3
|
||||
|
||||
reg_file[1] ← reg_file[1] + reg_file[3] // сложить регистр 1 с регистром 3 и
|
||||
// поместить результат в регистр 1
|
||||
reg_file[1] ← reg_file[1] + reg_file[3] // add register 1 and register 3 and
|
||||
// store the result in register 1
|
||||
|
||||
if (reg_file[1] < reg_file[2]) // если значение в регистре 1 меньше
|
||||
// значения в регистре 2,
|
||||
PC ← PC + (-1) // возврат на 1 инструкцию назад
|
||||
if (reg_file[1] < reg_file[2]) // if the value in register 1 is less than
|
||||
// the value in register 2,
|
||||
PC ← PC + (-1) // go back 1 instruction
|
||||
|
||||
out_o = reg_file[1], PC ← PC + 0 // бесконечное повторение этой инструкции
|
||||
// с выводом на out_o значения в регистре 1
|
||||
out_o = reg_file[1], PC ← PC + 0 // infinite repetition of this instruction
|
||||
// with output of register 1 value on out_o
|
||||
```
|
||||
_Листинг 1. Пример программы для CYBERcobra._
|
||||
_Listing 1. Example program for CYBERcobra._
|
||||
|
||||
|
||||
Теперь в соответствии с кодировкой инструкций переведем программу в машинные коды:
|
||||
Now, according to the instruction encoding, the program is translated into machine codes:
|
||||
|
||||
```text
|
||||
0 0 00 11111111111111111111111 00001
|
||||
@@ -319,26 +319,26 @@ _Листинг 1. Пример программы для CYBERcobra._
|
||||
0 1 00 11110 00001 00010 11111111 00000
|
||||
1 0 00 00000 00001 00000 00000000 00000
|
||||
```
|
||||
_Листинг 2. Представление листинга 1 в виде машинных кодов._
|
||||
_Listing 2. Listing 1 represented in machine codes._
|
||||
|
||||
Полученную программу можно помещать в память программ и выполнять на процессоре.
|
||||
The resulting program can be placed in program memory and executed on the processor.
|
||||
|
||||
## Инструменты для реализации процессора
|
||||
## Tools for Processor Implementation
|
||||
|
||||
Так как все модули процессора написаны, основная часть кода описания процессора будет связана с подключением этих модулей друг к другу. Подробнее о подключении модулей сказано в [Modules.md](../../Basic%20Verilog%20structures/Modules.md).
|
||||
Since all processor modules have been written, the main part of the processor description code will involve connecting these modules to each other. More details about module instantiation are given in [Modules.md](../../Basic%20Verilog%20structures/Modules.md).
|
||||
|
||||
Для реализации блоков знакорасширения с умножением на 4 подходит использование оператора конкатенации ([Concatenation.md](../../Basic%20Verilog%20structures/Concatenation.md)).
|
||||
The concatenation operator ([Concatenation.md](../../Basic%20Verilog%20structures/Concatenation.md)) is suitable for implementing sign-extension blocks with multiplication by 4.
|
||||
|
||||
## Задание по реализации процессора
|
||||
## Assignment
|
||||
|
||||
Разработать процессор `CYBERcobra` (см. [_рис. 5_](../../.pic/Labs/lab_04_cybercobra/ppd_5.drawio.svg)), объединив ранее разработанные модули:
|
||||
Develop the `CYBERcobra` processor (see [_Fig. 5_](../../.pic/Labs/lab_04_cybercobra/ppd_5.drawio.svg)) by combining the previously developed modules:
|
||||
|
||||
- Память инструкций (проинициализированную в двоичном формате файлом [`program.mem`](program.mem))
|
||||
- Регистровый файл
|
||||
- Арифметико-логическое устройство
|
||||
- 32-битный сумматор
|
||||
- Instruction memory (initialized in binary format with the file [`program.mem`](program.mem))
|
||||
- Register file
|
||||
- Arithmetic Logic Unit
|
||||
- 32-bit adder
|
||||
|
||||
Кроме того, необходимо описать регистр счётчика команд и логику его работы, в соответствии с ранее представленной микроархитектурой.
|
||||
In addition, the program counter register and its operating logic must be described in accordance with the microarchitecture presented above.
|
||||
|
||||
```Verilog
|
||||
module CYBERcobra (
|
||||
@@ -351,32 +351,32 @@ module CYBERcobra (
|
||||
endmodule
|
||||
```
|
||||
|
||||
## Порядок выполнения задания
|
||||
## Steps
|
||||
|
||||
1. Добавьте в `Design Sources` проекта файл [program.mem](program.mem), содержащий программу из Листинга 1.
|
||||
2. Опишите модуль `CYBERcobra` с таким же именем и портами, как указано в задании (обратите внимание на регистр имени модуля).
|
||||
1. В первую очередь, необходимо создать счётчик команд и все вспомогательные провода. При создании, **следите за разрядностью**.
|
||||
2. Затем, необходимо создать экземпляры модулей: памяти инструкции, АЛУ, регистрового файла и сумматора. При подключении сигналов сумматора, надо **обязательно** подать нулевое значение на входной бит переноса. Выходной бит переноса подключать не обязательно. Объекту памяти инструкций нужно дать имя `imem`.
|
||||
3. После этого, необходимо описать оставшуюся логику:
|
||||
1. Программного счётчика. Счётчик должен сбрасываться, когда сигнал _rst_i == 1_.
|
||||
2. Сигнала управления мультиплексором, выбирающим слагаемое для программного счётчика
|
||||
3. Сигнала разрешения записи в регистровый файл
|
||||
4. Мультиплексор, выбирающий слагаемое для программного счётчика
|
||||
5. Мультиплексор, выбирающий источник записи в регистровый файл.
|
||||
3. Проверьте модуль с помощью верификационного окружения, представленного в файле [`lab_04.tb_cybercobra.sv`](lab_04.tb_cybercobra.sv).
|
||||
1. Перед запуском моделирования убедитесь, что у вас выбран корректный модуль верхнего уровня в `Simulation Sources`.
|
||||
2. В этот раз в конце не будет сообщения о том, работает ли ваше устройство или в нём есть ошибки. Вам необходимо самостоятельно проверить работу модуля, перенеся его внутренние сигналы на временную диаграмму, и [изучив](../../Vivado%20Basics/05.%20Bug%20hunting.md) их поведение.
|
||||
3. По сути, проверка сводится к потактовому изучению временной диаграммы, во время которого вам нужно циклично ответить на следующие вопросы (после чего необходимо сравнить предсказанный ответ со значением сигналов на временной диаграмме):
|
||||
1. Какое сейчас значение программного счётчика?
|
||||
2. Какая инструкция должна быть считана при данном значении программного счётчика?
|
||||
3. Как должно обновиться содержимое регистрового файла в результате выполнения этой инструкции: должно ли записаться какое-либо значение? Если да, то какое и по какому адресу?
|
||||
4. Как должен измениться программный счётчик после выполнения этой инструкции?
|
||||
4. Проверьте работоспособность вашей цифровой схемы в ПЛИС.
|
||||
1. Add the file [program.mem](program.mem), containing the program from Listing 1, to the `Design Sources` of the project.
|
||||
2. Describe the `CYBERcobra` module with the same name and ports as specified in the task (pay attention to the case of the module name).
|
||||
1. First, create the program counter and all auxiliary wires. When doing so, **pay attention to bit widths**.
|
||||
2. Then, instantiate the modules: instruction memory, ALU, register file, and adder. When connecting the adder signals, you **must** drive the carry-in with zero. The carry-out does not need to be connected. The instruction memory instance must be named `imem`.
|
||||
3. After that, describe the remaining logic:
|
||||
1. Program counter. The counter must reset when _rst_i == 1_.
|
||||
2. Control signal for the multiplexer that selects the addend for the program counter.
|
||||
3. Write-enable signal for the register file.
|
||||
4. Multiplexer that selects the addend for the program counter.
|
||||
5. Multiplexer that selects the write source for the register file.
|
||||
3. Verify the module using the testbench provided in the file [`lab_04.tb_cybercobra.sv`](lab_04.tb_cybercobra.sv).
|
||||
1. Before running the simulation, make sure the correct top-level module is selected in `Simulation Sources`.
|
||||
2. This time there will be no message at the end indicating whether the device works correctly or contains errors. You must verify the module operation independently by adding its internal signals to the waveform and [examining](../../Vivado%20Basics/05.%20Bug%20hunting.md) their behavior.
|
||||
3. Essentially, verification comes down to a cycle-by-cycle study of the waveform, during which you must repeatedly answer the following questions (and then compare the predicted answer with the signal values on the waveform):
|
||||
1. What is the current value of the program counter?
|
||||
2. Which instruction should be fetched at this program counter value?
|
||||
3. How should the register file contents be updated as a result of executing this instruction: should any value be written? If so, what value and at which address?
|
||||
4. How should the program counter change after executing this instruction?
|
||||
4. Verify the operation of your digital circuit on the FPGA.
|
||||
|
||||
---
|
||||
|
||||
После выполнения задания по реализации процессора, необходимо также выполнить [индивидуальное задание](Индивидуальное%20задание) по написанию двоичной программы под созданный вами процессор.
|
||||
After completing the processor implementation task, you must also complete the [individual assignment](Индивидуальное%20задание) of writing a binary program for the processor you have created.
|
||||
|
||||
---
|
||||
|
||||
Дерзайте!
|
||||
Good luck!
|
||||
|
||||
Reference in New Issue
Block a user