|
Здравствуйте! Прошел курс, а где экзамен? Как сертификат получить? Без экзамена? |
Проектирование счетчика инструкций, памяти инструкций и памяти данных
Далее разместим на поле счетчик инструкций PC, АЛУ (ALU) и регистровый файл (RegFile). Проведем соединения адресных линий от счетчика к ПЗУ. Подключение осуществить с применением элемента "Разветвитель". Которому задать свойства:
- "Внешний вид" - леворукий;
- "Веерный выход" - 1;
- "Разрядность входа" - 32;
- Бит 0 - нет, Бит 1 - нет;
- Бит с 16 и до 32 - нет.
Выход АЛУ также через разветвитель подключить к входу адреса ОЗУ. Единственное изменить настройки таким образом, чтобы с ОЗУ соединялись биты со 2 по 9, что соответствует 256 ячейкам памяти.
Выход данных rs2 регистрового файла подключим к входу D ОЗУ.
Добавим на поле мультиплексор с разрядностью 32 и свойством "Выбирающие биты" 1. Вход 0 мультиплексора подключим к выходу АЛУ. Второй вход подключить к выходу D ОЗУ. Выход мультиплексора подключить к входу данных регистрового файла DataIn. Организация такой схемы как раз обусловлена тем, что сначала данные загружаются в регистры, выполняется соответствующая операция, затем данные загружаются в память. Также данные из памяти загружаются в регистры, а потом в память.
За данный процесс отвечает дешифратор инструкций и блок управления.
На рисунке 9.7 показан результат объединения счетчика инструкций PC и памяти инструкций (IMEM). На рисунке 9.8 приведена схема включения операционного блока с памятью данных.
Для проектирования регистрового файла в среде Quartus, в существующем проекте RISC_V, создать новый Verilog HDL File. Сохранить файл как PCUnit.v.
Проектируемый в целом отражает функциональную схему, приведенную на рисунке 9.1, но в него уже интегрированы входы переходов с блока управления ветвлениями, который будет рассмотрен далее. В листинге 9.1 приведен код счетчика инструкций.
module PCUnit(
input clk, // тактовый сигнал
input reset, // сигнал сброса
input branchTaken, // сигнал ветвления
input [31:0] branchAddr, // адрес для перехода при ветвлении
output reg [31:0] pc // выход счетчика
);
// Инициализация PC стартовым адресом
initial pc = 32'b0;
// анализ сигнала clk по фронту
always @(posedge clk) begin
if (reset) begin
// Установка PC в начальный адрес при сбросе
pc <= 32'b0;
end else if (branchTaken) begin
// Если присутсвует сигнал перехода то счетчик указывает на адрес branchAddr
pc <= branchAddr;
end else begin
// иначе PC увеличивается на 4
pc <= pc + 4;
end
end
endmodule
Листинг
9.1.
На рисунке 9.9 приведен вид RTL созданного модуля.
Оперативное запоминающее устройство, выполняющее функции памяти данных, создаваемая на Verilog HDL имеет аналогичные порты адреса и данных, а также входы управления записью и чтением. Для получения памяти данных в проекте создадим файл DataMemory.v и введем код из листинга 9.2.
module DataMemory (
input clk, //синхросигнал
input [31:0] addr, // шина адреса
input [31:0] writeData, //входная шина данных
input memWrite, // сигнал управления записи
input memRead, //сигнал управления чтением
output [31:0] readData //выход данных
);
reg [7:0] mem [0:255];// объем памяти равен 256 байт
// Чтение данных
assign readData = memRead ? {mem[addr+3], mem[addr+2], mem[addr+1], mem[addr]} : 32'b0;
// здесь данные как раз объединаются с применением конкатенации
// Запись данных по фронту clk
always @(posedge clk) begin
if (memWrite) begin
//здесь данные из 32-х битного слова делятся на 4 байта
mem[addr] <= writeData[7:0];
mem[addr+1] <= writeData[15:8];
mem[addr+2] <= writeData[23:16];
mem[addr+3] <= writeData[31:24];
//здесь данные из 32-х битного слова делятся на 4 байта
end
end
endmodule
Листинг
9.2.
На рисунке 9.10 приведен вид RTL созданного модуля.
Для процессора требуется описать память инструкций. На данном моменте требуется отметить, что память инструкций - обычно модуль ROM. Данный модуль содержит код, записанный заранее. Данная память может содержать код программы в виде констант с заранее определенными адресами:
always @ (addr)
case (addr)
32'h00000000: instr <= 32'b001000_00000_10000_0000000011111111;
32'h00000004: instr <= 32'b101011_00000_10000_1111000000000000;
Второй вариант применение файла инициализации, чтобы загрузить данные в модуль ROM из внешнего текстового файла. Это применяется как правило для загрузки больших таблиц кода.
Пример кода для данного метода имеет вид:
initial begin
$readmemh("rom_data.hex", rom);
End
Для первичной проверки работоспособности проектируемого процессора будет создана память инструкций, содержащая код программы непосредственно внутри модуля.
Для получения памяти инструкций в проекте создадим файл InstructionMemory.v и введем код из листинга 9.3.
module InstructionMemory(
input [31:0] addr, // шина адреса
output [31:0] instr // шина данных выхода
);
reg [31:0] mem [0:63]; // объем памяти 64 инструкции по 32 бит
initial begin
// Пример инструкций
mem[0] = 32'h00000013; // ADDI r1, r0, 0 (NOP)
mem[1] = 32'h002081B3; // ADD x3, x1, x2
mem[2] = 32'h40400013; // ADDI x1, x0, 64
end
assign instr = mem[addr[31:2]]; // Выравнивание по 4 байтам
endmodule
Листинг
9.3.
На рисунке 9.11 приведен вид RTL созданного модуля.




