Опубликован: 19.04.2025 | Доступ: свободный | Студентов: 1 / 0 | Длительность: 07:05:00
Лекция 7:
Конвейеризированное процессорное ядро
В случае опознавания перехода необходимо, чтобы команды, уже попавшие в конвейер, игнорировались. Суммирующий сигнал pipe_rst для дешифратора команд объединятся по "or" из несколки сигналов, чтобы охватить "заранее" эффекты от перехода.
rv_desh desh( // instruction decoder .inst(r2l2_iw), .opcode(l2r3_op), .rs1(l2r3_rs1), .rs1_en(), .rs2(l2r3_rs2), .rs2_en(), .rd(l2r3_rd), .rd_wr(l2r3_rd_wr), .funct3(l2r3_fn3), .f3_en(), .funct7(l2r3_fn7), .f7_en(), .mem_en(), .mem_wr(l2r3_mem_wr), .csr_en(), .csr_wr(l2r3_csr_wr), .pipe_rst(r2l2_pipe_rst | l3r4_PC_load | r1l1_pipe_rst), .pc_load() );
Финальная структура процессора представлена на рис.7.14
Временные диаграммы приведены на рис.7.15 - видно, что блокирование выполнения операций предыдущих этапов конвейера, равно как и переход - работают штатно.
Финальный код процессорного ядра:
`include "rv_pc.v"
`include "rv_mem.v"
`include "rv_desh.v"
`include "rv_imm.v"
`include "rv_reg_file_tst.v"
`include "rv_ops_mux.v"
`include "rv_cmp.v"
`include "rv_alu_v.v"
`include "rv_rez_mux.v"
`include "rv_csr.v"
`include "rv_r_reg.v"
`include "rv_ring_reg.v"
module rv_cpu_top
#(
parameter DATA_WIDTH=32,
parameter ADDR_WIDTH=32
)
( input clk,
input rst,
// input [(ADDR_WIDTH-1):0] Data_In,
output[(DATA_WIDTH-1):0] Data_out
);
// CPU modules
///*
wire [6:0] en_level;
rv_ring_reg ring_reg(
.clk(clk),
.rst_n(rst),
.L_en(en_level)
);
//*/
// L0_R1
wire [31:0]l0r1_PC;
wire [31:0]l0r1_PCplus;
wire [31:0]r1l1_PC;
wire [31:0]r1l1_PCplus;
rv_pc pc( // programm counter
.clk(clk),
.rst_n(rst),
.en(1'b1),
.pc_load(l3r4_PC_load),
.pc_next(Rez),
.pc(l0r1_PC),
.pc_plus(l0r1_PCplus)
);
wire [255:0] r1_in;
assign r1_in = {l3r4_PC_load, l0r1_PC, l0r1_PCplus, 191'h0};
wire [255:0] r1_out;
wire [190:0] r1_null;
assign {r1l1_pipe_rst, r1l1_PC, r1l1_PCplus, r1_null} = r1_out;
rv_r_reg R1(
.clk(clk),
.rst_n(rst),
.en(1'b1),
.r_in(r1_in),
.r_out(r1_out)
);
// R1_L1
wire [31:0] l1r2_iw;
wire [31:0] l1r2_PC;
wire [31:0] l1r2_PCplus;
rv_mem mem( // system memory
.clk(clk),
//.i_addr(32'h0), //(r1l1_PC),
.i_addr(r1l1_PC>>2),
.code_out(l1r2_iw),
.d_addr(Rez>>2),
.d_out(Mem_data),
.d_in(Rs2_reg),
.we(r3l3_mem_wr),
.en(1'b1)
);
// L1_R2
wire [31:0]r2l2_iw;
wire [31:0]r2l2_PC;
wire [31:0]r2l2_PCplus;
wire [255:0] r2_in;
wire [255:0] r2_out;
//assign r2_in = {l1r2_iw, r1l1_PC, r1l1_PCplus, 160'h0};
//wire [159:0] r2_null;
//assign {r2l2_iw, r2l2_PC, r2l2_PCplus, r2_null} = r2_out;
//assign r2_in = {l3r4_PC_load, l1r2_iw, r1l1_PC, r1l1_PCplus, 159'h0};
assign r2_in = {r1l1_pipe_rst, l1r2_iw, r1l1_PC, r1l1_PCplus, 159'h0};
wire [158:0] r2_null;
assign {r2l2_pipe_rst, r2l2_iw, r2l2_PC, r2l2_PCplus, r2_null} = r2_out;
rv_r_reg R2(
.clk(clk),
.rst_n(rst),
.en(1'b1),
.r_in(r2_in),
.r_out(r2_out)
);
// L2_R3
wire [4:0] l2r3_rs1;
wire [4:0] l2r3_rs2;
wire [6:0] l2r3_op;
wire [2:0] l2r3_fn3;
wire [6:0] l2r3_fn7;
wire [4:0] l2r3_rd;
wire l2r3_rd_wr;
wire l2r3_mem_wr;
wire l2r3_csr_wr;
wire [31:0] l2r3_imm;
wire [31:0] l2r3_PC;
wire [31:0] l2r3_PCplus;
rv_desh desh( // instruction decoder
.inst(r2l2_iw),
.opcode(l2r3_op),
.rs1(l2r3_rs1),
.rs1_en(),
.rs2(l2r3_rs2),
.rs2_en(),
.rd(l2r3_rd),
.rd_wr(l2r3_rd_wr),
.funct3(l2r3_fn3),
.f3_en(),
.funct7(l2r3_fn7),
.f7_en(),
.mem_en(),
.mem_wr(l2r3_mem_wr),
.csr_en(),
.csr_wr(l2r3_csr_wr),
.pipe_rst(r2l2_pipe_rst | l3r4_PC_load | r1l1_pipe_rst),
.pc_load()
);
rv_imm immed( // immediate decoder
.inst(r2l2_iw),
.imm(l2r3_imm)
);
wire [4:0] r3l3_rs1;
wire [4:0] r3l3_rs2;
wire [6:0] r3l3_op;
wire [2:0] r3l3_fn3;
wire [6:0] r3l3_fn7;
wire [4:0] r3l3_rd;
wire r3l3_rd_wr;
wire r3l3_mem_wr;
wire r3l3_csr_wr;
wire [31:0] r3l3_imm;
wire [31:0] r3l3_PC;
wire [31:0] r3l3_PCplus;
wire [255:0] r3_in;
wire [255:0] r3_out;
assign r3_in = {l2r3_rs1, l2r3_rs2, l2r3_op, l2r3_fn3, l2r3_fn7, l2r3_rd, l2r3_rd_wr,
l2r3_mem_wr, l2r3_csr_wr, l2r3_imm, r2l2_PC, r2l2_PCplus, 125'h0};
wire [124:0] r3_null;
assign {r3l3_rs1, r3l3_rs2, r3l3_op, r3l3_fn3, r3l3_fn7, r3l3_rd, r3l3_rd_wr,
r3l3_mem_wr, r3l3_csr_wr, r3l3_imm, r3l3_PC, r3l3_PCplus, r3_null} = r3_out;
rv_r_reg R3(
.clk(clk),
.rst_n(rst),
.en(1'b1),
.r_in(r3_in),
.r_out(r3_out)
);
wire [31:0] Rs1_reg;
wire [31:0] Rs2_reg;
wire [31:0] CSR_mux;
rv_reg_file reg_file( // register's file
.clk(~clk),
.rs1(r3l3_rs1),
.rs2(r3l3_rs2),
.rd(r3l3_rd),
.Rs1_out(Rs1_reg),
.Rs2_out(Rs2_reg),
.Rd_input(Rd_reg),
.we(r3l3_rd_wr),
.en(1'b1)
);
rv_csr csr(
.clk(~clk),
.csr_addr(r3l3_imm[11:0]),
.csr_in(Rez),
.csr_out(CSR_mux),
.csr_wr(r3l3_csr_wr),
.en(1'b1)
);
wire [31:0] Op1;
wire [31:0] Op2;
rv_ops_mux ops_mux(
.opcode(r3l3_op),
.funct3(r3l3_fn3),
.funct7(r3l3_fn7),
.Rs1(Rs1_reg),
.Rs2(Rs2_reg),
.imm(r3l3_imm),
.PC(r3l3_PC),
.CSR(CSR_mux),
.Op1(Op1),
.Op2(Op2)
);
rv_cmp cmp(
.opcode(r3l3_op),
.funct3(r3l3_fn3),
.Rs1(Rs1_reg),
.Rs2(Rs2_reg),
.pc_new(l3r4_PC_load)
);
wire [31:0] Rez;
wire [31:0] Rd_reg;
wire [31:0] Mem_data;
rv_alu_v alu_v(
.opcode(r3l3_op),
.funct3(r3l3_fn3),
.funct7(r3l3_fn7),
.Op1(Op1),
.Op2(Op2),
.Rez(Rez)
);
rv_rez_mux rez_mux(
.opcode(r3l3_op),
.funct3(r3l3_fn3),
.funct7(r3l3_fn7),
.Rez(Rez),
.Pc_plus(r3l3_PCplus),
.Mem_data(Mem_data),
.Imm(r3l3_imm),
.Rd(Rd_reg)
);
wire r4l4_PC_load;
wire [31:0] r4l4_Rez;
wire [255:0] r4_in;
wire [255:0] r4_out;
assign r4_in = {Rez, l3r4_PC_load, 223'h0};
wire [222:0] r4_null;
assign {r4l4_Rez, r4l4_PC_load, r4_null} = r4_out;
rv_r_reg R4(
.clk(clk),
.rst_n(rst),
.en(1'b1),
.r_in(r4_in),
.r_out(r4_out)
);
endmodule

