You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
12 KiB
271 lines
12 KiB
3 years ago
|
`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
|