Опубликован: 17.03.2025 | Доступ: свободный | Студентов: 7 / 0 | Длительность: 07:30:00
Лекция 10:

Проектирование блока управления

Содержимое файла ROM памяти приведено ниже

v3.0 hex words addressed
0000: 00000093 0010a0a3 00100093 0010a223 00100133 0020a423 002081b3 0030a623
0008: 00310233 0040a823 004182b3 0050aa23 00520333 0060ac23 006283b3 0070ae23
0010: 00730433 0280a023 008384b3 0290a223 00000513 00000073 00000000 00000000

На рисунке 10.28 приведен итог вычисления числа Фибоначчи. Он должен соответствовать результату вычисления в линейном алгоритме.


Рис. 10.28.

Для завершения проектирования процессора на языке Verilog HDL необходимо вернуться в среду в ранее созданный проект RISC_V. Реализуем блок переходов BranchUnit. Как видно из рисунка 10.23 в его основе лежат компараторы, выполняющие сравнение двух 32-х битных кодов. В зависимости от кода на шине funct3 коммутирующие результирующий сигнал сравнения на выход. На языке Verilog HDL данная схема может быть реализована так как показано в листинге 10.4 (файл BranchUnit.v)

module BranchUnit(
    input [31:0] srcA, srcB, //входы данных с регистров
    input [2:0] funct3, // вход funct3
    output reg branchTaken //выход сигнализирующий о наличии перехода
);
    always @(*) begin
        case (funct3)
            3'b000: branchTaken = (srcA == srcB); // BEQ
            3'b001: branchTaken = (srcA != srcB); // BNE
            3'b100: branchTaken = ($signed(srcA) < $signed(srcB)); // BLT
            3'b101: branchTaken = ($signed(srcA) >= $signed(srcB)); // BGE
            3'b110: branchTaken = (srcA < srcB); // BLTU
            3'b111: branchTaken = (srcA >= srcB); // BGEU
            default: branchTaken = 1'b0; // по умолчанию выход 0 
        endcase
    end
endmodule
Листинг 10.4.

На рисунке 10.29 приведен вид RTL созданного модуля. Развернув его (рисунок 10.30) , можно убедится в эквивалентности схемы, приведенной на рисунке 10.23.


Рис. 10.29.

Рис. 10.30.

Реализуем модуля дешифратора операций АЛУ. Для этого создадим файл ALUDecoder.v. В листинге 10.5 приведен код данного модуля. Анализируя поля funct7, funct3 инструкции RISC-V, а также поле aluOp формируемое блоком ControlUnit данный дешифратор осуществляет формирование кода микрооперации в АЛУ.

module ALUDecoder(
    input [6:0] funct7,
    input [2:0] funct3,
    input [1:0] aluOp,//код операции
    output reg [3:0] aluControl
);
    always @(*) begin
        case (aluOp)
            2'b00: aluControl = 4'b0000; // операции загрузка/сохранение (ADD)
            2'b01: aluControl = 4'b0001; // операция ветвления (SUB)
            2'b10: begin // R-type инструкции
                case ({funct7, funct3})
                    10'b0000000000: aluControl = 4'b0000; // ADD
                    10'b0100000000: aluControl = 4'b0001; // SUB
                    10'b0000000111: aluControl = 4'b0010; // AND
                    10'b0000000110: aluControl = 4'b0011; // OR
                    10'b0000000100: aluControl = 4'b0100; // XOR
                    10'b0000000001: aluControl = 4'b0101; // SLL
                    10'b0000000101: aluControl = 4'b0110; // SRL
                    10'b0100000101: aluControl = 4'b0111; // SRA
                    10'b0000000010: aluControl = 4'b1000; // SLT
                    10'b0000000011: aluControl = 4'b1001; // SLTU
                    default: aluControl = 4'b0000;
                endcase
            end
            default: aluControl = 4'b0000;
        endcase
    end
endmodule
Листинг 10.5.

На рисунке 10.31 приведен вид RTL созданного модуля.


Рис. 10.31.

Следующим этапом выполним построение "сплиттера" кода инструкции - дешифратора инструкции (схемотехническая реализация разборки кода инструкции рассмотрена нами в начале данного раздела). Создадим в проекте RISC_V новый файл с именем InstructionDecoder.v. Внесем в него код из листинга 10.6.

module InstructionDecoder(
    input [31:0] instr,
    output [6:0] opcode,
    output [4:0] rd,
    output [2:0] funct3,
    output [4:0] rs1, rs2,
    output [6:0] funct7,
    output [31:0] imm
);
    assign opcode = instr[6:0];// выделяем 0 по 6 бит под opcode
    assign rd = instr[11:7]; //с 7 по 11 бит адрес регистра назначения
    assign funct3 = instr[14:12]; //с 12 по 14 бит поле funct3
    assign rs1 = instr[19:15];//с 15 по 19 бит адрес регистра источника 1
    assign rs2 = instr[24:20];//с 20 по 24 бит адрес регистра источника 2
    assign funct7 = instr[31:25];
    assign imm = { {21{instr[31]}}, instr[30:20] }; //формируемое поле //непосредственных значений Immediate (I-Type)
endmodule
Листинг 10.6.

На рисунке 10.32 приведен вид RTL созданного модуля.


Рис. 10.32.

Если раскрыть модуль InstructionDecoder, то можно наблюдать разветвление эквивалентное разветвителю, приведенному на рисунке 10.12 (рисунок 10.33).

Вячеслав Сагитов
Вячеслав Сагитов

Здравствуйте! Прошел курс, а где экзамен? Как сертификат получить? Без экзамена?