mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
WIP: APS cumulative update (#98)
* WIP: APS cumulative update * Update How FPGA works.md * Перенос раздела "Последовательностная логика" в отдельный док * Исправление картинки * Исправление оформления индексов * Переработка раздела Vivado Basics * Добавление картинки в руководство по созданию проекта * Исправление ссылок в анализе rtl * Обновление изображения в sequential logic * Исправление ссылок в bug hunting * Исправление ссылок * Рефактор руководства по прошивке ПЛИС * Mass update * Update fig_10 * Restore fig_02
This commit is contained in:
committed by
GitHub
parent
78bb01ef95
commit
a28002e681
@@ -1,4 +1,4 @@
|
||||
# Лабораторная работа 2. Арифметико-логическое устройство
|
||||
# Лабораторная работа №2. Арифметико-логическое устройство
|
||||
|
||||
Так как основной задачей процессора является обработка цифровых данных, одним из его основных блоков является арифметико-логическое устройство (АЛУ). Задача АЛУ производить над входными данным арифметические и поразрядно логические операции.
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
## Материалы для подготовки к лабораторной работе
|
||||
|
||||
Освоить [описание мультиплексора на языке SystemVerilog](../../Basic%20Verilog%20structures/Multiplexors.md).
|
||||
В дополнение к [материалам](../../Basic%20Verilog%20structures/), изученным в ходе предыдущей лабораторной работы, вам рекомендуется ознакомиться с:
|
||||
|
||||
- способами описания [мультиплексора](../../Basic%20Verilog%20structures/Multiplexors.md) на языке SystemVerilog.
|
||||
|
||||
## Общий ход выполнения работы
|
||||
|
||||
@@ -20,7 +22,7 @@
|
||||
|
||||
## Теория
|
||||
|
||||
Арифметико-логическое устройство (АЛУ, Arithmetic Logic Unit – ALU) – это блок процессора, выполняющий арифметические и поразрядно логические операции. Разница между арифметическими и логическими операциями в отсутствии у последних бита переноса, так как логические операции происходят между 1-битными числами и дают 1-битный результат, а в случае АЛУ (в рамках данной лабораторной работы) одновременно между 32-мя 1-битными парами чисел. В логических операциях результаты значений отдельных битов друг с другом никак не связаны.
|
||||
**Арифметико-логическое устройство** (**АЛУ**, Arithmetic Logic Unit – ALU) – это блок процессора, выполняющий арифметические и поразрядно логические операции. Разница между арифметическими и логическими операциями в отсутствии у последних бита переноса, так как логические операции происходят между 1-битными числами и дают 1-битный результат, а в случае АЛУ (в рамках данной лабораторной работы) одновременно между 32-мя 1-битными парами чисел. В логических операциях результаты значений отдельных битов друг с другом никак не связаны.
|
||||
|
||||
Также, кроме результата операций, АЛУ формирует флаги, которые показывают выполняется ли заданное условие. Например, выведет `1`, если один операнд меньше другого.
|
||||
|
||||
@@ -32,7 +34,7 @@ _Рисунок 1. Структурное обозначение элемент
|
||||
|
||||
На рис. 1 изображен пример АЛУ, используемый в книге "Цифровая схемотехника и архитектура компьютера" Харрис и Харрис. На входы `A` и `B` поступают операнды с разрядностью _N_. На 3-битный вход `F` подается код операции. Например, если туда подать `000`, то на выходе `Y` появится результат операции _логическое И_ между битами операндов `A` и `B`. Если на `F` подать `010`, то на выходе появится результат сложения. Это лишь пример, разрядность и коды могут отличаться в зависимости от количества выполняемых операций и архитектуры.
|
||||
|
||||
Существует несколько подходов к реализации АЛУ, отличающиеся внутренней организацией. В лабораторных работах применяется повсеместно используемый подход мультиплексирования операций, то есть подключения нескольких операционных устройств (которые выполняют какие-то операции, например сложения, логического И и т.п.) к мультиплексору, который будет передавать результат нужного операционного устройства на выходы АЛУ.
|
||||
Существует несколько подходов к реализации АЛУ, отличающиеся внутренней организацией. В лабораторных работах применяется повсеместно используемый подход мультиплексирования операций, то есть подключения нескольких операционных устройств (которые выполняют какие-то операции, например сложения, логического ИЛИ и т.п.) к мультиплексору, который будет передавать результат нужного операционного устройства на выходы АЛУ.
|
||||
|
||||
Рассмотрим данный подход на примере все того же АЛУ MIPS из книги Харрисов. На рис. 2, в левой его части, изображена внутренняя организация этого АЛУ, справа – таблица соответствия кодов операциям. На выходе схемы (внизу) стоит 4-входовой мультиплексор, управляемый двумя из трех битов `F`. К его входам подключены _N_ логических И (побитовое И _N_-битных операндов), _N_ логических ИЛИ, _N_-битный сумматор и Zero Extend – устройство, дополняющее слева нулями 1-битное число до N-битного.
|
||||
|
||||
@@ -75,40 +77,43 @@ _Рисунок 3. Пример исполнения операции АЛУ._
|
||||
|
||||
Пример:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module overflow #(parameter WIDTH = 32)(
|
||||
input logic [WIDTH-1 : 0] a, b,
|
||||
output logic overflow
|
||||
output logic overflow
|
||||
);
|
||||
|
||||
logic [WIDТН : 0] sum;
|
||||
logic [WIDTH : 0] sum;
|
||||
|
||||
ass𝚒gn sum = a + b;
|
||||
ass𝚒gn overflow = sum[WIDTH];
|
||||
assign sum = a + b;
|
||||
assign overflow = sum[WIDTH];
|
||||
|
||||
endmodule
|
||||
```
|
||||
|
||||
_Листинг 1. Пример описания параметра в прототипе модуля._
|
||||
|
||||
В случае, если параметр не влияет на разрядность портов, его можно объявить в теле модуля:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
module toaster(
|
||||
input logic [31:0] command,
|
||||
output logic power
|
||||
)
|
||||
|
||||
parameter TOASTER_EN = 32'haf3c5bd0;
|
||||
|
||||
assign power = command == TOASTER_EN;
|
||||
|
||||
endmodule
|
||||
```
|
||||
|
||||
_Листинг 2. Пример описания параметра в теле модуля._
|
||||
|
||||
В случае АЛУ будет удобно использовать параметры для обозначения кодов команд. Во-первых, для того чтобы в `case` не допустить ошибок, а во-вторых – чтобы можно было легко менять управляющие коды для повторного использования АЛУ в других проектах.
|
||||
|
||||
Сравните сами:
|
||||
Сравните сами _листинги 3 и 4_:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
//parameter SLT = 5'b00011;
|
||||
//parameter BEQ = 5'b11000;
|
||||
|
||||
@@ -121,28 +126,30 @@ always_comb
|
||||
5'b11000: //... // никуда не годится
|
||||
```
|
||||
|
||||
и
|
||||
_Листинг 3. Пример описания модуля, использующего "магические" числа._
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
parameter SLT = 5'b00011;
|
||||
parameter BEQ = 5'b11000;
|
||||
|
||||
//...
|
||||
|
||||
аlwауs_comb
|
||||
always_comb
|
||||
case(ALUOp)
|
||||
//...
|
||||
SLT: //... // очень понятно
|
||||
BEQ: //... // так лаконично и красиво
|
||||
```
|
||||
|
||||
С параметрами гораздо взрослее, серьезнее и понятнее смотрится. Кстати, сразу на заметку: в SystemVerilog можно объединять группу параметров в **пакет** (package), а затем импортировать его внутрь модуля, позволяя переиспользовать параметры без повторного их прописывания для других модулей.
|
||||
_Листинг 4. Пример описания модуля, использующего параметры._
|
||||
|
||||
С параметрами смотрится гораздо взрослее, серьёзнее и понятнее. Кстати, сразу на заметку: в SystemVerilog можно объединять группу параметров в **пакет** (package), а затем импортировать его внутрь модуля, позволяя переиспользовать параметры без повторного их прописывания для других модулей.
|
||||
|
||||
Делается это следующим образом.
|
||||
|
||||
Сперва создается SystemVerilog-файл, который будет содержать пакет (к примеру, содержимое файла может быть таким):
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
package riscv_params_pkg;
|
||||
parameter ISA_WIDTH = 32;
|
||||
parameter ANOTHER_EX = 15;
|
||||
@@ -151,16 +158,17 @@ endpackage
|
||||
|
||||
Далее, внутри модуля, которому нужны параметры из этого пакета, необходимо сделать соответствующий импорт этих параметров. Это можно сделать либо для каждого параметра отдельно, либо импортировать все параметры сразу:
|
||||
|
||||
```SystemVerilog
|
||||
module riscv_processor(
|
||||
```Verilog
|
||||
module riscv_processor
|
||||
//import riscv_params_pkg::*;
|
||||
import riscv_params_pkg::ISA_WIDTH; // Если необходимо импортировать
|
||||
(
|
||||
//...Порты
|
||||
);
|
||||
|
||||
import riscv_params_pkg::ISA_WIDTH; // Если необходимо импортировать
|
||||
import riscv_params_pkg::ANOTHER_EX; // все параметры в пакете,эти две строчки
|
||||
import riscv_params_pkg::ANOTHER_EX; // все параметры в пакете, эти две строчки
|
||||
// могут быть заменены закомментированной
|
||||
// ниже строкой:
|
||||
//import riscv_params_pkg::*;
|
||||
// выше строкой:
|
||||
|
||||
endmodule
|
||||
```
|
||||
@@ -191,14 +199,14 @@ endmodule
|
||||
|
||||
Необходимо на языке SystemVerilog реализовать АЛУ в соответствии со следующим прототипом:
|
||||
|
||||
```SystemVerilog
|
||||
```Verilog
|
||||
|
||||
module аlu_r𝚒sсv (
|
||||
𝚒nput logic [31:0] a_i,
|
||||
𝚒nput logic [31:0] b_i,
|
||||
𝚒nput logic [4:0] alu_op_i,
|
||||
оutput logic flag_o,
|
||||
оutput logic [31:0] result_o
|
||||
module alu (
|
||||
input logic [31:0] a_i,
|
||||
input logic [31:0] b_i,
|
||||
input logic [4:0] alu_op_i,
|
||||
output logic flag_o,
|
||||
output logic [31:0] result_o
|
||||
);
|
||||
|
||||
import alu_opcodes_pkg::*; // импорт параметров, содержащих
|
||||
@@ -271,8 +279,8 @@ _Таблица 2. Список операций сравнения._
|
||||
|
||||
Конструкция `$signed` говорит САПР интерпретировать число, переданное в качестве операнда, как знаковое.
|
||||
|
||||
```SystemVerilog
|
||||
аss𝚒gn Rеsult = $s𝚒gnеd(А) >>> В[4:0];
|
||||
```Verilog
|
||||
assign Result = $signed(A) >>> B[4:0];
|
||||
```
|
||||
|
||||
В этом примере некоторому сигналу `Result` присваивают результат сдвига знакового числа `A` на значение количества бит получаемых из младших 5 бит сигнала `B`.
|
||||
@@ -285,9 +293,8 @@ _Рисунок 4. Пример схемы, реализующей АЛУ._
|
||||
|
||||
### Порядок выполнения задания
|
||||
|
||||
1. Добавьте в проект файл [`alu_opcodes_pkg.sv`](alu_opcodes_pkg.sv). Этот файл содержит объявление пакета `alu_opcodes_pkg`, в котором прописаны все опкоды АЛУ.
|
||||
2. В `Design Sources` проекта создайте `SystemVerilog`-файл `аlu_r𝚒sсv.sv`.
|
||||
3. Опишите в нем модуль АЛУ с таким же именем и портами, как указано в [задании](#задание).
|
||||
1. Добавьте в `Design Sources` проекта файл [`alu_opcodes_pkg.sv`](alu_opcodes_pkg.sv). Этот файл содержит объявление пакета `alu_opcodes_pkg`, в котором прописаны все опкоды АЛУ.
|
||||
2. Опишите модуль `alu` с таким же именем и портами, как указано в [задании](#задание).
|
||||
1. Поскольку у вас два выходных сигнала, зависящих от сигнала `alu_op_i`, вам потребуется описать два разных [мультиплексора](../../Basic%20Verilog%20structures/Multiplexors.md) (их лучше всего описывать через два отдельных блока `case`). При описании, используйте `default` на оставшиеся комбинации сигнала `alu_op_i`.
|
||||
2. Следите за разрядностью ваших сигналов.
|
||||
3. Для реализации АЛУ, руководствуйтесь таблицей с операциями, а не схемой в конце задания, которая приведена в качестве референса. Обратите внимание, в одной половине операций `flag_o` должен быть равен нулю, в другой `result_o` (т.е. всегда либо один, либо другой сигнал должен быть равен нулю). Именно поэтому удобней всего будет описывать АЛУ в двух разных блоках `case`.
|
||||
@@ -296,19 +303,9 @@ _Рисунок 4. Пример схемы, реализующей АЛУ._
|
||||
1. При подключении сумматора, на входной бит переноса необходимо подать значение `1'b0`. Если не подать значение на входной бит переноса, результат суммы будет не определен (т.к. не определено одно из слагаемых).
|
||||
2. Выходной бит переноса при подключении сумматора можно не указывать, т.к. он использоваться не будет.
|
||||
6. При реализации операций сдвига, руководствуйтесь [особенностями реализации сдвигов](#особенности-реализации-сдвига).
|
||||
4. После реализации модуля АЛУ его нужно будет проверить с помощью тестового окружения.
|
||||
1. Добавьте файл [`tb_alu.sv`](tb_alu.sv) в `Simulation sources`.
|
||||
2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||||
3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран модуль `tb_alu`.
|
||||
4. Убедитесь, что симуляция завершена (об этом будет соответствующее сообщение в консоли). По завершению симуляции, в случае отсутствия ошибок, будет выведено сообщение "SUCCESS", в противном случае будут выведены сообщения об этих ошибках.
|
||||
5. В случае, если были найдены ошибки, вы должны найти и исправить их. Для этого руководствуйтесь [документом](../../Vivado%20Basics/Debug%20manual.md).
|
||||
5. Проверьте работоспособность вашей цифровой схемы в ПЛИС. Для этого:
|
||||
1. Добавьте файлы из папки [`board files`](https://github.com/MPSU/APS/tree/master/Labs/02.%20Arithmetic-logic%20unit/board%20files) в проект.
|
||||
1. Файл [nexys_alu.sv](https://github.com/MPSU/APS/tree/master/Labs/02.%20Arithmetic-logic%20unit/board%20files/nexys_alu.sv) необходимо добавить в `Design Sources` проекта.
|
||||
2. Файл [nexys_a7_100t.xdc](https://github.com/MPSU/APS/tree/master/Labs/02.%20Arithmetic-logic%20unit/board%20files/nexys_a7_100t.xdc) необходимо добавить в `Constraints` проекта. В случае, если вы уже добавляли одноименный файл в рамках предыдущих лабораторных работ, его содержимое необходимо заменить содержимым нового файла.
|
||||
2. Выберите `nexys_alu` в качестве модуля верхнего уровня (`top-level`).
|
||||
3. Выполните генерацию битстрима и сконфигурируйте ПЛИС. Для этого воспользуйтесь [следующей инструкцией](../../Vivado%20Basics/How%20to%20program%20an%20fpga%20board.md).
|
||||
4. Описание логики работы модуля верхнего уровня и связи периферии ПЛИС с реализованным модулем находится в папке [`board files`](https://github.com/MPSU/APS/tree/master/Labs/02.%20Arithmetic-logic%20unit/board%20files).
|
||||
3. Проверьте модуль с помощью верификационного окружения, представленного в файле [`lab_02.tb_alu.sv`](lab_02.tb_alu.sv). В случае, если в TCL-консоли появились сообщения об ошибках, вам необходимо [найти](../../Vivado%20Basics/05.%20Bug%20hunting.md) и исправить их.
|
||||
1. Перед запуском моделирования, убедитесь, что у вас выбран корректный модуль верхнего уровня в `Simulation Sources`.
|
||||
4. Проверьте работоспособность вашей цифровой схемы в ПЛИС.
|
||||
|
||||
## Список использованной литературы
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
После того, как вы проверили на моделировании АЛУ, вам необходимо проверить его работу на прототипе в ПЛИС.
|
||||
|
||||
Инструкция по реализации прототипа описана [здесь](../../../Vivado%20Basics/How%20to%20program%20an%20fpga%20board.md).
|
||||
Инструкция по реализации прототипа описана [здесь](../../../Vivado%20Basics/07.%20Program%20and%20debug.md).
|
||||
|
||||
На _рис. 1_ представлена схема прототипа в ПЛИС.
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
|
||||
* ------------------------------------------------------------------------------
|
||||
*/
|
||||
module tb_alu();
|
||||
module lab_02_tb_alu();
|
||||
|
||||
import alu_opcodes_pkg::*;
|
||||
|
||||
@@ -28,7 +28,7 @@ wire [31:0] result_ref;
|
||||
wire comparison_result_ref;
|
||||
|
||||
|
||||
alu_riscv DUT
|
||||
alu DUT
|
||||
(
|
||||
.alu_op_i (operator_i ),
|
||||
.a_i (operand_a_i),
|
||||
@@ -38,7 +38,7 @@ alu_riscv DUT
|
||||
.flag_o (comparison_result_dut)
|
||||
);
|
||||
|
||||
alu_riscv_ref REF
|
||||
alu_ref REF
|
||||
(
|
||||
.alu_op_i (operator_i ),
|
||||
.a_i (operand_a_i),
|
||||
@@ -54,7 +54,6 @@ reg [8*9:1] operator_type;
|
||||
initial
|
||||
begin
|
||||
$display("Test has been started");
|
||||
$display( "\n\n==========================\nCLICK THE BUTTON 'Run All'\n==========================\n"); $stop();
|
||||
//X_test();
|
||||
result_test();
|
||||
flag_test();
|
||||
@@ -141,7 +140,7 @@ task direct_test();
|
||||
logic [4:0] flag_opcodes_2[3] = {ALU_SLL, ALU_SRL, ALU_SRA};
|
||||
logic [4:0] flag_opcodes_3[2] = {ALU_ADD, ALU_SUB};
|
||||
logic [4:0] flag_opcodes_4[5] = {ALU_XOR, ALU_OR, ALU_AND, ALU_EQ, ALU_NE};
|
||||
|
||||
|
||||
repeat(100)
|
||||
begin
|
||||
std::randomize(operand_a_i, operand_b_i) with {operand_a_i==operand_b_i;};
|
||||
@@ -191,14 +190,14 @@ task direct_test();
|
||||
|
||||
repeat(100)
|
||||
begin
|
||||
std::randomize(operand_a_i) with {operand_a_i > {31{1'b1}};};
|
||||
std::randomize(operand_a_i) with {operand_a_i > {31{1'b1}};};
|
||||
std::randomize(operand_b_i) with {operand_b_i > {31{1'b1}};};
|
||||
foreach(flag_opcodes_3[i]) begin
|
||||
operator_i = flag_opcodes_3[i];
|
||||
@(posedge clk);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
repeat(100)
|
||||
begin
|
||||
operand_a_i = $urandom();
|
||||
@@ -256,7 +255,7 @@ parameter HASH_LEN = 1000;
|
||||
parameter START_CODING = 10366;
|
||||
parameter START_MUX = START_CODING+100;
|
||||
|
||||
module alu_riscv_ref (
|
||||
module alu_ref (
|
||||
input logic [ALUOP_W-1:0] alu_op_i,
|
||||
input logic [OP_W-1:0] a_i,
|
||||
input logic [OP_W-1:0] b_i,
|
Reference in New Issue
Block a user