master
parent
468beb8bf8
commit
87310d1cb3
@ -0,0 +1,13 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 加法器
|
||||
module adder #(
|
||||
parameter WIDTH = 8
|
||||
)(
|
||||
input logic [WIDTH-1:0] a, b,
|
||||
output logic [WIDTH-1:0] y
|
||||
);
|
||||
|
||||
// add your adder logic here
|
||||
assign y = a + b;
|
||||
|
||||
endmodule
|
@ -0,0 +1,41 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 算数逻辑单元
|
||||
module alu #(
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter OPCODE_LENGTH = 4
|
||||
)(
|
||||
input logic[DATA_WIDTH - 1 : 0] operand_a,
|
||||
input logic[DATA_WIDTH - 1 : 0] operand_b,
|
||||
input logic[OPCODE_LENGTH - 1 : 0] alu_ctrl, // Operation
|
||||
output logic[DATA_WIDTH - 1 : 0] alu_result,
|
||||
output logic zero
|
||||
);
|
||||
|
||||
// add your code here.
|
||||
logic [31:0] s;
|
||||
logic signed [31:0] signed_s, signed_operand_a, signed_operand_b;
|
||||
assign signed_operand_a = $signed(operand_a);
|
||||
assign signed_operand_b = $signed(operand_b);
|
||||
assign signed_s = $signed(signed_operand_a - signed_operand_b);
|
||||
assign s = operand_a - operand_b;
|
||||
assign zero = (s == 32'b0)? 1'b1 : 1'b0;
|
||||
always_comb
|
||||
case (alu_ctrl)
|
||||
4'b0000: alu_result = operand_a + operand_b; // add, jalr
|
||||
4'b0001: alu_result = operand_a - operand_b; // sub
|
||||
4'b0010: alu_result = operand_a | operand_b; // or
|
||||
4'b0011: alu_result = operand_a & operand_b; // and
|
||||
4'b0100: alu_result = {31'b0, signed_s[31]}; // slt
|
||||
4'b0101: alu_result = (operand_a == operand_b)? 32'b1 : 32'b0; // beq
|
||||
4'b0110: alu_result = (operand_a != operand_b)? 32'b1 : 32'b0; // bne
|
||||
4'b0111: alu_result = (signed_operand_a < signed_operand_b)? 32'b1 : 32'b0; // blt
|
||||
4'b1000: alu_result = (signed_operand_a >= signed_operand_b)? 32'b1 : 32'b0; // bge
|
||||
4'b1001: alu_result = (operand_a < operand_b)? 32'b1 : 32'b0; // bltu
|
||||
4'b1010: alu_result = (operand_a >= operand_b)? 32'b1 : 32'b0; // bgeu
|
||||
4'b1011: alu_result = 32'b1; // jal
|
||||
4'b1100: alu_result = operand_a ^ operand_b; // xor
|
||||
default: alu_result = 32'b0;
|
||||
endcase
|
||||
|
||||
endmodule
|
||||
|
@ -0,0 +1,41 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 算数逻辑单元控制器
|
||||
module ALU_Controller (
|
||||
input logic [1:0] alu_op, // 2-bit opcode field from the Proc_controller
|
||||
input logic [6:0] funct7, // insn[31:25]
|
||||
input logic [2:0] funct3, // insn[14:12]
|
||||
output logic [3:0] operation // operation selection for ALU
|
||||
);
|
||||
|
||||
// add your code here.
|
||||
always_comb
|
||||
case (alu_op)
|
||||
2'b00: operation = 4'b0000; // lw, sw
|
||||
2'b01:
|
||||
case (funct3)
|
||||
3'b000: operation = 4'b0101; // beq
|
||||
3'b001: operation = 4'b0110; // bne
|
||||
3'b100: operation = 4'b0111; // blt
|
||||
3'b101: operation = 4'b1000; // bge
|
||||
3'b110: operation = 4'b1001; // bltu
|
||||
3'b111: operation = 4'b1010; // bgeu
|
||||
default: operation = 4'b0000;
|
||||
endcase
|
||||
2'b10:
|
||||
case (funct3)
|
||||
3'b000:
|
||||
case (funct7)
|
||||
7'b0100000: operation = 4'b0001; // sub (存在addi的立即数恰好满足此情况的bug)
|
||||
default: operation = 4'b0000; // add, addi
|
||||
endcase
|
||||
3'b100: operation = 4'b1100; // xor
|
||||
3'b110: operation = 4'b0010; // or, ori
|
||||
3'b111: operation = 4'b0011; // and, andi
|
||||
3'b010: operation = 4'b0100; // slt
|
||||
default: operation = 4'b0000;
|
||||
endcase
|
||||
2'b11: operation = 4'b1011; // jal
|
||||
default: operation = 4'b0000;
|
||||
endcase
|
||||
|
||||
endmodule
|
@ -0,0 +1,30 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 跳转单元
|
||||
module BranchUnit #(
|
||||
parameter PC_W = 9
|
||||
)(
|
||||
input logic [PC_W - 1:0] cur_pc,
|
||||
input logic [31:0] imm,
|
||||
input logic jalr_sel,
|
||||
input logic branch_taken, // Branch
|
||||
input logic [31:0] alu_result,
|
||||
output logic [31:0] pc_plus_imm, // PC + imm
|
||||
output logic [31:0] pc_plus_4, // PC + 4
|
||||
output logic [31:0] branch_target, // BrPC
|
||||
output logic pc_sel
|
||||
);
|
||||
|
||||
logic [31:0] pc;
|
||||
assign pc = {23'b0, cur_pc};
|
||||
always_comb
|
||||
begin
|
||||
pc_plus_4 = pc + 32'd4;
|
||||
pc_plus_imm = pc + imm;
|
||||
pc_sel = jalr_sel | (branch_taken & alu_result[0]);
|
||||
if (jalr_sel == 1'b1)
|
||||
branch_target = alu_result & 32'hfffffffe; // jalr
|
||||
else
|
||||
branch_target = pc + (imm << 1); // jal and beq
|
||||
end
|
||||
|
||||
endmodule
|
@ -0,0 +1,38 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 数据存储器
|
||||
module datamemory#(
|
||||
parameter ADDR_WIDTH = 12,
|
||||
parameter DATA_WIDTH = 32
|
||||
)(
|
||||
input logic clock,
|
||||
input logic read_en,
|
||||
input logic write_en,
|
||||
input logic [ADDR_WIDTH -1 : 0] address, // read/write address
|
||||
input logic [DATA_WIDTH -1 : 0] data_in, // write Data
|
||||
input logic [2:0] funct3, // insn[14:12]
|
||||
output logic [DATA_WIDTH -1 : 0] data_out // read data
|
||||
);
|
||||
|
||||
logic [DATA_WIDTH - 1 : 0] MEM[(2**(ADDR_WIDTH - 2)) - 1 : 0];
|
||||
always @(posedge clock)
|
||||
if (write_en) // sw etc.
|
||||
case (funct3)
|
||||
3'b000: MEM[address[ADDR_WIDTH - 1 : 2]][7:0] <= data_in; // sb
|
||||
3'b001: MEM[address[ADDR_WIDTH - 1 : 2]][15:0] <= data_in; // sh
|
||||
3'b010: MEM[address[ADDR_WIDTH - 1 : 2]] <= data_in; // sw
|
||||
default: MEM[address[ADDR_WIDTH - 1 : 2]] <= data_in; // 默认sw
|
||||
endcase
|
||||
|
||||
always_comb
|
||||
if (read_en) // lw etc.
|
||||
case (funct3)
|
||||
3'b000: data_out = {{24{MEM[address[ADDR_WIDTH - 1 : 2]][7]}}, MEM[address[ADDR_WIDTH - 1 : 2]][7:0]}; // lb
|
||||
3'b001: data_out = {{16{MEM[address[ADDR_WIDTH - 1 : 2]][15]}}, MEM[address[ADDR_WIDTH - 1 : 2]][15:0]}; // lh
|
||||
3'b010: data_out = MEM[address[ADDR_WIDTH - 1 : 2]]; // lw
|
||||
3'b100: data_out = {24'b0,MEM[address[ADDR_WIDTH - 1 : 2]][7:0]}; // lbu
|
||||
3'b101: data_out = {16'b0,MEM[address[ADDR_WIDTH - 1 : 2]][15:0]}; // lhu
|
||||
default: data_out = MEM[address[ADDR_WIDTH - 1 : 2]]; // 默认lw
|
||||
endcase
|
||||
|
||||
endmodule
|
||||
|
@ -0,0 +1,270 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 数据通路
|
||||
`include "pipeline_regs.sv"
|
||||
import Pipe_Buf_Reg_PKG::*;
|
||||
|
||||
module Datapath #(
|
||||
parameter PC_W = 9, // Program Counter
|
||||
parameter INS_W = 32, // Instruction Width
|
||||
parameter DATA_W = 32, // Data WriteData
|
||||
parameter DM_ADDRESS = 9, // Data Memory Address
|
||||
parameter ALU_CC_W = 4 // ALU Control Code Width
|
||||
)(
|
||||
input logic clock,
|
||||
input logic reset, // reset , sets the PC to zero
|
||||
input logic reg_write_en, // Register file writing enable
|
||||
input logic MemtoReg, // Memory or ALU MUX
|
||||
input logic alu_src, // Register file or Immediate MUX
|
||||
input logic mem_write_en, // Memroy Writing Enable
|
||||
input logic mem_read_en, // Memroy Reading Enable
|
||||
input logic branch_taken, // Branch Enable
|
||||
input logic jalr_sel, // Jalr Mux Select
|
||||
input logic [1:0] alu_op,
|
||||
input logic [1:0] RWSel, // Mux4to1 Select
|
||||
input logic [ALU_CC_W -1:0] alu_cc, // ALU Control Code ( input of the ALU )
|
||||
output logic [6:0] opcode,
|
||||
output logic [6:0] funct7,
|
||||
output logic [2:0] funct3,
|
||||
output logic [1:0] aluop_current,
|
||||
output logic [DATA_W-1:0] wb_data // data write back to register
|
||||
);
|
||||
|
||||
// ====================================================================================
|
||||
// Instruction Fetch (IF)
|
||||
// ====================================================================================
|
||||
//
|
||||
// peripheral logic here.
|
||||
//
|
||||
logic BrFlush, stall;
|
||||
logic [31:0] PC_mux_result, PC, PCplus4, BrPC, instr;
|
||||
flipflop #(32) PC_unit(.clock(clock), .reset(reset), .d(PC_mux_result), .stall(stall), .q(PC));
|
||||
mux2 PC_mux(.d0(PCplus4), .d1(BrPC), .s(BrFlush), .y(PC_mux_result));
|
||||
adder #(32) PC_adder(.a(PC), .b(32'd4), .y(PCplus4));
|
||||
//
|
||||
// add your instruction memory
|
||||
//
|
||||
Insn_mem IM(.read_address(PC[PC_W - 1 : 0]), .insn(instr));
|
||||
// ====================================================================================
|
||||
// End of Instruction Fetch (IF)
|
||||
// ====================================================================================
|
||||
if_id_reg RegA;
|
||||
id_ex_reg RegB;
|
||||
ex_mem_reg RegC;
|
||||
mem_wb_reg RegD;
|
||||
|
||||
always @(posedge clock, posedge reset)
|
||||
begin
|
||||
// add your logic here to update the IF_ID_Register
|
||||
if (BrFlush | reset)
|
||||
begin
|
||||
RegA.Curr_Pc <= 9'b0;
|
||||
RegA.Curr_Instr <= 32'b0;
|
||||
end
|
||||
else if (!stall)
|
||||
begin
|
||||
RegA.Curr_Pc <= PC[PC_W - 1 : 0];
|
||||
RegA.Curr_Instr <= instr;
|
||||
end
|
||||
end
|
||||
// ====================================================================================
|
||||
// Instruction Decoding (ID)
|
||||
// ====================================================================================
|
||||
//
|
||||
// peripheral logic here.
|
||||
//
|
||||
assign opcode = RegA.Curr_Instr[6:0];
|
||||
logic [31:0] rd1, rd2, ImmG;
|
||||
//
|
||||
// add your register file here.
|
||||
//
|
||||
Reg_file RF(.clock(clock), .reset(reset), .write_en(RegD.RegWrite), .write_addr(RegD.rd),
|
||||
.data_in(wb_data), .read_addr1(RegA.Curr_Instr[19:15]),
|
||||
.read_addr2(RegA.Curr_Instr[24:20]), .data_out1(rd1), .data_out2(rd2));
|
||||
//
|
||||
// add your immediate generator here
|
||||
//
|
||||
Imm_gen Imm_Gen(.inst_code(RegA.Curr_Instr), .imm_out(ImmG));
|
||||
// ====================================================================================
|
||||
// End of Instruction Decoding (ID)
|
||||
// ====================================================================================
|
||||
always @(posedge clock, posedge reset)
|
||||
begin
|
||||
// add your logic here to update the ID_EX_Register
|
||||
if (BrFlush | reset | stall)
|
||||
begin
|
||||
RegB.ALUSrc <= 1'b0;
|
||||
RegB.MemtoReg <= 1'b0;
|
||||
RegB.RegWrite <= 1'b0;
|
||||
RegB.MemRead <= 1'b0;
|
||||
RegB.MemWrite <= 1'b0;
|
||||
RegB.ALUOp <= 2'b0;
|
||||
RegB.Branch <= 1'b0;
|
||||
RegB.JalrSel <= 1'b0;
|
||||
RegB.RWSel <= 2'b0;
|
||||
RegB.Curr_Pc <= 9'b0;
|
||||
RegB.RD_One <= 32'b0;
|
||||
RegB.RD_Two <= 32'b0;
|
||||
RegB.RS_One <= 5'b0;
|
||||
RegB.RS_Two <= 5'b0;
|
||||
RegB.rd <= 5'b0;
|
||||
RegB.ImmG <= 32'b0;
|
||||
RegB.func3 <= 3'b0;
|
||||
RegB.func7 <= 7'b0;
|
||||
RegB.Curr_Instr <= 32'b0;
|
||||
end
|
||||
else if (!stall)
|
||||
begin
|
||||
RegB.ALUSrc <= alu_src;
|
||||
RegB.MemtoReg <= MemtoReg;
|
||||
RegB.RegWrite <= reg_write_en;
|
||||
RegB.MemRead <= mem_read_en;
|
||||
RegB.MemWrite <= mem_write_en;
|
||||
RegB.ALUOp <= alu_op;
|
||||
RegB.Branch <= branch_taken;
|
||||
RegB.JalrSel <= jalr_sel;
|
||||
RegB.RWSel <= RWSel;
|
||||
RegB.Curr_Pc <= RegA.Curr_Pc;
|
||||
RegB.RD_One <= rd1;
|
||||
RegB.RD_Two <= rd2;
|
||||
RegB.RS_One <= RegA.Curr_Instr[19:15];
|
||||
RegB.RS_Two <= RegA.Curr_Instr[24:20];
|
||||
RegB.rd <= RegA.Curr_Instr[11:7];
|
||||
RegB.ImmG <= ImmG;
|
||||
RegB.func3 <= RegA.Curr_Instr[14:12];
|
||||
RegB.func7 <= RegA.Curr_Instr[31:25];
|
||||
RegB.Curr_Instr <= RegA.Curr_Instr;
|
||||
end
|
||||
end
|
||||
// ====================================================================================
|
||||
// Execution (EX)
|
||||
// ====================================================================================
|
||||
//
|
||||
// add your ALU, branch unit and with peripheral logic here
|
||||
//
|
||||
logic [31:0] FA_mux_result, FB_mux_result, ALU_result, PCplusImm, PCplus4_EX, src_mux_result, lui_mux_resultA, lui_mux_resultB;
|
||||
logic [1:0] ForwardA, ForwardB;
|
||||
logic zero, if_lui1, if_lui2;
|
||||
assign aluop_current = RegB.ALUOp;
|
||||
assign funct3 = RegB.func3;
|
||||
assign funct7 = RegB.func7;
|
||||
assign if_lui = (RegC.Curr_Instr[6:0] == 7'b0110111)? 1'b1 : 1'b0;
|
||||
alu ALU(.operand_a(FA_mux_result), .operand_b(src_mux_result), .alu_ctrl(alu_cc), .alu_result(ALU_result), .zero(zero));
|
||||
BranchUnit Branch_unit(.cur_pc(RegB.Curr_Pc), .imm(RegB.ImmG), .jalr_sel(RegB.JalrSel), .branch_taken(RegB.Branch),
|
||||
.alu_result(ALU_result), .pc_plus_imm(PCplusImm), .pc_plus_4(PCplus4_EX), .branch_target(BrPC), .pc_sel(BrFlush));
|
||||
mux4 FA_mux(.d00(RegB.RD_One), .d01(lui_mux_resultA), .d10(wb_data), .d11(32'b0), .s(ForwardA), .y(FA_mux_result));
|
||||
mux4 FB_mux(.d00(RegB.RD_Two), .d01(lui_mux_resultB), .d10(wb_data), .d11(32'b0), .s(ForwardB), .y(FB_mux_result));
|
||||
mux2 src_mux(.d0(FB_mux_result), .d1(RegB.ImmG), .s(RegB.ALUSrc), .y(src_mux_result));
|
||||
mux2 lui_muxA(.d0(RegC.Alu_Result), .d1(RegC.Imm_Out), .s(if_lui), .y(lui_mux_resultA));
|
||||
mux2 lui_muxB(.d0(RegC.Alu_Result), .d1(RegC.Imm_Out), .s(if_lui), .y(lui_mux_resultB));
|
||||
// ====================================================================================
|
||||
// End of Execution (EX)
|
||||
// ====================================================================================
|
||||
always @(posedge clock, posedge reset)
|
||||
begin
|
||||
// add your logic here to update the EX_MEM_Register
|
||||
if(reset)
|
||||
begin
|
||||
RegC.RegWrite <= 1'b0;
|
||||
RegC.MemtoReg <= 1'b0;
|
||||
RegC.MemRead <= 1'b0;
|
||||
RegC.MemWrite <= 1'b0;
|
||||
RegC.RWSel <= 2'b0;
|
||||
RegC.Pc_Imm <= 32'b0;
|
||||
RegC.Pc_Four <= 32'b0;
|
||||
RegC.Imm_Out <= 32'b0;
|
||||
RegC.Alu_Result <= 32'b0;
|
||||
RegC.RD_Two <= 32'b0;
|
||||
RegC.rd <= 5'b0;
|
||||
RegC.func3 <= 3'b0;
|
||||
RegC.func7 <= 7'b0;
|
||||
RegC.Curr_Instr <= 32'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
RegC.RegWrite <= RegB.RegWrite;
|
||||
RegC.MemtoReg <= RegB.MemtoReg;
|
||||
RegC.MemRead <= RegB.MemRead;
|
||||
RegC.MemWrite <= RegB.MemWrite;
|
||||
RegC.RWSel <= RegB.RWSel;
|
||||
RegC.Pc_Imm <= PCplusImm;
|
||||
RegC.Pc_Four <= PCplus4_EX;
|
||||
RegC.Imm_Out <= RegB.ImmG; // lui
|
||||
RegC.Alu_Result <= ALU_result;
|
||||
RegC.RD_Two <= FB_mux_result;
|
||||
RegC.rd <= RegB.rd;
|
||||
RegC.func3 <= RegB.func3;
|
||||
RegC.func7 <= RegB.func7;
|
||||
RegC.Curr_Instr <= RegB.Curr_Instr;
|
||||
end
|
||||
end
|
||||
// ====================================================================================
|
||||
// Memory Access (MEM)
|
||||
// ====================================================================================
|
||||
// add your data memory here.
|
||||
logic [31:0] ReadData;
|
||||
datamemory DM(.clock(clock), .read_en(RegC.MemRead), .write_en(RegC.MemWrite),
|
||||
.address(RegC.Alu_Result[11:0]), .data_in(RegC.RD_Two), .funct3(RegC.func3), .data_out(ReadData));
|
||||
// ====================================================================================
|
||||
// End of Memory Access (MEM)
|
||||
// ====================================================================================
|
||||
always @(posedge clock)
|
||||
begin
|
||||
// add your logic here to update the MEM_WB_Register
|
||||
if(reset)
|
||||
begin
|
||||
RegD.RegWrite <= 1'b0;
|
||||
RegD.MemtoReg <= 1'b0;
|
||||
RegD.RWSel <= 2'b0;
|
||||
RegD.Pc_Imm <= 32'b0;
|
||||
RegD.Pc_Four <= 32'b0;
|
||||
RegD.Imm_Out <= 32'b0;
|
||||
RegD.Alu_Result <= 32'b0;
|
||||
RegD.MemReadData <= 32'b0;
|
||||
RegD.rd <= 5'b0;
|
||||
RegD.Curr_Instr <= 5'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
RegD.RegWrite <= RegC.RegWrite;
|
||||
RegD.MemtoReg <= RegC.MemtoReg;
|
||||
RegD.RWSel <= RegC.RWSel;
|
||||
RegD.Pc_Imm <= RegC.Pc_Imm;
|
||||
RegD.Pc_Four <= RegC.Pc_Four;
|
||||
RegD.Imm_Out <= RegC.Imm_Out;
|
||||
RegD.Alu_Result <= RegC.Alu_Result;
|
||||
RegD.MemReadData <= ReadData;
|
||||
RegD.rd <= RegC.rd;
|
||||
RegD.Curr_Instr <= RegC.Curr_Instr;
|
||||
end
|
||||
end
|
||||
// ====================================================================================
|
||||
// Write Back (WB)
|
||||
// ====================================================================================
|
||||
//
|
||||
// add your write back logic here.
|
||||
//
|
||||
logic [31:0] res_mux_result;
|
||||
mux2 res_mux(.d0(RegD.Alu_Result), .d1(RegD.MemReadData), .s(RegD.MemtoReg), .y(res_mux_result));
|
||||
mux4 wrs_mux(.d00(res_mux_result), .d01(RegD.Pc_Four), .d10(RegD.Imm_Out), .d11(RegD.Pc_Imm), .s(RegD.RWSel), .y(wb_data));
|
||||
// ====================================================================================
|
||||
// End of Write Back (WB)
|
||||
// ====================================================================================
|
||||
// ====================================================================================
|
||||
// other logic
|
||||
// ====================================================================================
|
||||
//
|
||||
// add your hazard detection logic here
|
||||
//
|
||||
Hazard_detector hazard_unit(.clock(clock), .reset(reset), .if_id_rs1(RegA.Curr_Instr[19:15]), .if_id_rs2(RegA.Curr_Instr[24:20]),
|
||||
.id_ex_rd(RegB.rd), .id_ex_memread(RegB.MemRead), .stall(stall));
|
||||
//
|
||||
// add your forwarding logic here
|
||||
//
|
||||
ForwardingUnit forwarding_unit(.rs1(RegB.RS_One), .rs2(RegB.RS_Two), .ex_mem_rd(RegC.rd), .mem_wb_rd(RegD.rd),
|
||||
.ex_mem_regwrite(RegC.RegWrite), .mem_wb_regwrite(RegD.RegWrite), .forward_a(ForwardA), .forward_b(ForwardB));
|
||||
//
|
||||
// possible extra code
|
||||
//
|
||||
|
||||
|
||||
endmodule
|
@ -0,0 +1,32 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 数据定向处理单元
|
||||
module ForwardingUnit (
|
||||
input logic [4:0] rs1,
|
||||
input logic [4:0] rs2,
|
||||
input logic [4:0] ex_mem_rd,
|
||||
input logic [4:0] mem_wb_rd,
|
||||
input logic ex_mem_regwrite,
|
||||
input logic mem_wb_regwrite,
|
||||
output logic [1:0] forward_a,
|
||||
output logic [1:0] forward_b
|
||||
);
|
||||
|
||||
// define your forwarding logic here.
|
||||
always_comb
|
||||
begin
|
||||
if ((rs1 != 0) && (rs1 == ex_mem_rd) && ex_mem_regwrite)
|
||||
forward_a = 2'b01;
|
||||
else if ((rs1 != 0) && (rs1 == mem_wb_rd) && mem_wb_regwrite)
|
||||
forward_a = 2'b10;
|
||||
else
|
||||
forward_a = 2'b00;
|
||||
|
||||
if ((rs2 != 0) && (rs2 == ex_mem_rd) && ex_mem_regwrite)
|
||||
forward_b = 2'b01;
|
||||
else if ((rs2 != 0) && (rs2 == mem_wb_rd) && mem_wb_regwrite)
|
||||
forward_b = 2'b10;
|
||||
else
|
||||
forward_b = 2'b00;
|
||||
end
|
||||
|
||||
endmodule
|
@ -0,0 +1,35 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 冒险探测器(阻塞生成器)
|
||||
module Hazard_detector (
|
||||
input logic clock,
|
||||
input logic reset,
|
||||
input logic [4:0] if_id_rs1,
|
||||
input logic [4:0] if_id_rs2,
|
||||
input logic [4:0] id_ex_rd,
|
||||
input logic id_ex_memread,
|
||||
output logic stall
|
||||
);
|
||||
|
||||
// define your hazard detection logic here
|
||||
logic [1:0] counter;
|
||||
always @(negedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
stall <= 1'b0;
|
||||
counter <= 2'b00;
|
||||
end
|
||||
else
|
||||
begin
|
||||
stall <= (id_ex_memread && ((id_ex_rd == if_id_rs1) || (id_ex_rd == if_id_rs2)));
|
||||
if (stall == 1'b1)
|
||||
counter <= counter + 2'b01;
|
||||
if (counter == 2'b10)
|
||||
begin
|
||||
counter <= 2'b00;
|
||||
stall <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -0,0 +1,23 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 立即数扩展
|
||||
module Imm_gen(
|
||||
input logic [31:0] inst_code,
|
||||
output logic [31:0] imm_out
|
||||
);
|
||||
|
||||
// add your immediate extension logic here.
|
||||
logic [6:0] test;
|
||||
assign test = inst_code[6:0];
|
||||
always_comb
|
||||
case (test)
|
||||
7'b0010011: imm_out = {{20{inst_code[31]}}, inst_code[31:20]}; // andi, ori, addi
|
||||
7'b0000011: imm_out = {{20{inst_code[31]}}, inst_code[31:20]}; // lb, lh, lw, lbu, lhu
|
||||
7'b0100011: imm_out = {{20{inst_code[31]}}, inst_code[31:25], inst_code[11:7]}; // sb, sh, sw
|
||||
7'b1100011: imm_out = {{20{inst_code[31]}}, inst_code[31], inst_code[7], inst_code[30:25], inst_code[11:8]}; // beq, bne, blt, bge, bltu, bgeu
|
||||
7'b1101111: imm_out = {{12{inst_code[31]}}, inst_code[31], inst_code[19:12], inst_code[20], inst_code[30:21]}; // jal
|
||||
7'b1100111: imm_out = {{20{inst_code[31]}}, inst_code[31:20]}; // jalr
|
||||
7'b0110111: imm_out = {inst_code[31:12], 12'b0}; // lui
|
||||
default: imm_out = 32'd0;
|
||||
endcase
|
||||
|
||||
endmodule
|
@ -0,0 +1,13 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 二端口多路选择器
|
||||
module mux2 #(
|
||||
parameter WIDTH = 32
|
||||
)(
|
||||
input logic [WIDTH-1:0] d0, d1,
|
||||
input logic s,
|
||||
output logic [WIDTH-1:0] y
|
||||
);
|
||||
|
||||
assign y = s ? d1 : d0;
|
||||
|
||||
endmodule
|
@ -0,0 +1,13 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 四端口多路选择器
|
||||
module mux4 #(
|
||||
parameter WIDTH = 32
|
||||
)(
|
||||
input logic [WIDTH-1:0] d00, d01, d10, d11,
|
||||
input logic [1:0] s,
|
||||
output logic [WIDTH-1:0] y
|
||||
);
|
||||
|
||||
assign y = (s==2'b11) ? d11 : (s==2'b10) ? d10 : (s==2'b01) ? d01 : d00;
|
||||
|
||||
endmodule
|
@ -0,0 +1,63 @@
|
||||
//
|
||||
package Pipe_Buf_Reg_PKG;
|
||||
// Reg A
|
||||
typedef struct packed{
|
||||
logic [8:0] Curr_Pc;
|
||||
logic [31:0] Curr_Instr;
|
||||
} if_id_reg;
|
||||
|
||||
// Reg B
|
||||
typedef struct packed{
|
||||
logic ALUSrc;
|
||||
logic MemtoReg;
|
||||
logic RegWrite;
|
||||
logic MemRead;
|
||||
logic MemWrite;
|
||||
logic [1:0] ALUOp;
|
||||
logic Branch;
|
||||
logic JalrSel;
|
||||
logic [1:0] RWSel;
|
||||
logic [8:0] Curr_Pc;
|
||||
logic [31:0] RD_One;
|
||||
logic [31:0] RD_Two;
|
||||
logic [4:0] RS_One;
|
||||
logic [4:0] RS_Two;
|
||||
logic [4:0] rd;
|
||||
logic [31:0] ImmG;
|
||||
logic [2:0] func3;
|
||||
logic [6:0] func7;
|
||||
logic [31:0] Curr_Instr;
|
||||
} id_ex_reg;
|
||||
|
||||
// Reg C
|
||||
typedef struct packed{
|
||||
logic RegWrite;
|
||||
logic MemtoReg;
|
||||
logic MemRead;
|
||||
logic MemWrite;
|
||||
logic [1:0] RWSel;
|
||||
logic [31:0] Pc_Imm;
|
||||
logic [31:0] Pc_Four;
|
||||
logic [31:0] Imm_Out;
|
||||
logic [31:0] Alu_Result;
|
||||
logic [31:0] RD_Two;
|
||||
logic [4:0] rd;
|
||||
logic [2:0] func3;
|
||||
logic [6:0] func7;
|
||||
logic [31:0] Curr_Instr;
|
||||
} ex_mem_reg;
|
||||
|
||||
// Reg D
|
||||
typedef struct packed{
|
||||
logic RegWrite;
|
||||
logic MemtoReg;
|
||||
logic [1:0] RWSel;
|
||||
logic [31:0] Pc_Imm;
|
||||
logic [31:0] Pc_Four;
|
||||
logic [31:0] Imm_Out;
|
||||
logic [31:0] Alu_Result;
|
||||
logic [31:0] MemReadData;
|
||||
logic [4:0] rd;
|
||||
logic [31:0] Curr_Instr;
|
||||
} mem_wb_reg;
|
||||
endpackage
|
@ -0,0 +1,54 @@
|
||||
`timescale 1ns / 1ps
|
||||
// 寄存器文件
|
||||
module Reg_file #(
|
||||
parameter DATA_WIDTH = 32, // number of bits in each register
|
||||
parameter ADDRESS_WIDTH = 5, //number of registers = 2^ADDRESS_WIDTH
|
||||
parameter NUM_REGS = 2 ** ADDRESS_WIDTH
|
||||
)(
|
||||
// Inputs
|
||||
input clock, //clock
|
||||
input reset, //synchronous reset; reset all regs to 0 upon assertion.
|
||||
input write_en, //write enable
|
||||
input [ADDRESS_WIDTH-1:0] write_addr, //address of the register that supposed to written into
|
||||
input [DATA_WIDTH-1:0] data_in, // data that supposed to be written into the register file
|
||||
input [ADDRESS_WIDTH-1:0] read_addr1, //first address to be read from
|
||||
input [ADDRESS_WIDTH-1:0] read_addr2, //second address to be read from
|
||||
|
||||
// Outputs
|
||||
output logic [DATA_WIDTH-1:0] data_out1, //content of reg_file[read_addr1] is loaded into
|
||||
output logic [DATA_WIDTH-1:0] data_out2 //content of reg_file[read_addr2] is loaded into
|
||||
);
|
||||
|
||||
|
||||
integer i;
|
||||
|
||||
logic [DATA_WIDTH-1:0] register_file [NUM_REGS-1:0];
|
||||
integer log_file;
|
||||
initial begin
|
||||
log_file = $fopen("./reg_trace.txt", "w");
|
||||
|
||||
if (log_file)
|
||||
$display("***************************** File was opened succussfully: %s", "./test.txt");
|
||||
else
|
||||
$display("***************************** Failed to open the file: %s", "./test.txt");
|
||||
|
||||
end
|
||||
|
||||
always @( negedge clock )
|
||||
begin
|
||||
if( reset == 1'b1 )
|
||||
for (i = 0; i < NUM_REGS ; i = i + 1) begin
|
||||
register_file [i] <= 0;
|
||||
$fwrite(log_file, "r%d, 0", i);
|
||||
end
|
||||
else if( reset ==1'b0 && write_en ==1'b1 && write_addr != 0) begin
|
||||
register_file [ write_addr ] <= data_in;
|
||||
$fwrite(log_file, "r%02x, %08x\n", write_addr, data_in);
|
||||
end
|
||||
end
|
||||
|
||||
assign data_out1 = register_file[read_addr1];
|
||||
assign data_out2 = register_file[read_addr2];
|
||||
|
||||
|
||||
endmodule
|
@ -0,0 +1,25 @@
|
||||
`timescale 1ns / 1ps
|
||||
// risc-V整体模块
|
||||
module riscv #(
|
||||
parameter DATA_W = 32)
|
||||
(input logic clock, reset, // clock and reset signals
|
||||
output logic [31:0] WB_Data// The ALU_Result
|
||||
);
|
||||
|
||||
logic [6:0] opcode;
|
||||
logic ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch, JalrSel;
|
||||
logic [1:0] RWSel;
|
||||
|
||||
logic [1:0] ALUop;
|
||||
logic [1:0] ALUop_Reg;
|
||||
logic [6:0] Funct7;
|
||||
logic [2:0] Funct3;
|
||||
logic [3:0] Operation;
|
||||
|
||||
Proc_controller proc_controller(opcode, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, ALUop, Branch, JalrSel, RWSel);
|
||||
|
||||
ALU_Controller proc_alu_controller(ALUop_Reg, Funct7, Funct3, Operation);
|
||||
|
||||
Datapath proc_data_path(clock, reset, RegWrite , MemtoReg, ALUSrc , MemWrite, MemRead, Branch, JalrSel, ALUop, RWSel, Operation, opcode, Funct7, Funct3, ALUop_Reg, WB_Data);
|
||||
|
||||
endmodule
|
@ -0,0 +1,30 @@
|
||||
`timescale 1ns / 1ps
|
||||
//
|
||||
module tb_top;
|
||||
|
||||
//clock and reset signal declaration
|
||||
logic tb_clk, reset;
|
||||
logic [31:0] tb_WB_Data;
|
||||
|
||||
//clock generation
|
||||
always #10 tb_clk = ~tb_clk;
|
||||
|
||||
//reset Generation
|
||||
initial begin
|
||||
tb_clk = 0;
|
||||
reset = 1;
|
||||
#25 reset =0;
|
||||
end
|
||||
|
||||
|
||||
riscv riscV(
|
||||
.clock(tb_clk),
|
||||
.reset(reset),
|
||||
.WB_Data(tb_WB_Data)
|
||||
);
|
||||
|
||||
initial begin
|
||||
#2500;
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
Loading…
Reference in new issue