1 Star 3 Fork 0

jmqian1009 / 多周期RISC-V CPU设计

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
MC_RV32Core.sv 7.33 KB
一键复制 编辑 原始数据 按行查看 历史
jmqian1009 提交于 2022-03-18 09:20 . 修复了算数右移的bug
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/03/17 09:43:41
// Design Name:
// Module Name: MC_RV32Core
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`include "Parameters.v"
import Params::*;
module MC_RV32Core(
input logic clk,
input logic rst_n
);
//状态机
typedef enum bit [2:0] {
IDLE,
IF,ID,EXE,MEM,WB
} State;
State cur_state,next_state; //状态机
//ID
logic [4:0] RS1; //第一个源操作数的寄存器编号
logic [4:0] RS2; //第二个源操作数的寄存器编号
logic [4:0] RD; //目的寄存器编号
logic [31:0] Imm; //解析得到的立即数
logic [6:0] Op; //操作码
logic [2:0] Fn3; //功能字段
logic [6:0] Fn7; //功能字段
logic Jal; //Jal指令
logic Jalr; //Jalr指令
LoadType RegWrite; //数据选取
logic MemToReg; //写寄存器的数据是否来自MEM
logic [3:0] MemWrite; //写数据存储器
logic LoadNpc; //是否计算PCF+4
BType BranchType; //条件分支指令类型
AluOp AluControl; //ALU控制信号
logic AluSrc1; //第一个源操作数来源
logic [1:0] AluSrc2; //第二个源操作数来源
Type ImmType; //立即数类型
logic [31:0] RegOut1; //寄存器读出值
logic [31:0] RegOut2; //寄存器读出值
logic [31:0] JalT; //Jal跳转地址
//IF
logic [31:0] PCF; //当前PC地址,根据PCF的值读取指令
logic [31:0]Instr; //读出的指令
logic [31:0] NPC; //下一条指令的地址
//EXE
logic [31:0] Operand1; //ALU源操作数1
logic [31:0] Operand2; //ALU源操作数2
logic [31:0] AluOut; //ALU输出
logic [31:0] BrT; //条件分支跳转地址
logic [31:0] JalrT; //Jalr跳转地址
//MEM
logic [31:0] StoreData; //要写入存储器的数据
logic [31:0] DM_RD; //数据存储器读出数据
logic [31:0] Result; //要写入寄存器堆的数据,或来自Alu,或来自PCF+4,由LoadNpc决定
//WB
logic [31:0] RegWriteData; //要写入寄存器的数据,或来自于DMEM,或来自于其他
logic [31:0] DM_RD_EXT; //字节选择后的DMEM读出数据
logic RegWriteEn; //是否写寄存器堆
//解析Instr的各个字段,包括RS1,RS2,RD,Op,Fn3,Fn7
assign RS1=Instr[19:15];
assign RS2=Instr[24:20];
assign RD=Instr[11:7];
assign Op=Instr[6:0];
assign Fn3=Instr[14:12];
assign Fn7=Instr[31:25];
//RegWriteEn,寄存器写使能信号
//是否写寄存器堆,仅在WB阶段写
always_comb
begin
if(cur_state==WB) //仅在WB阶段写寄存器
begin
if(RegWrite==NOREGWRITE)
RegWriteEn=0;
else
RegWriteEn=1;
end
else
RegWriteEn=0;
end
//PCF
always_ff@(posedge clk,negedge rst_n)
if(~rst_n)
PCF<=0;
else if(cur_state==WB) //地址均在WB阶段更新
PCF<=NPC;
//Operand1,Operand2
always_comb
begin
if(AluSrc1==1'b1)
Operand1=PCF;
else
Operand1=RegOut1;
end
always_comb
begin
if(AluSrc2==2'b00) //移位指令
Operand2=RS2;
else if(AluSrc2==2'b01) //R型和B型指令
Operand2=RegOut2;
else //其他,来自立即数
Operand2=Imm;
end
//StoreData
assign StoreData=RegOut2; //仅在指令为S型指令时有效,其值为Reg[rs2]
//Result
always_comb
begin
if(LoadNpc) //jal,jalr指令,将PCF+4写入Reg[rd]
Result=PCF+4;
else
Result=AluOut;
end
//RegWriteData
always_comb
begin
if(MemToReg)
RegWriteData=DM_RD_EXT;
else
RegWriteData=Result;
end
//JalT,JalrT,BrT
assign JalT=Imm+PCF; //加法部件计算得到
assign JalrT=AluOut; //ALU计算得到
assign BrT=Imm+PCF; //加法部件计算得到
//三段式状态机
always_ff@(posedge clk,negedge rst_n)
if(~rst_n)
cur_state<=IDLE;
else
cur_state<=next_state;
//
always_comb begin
case(cur_state)
IDLE:if(~rst_n)
next_state=IDLE;
else
next_state=IF;
IF:next_state=ID;
ID:next_state=EXE;
EXE:next_state=MEM;
MEM:next_state=WB;
WB:next_state=IF;
default:next_state=IDLE;
endcase
end
//模块例化
//控制单元
ControlUnit U1(
.Op(Op),
.Fn3(Fn3),
.Fn7(Fn7),
.JalD(Jal), //是否为Jal指令
.JalrD(Jalr), //是否是Jalr指令
.RegWriteD(RegWrite), //LOAD指令字节选取(LW,LH,LB,...)
.MemToRegD(MemToReg), //写入寄存器的值是否来自MEM
.MemWriteD(MemWrite), //写MEM时字节选中信号,S类型指令
.LoadNpcD(LoadNpc), //MEM阶段是否计算PC+4,用于Jal和Jalr指令
.BranchTypeD(BranchType), //分支指令类型,BEQ,BNE,...
.AluControlD(AluControl), //EXE阶段ALU控制信号,进行何种运算
.AluSrc2D(AluSrc2), //第二个源操作数的来源
.AluSrc1D(AluSrc1), //第一个源操作数的来源,rs1或者pc
.ImmType(ImmType) //立即数类型,不同类型解析不同
);
//ALU
ALU U2(
.Operand1(Operand1),
.Operand2(Operand2),
.AluControl(AluControl),
.AluOut(AluOut)
);
//BranchUnit
BranchUnit U3(
.Reg1(Operand1), //第一个源操作数
.Reg2(Operand2), //第二个源操作数
.BrType(BranchType), //条件分支指令类型
.BranchE(Branch) //是否跳转
);
//数据存储器
DataMem U4(
.clk(clk),
.A(AluOut), //地址
.WD(StoreData), //要写入的数据
.WE(MemWrite), //写使能(一个字节一位)
.RD(DM_RD) //读出的数据
);
//数据选取单元
Data_Ext U5(
.LoadByteSelect(AluOut[1:0]),
.RegWrite(RegWrite),
.In(DM_RD),
.Out(DM_RD_EXT)
);
//立即数单元
ImmUnit U6(
.ImmType(ImmType), //指令中立即数的类型
.In(Instr), //输入指令
.Out(Imm) //输出解析得到的立即数
);
//指令存储器
InstrMem U7(
.InstrAddr(PCF), //指令地址,4字节对齐
.Instr(Instr) //读出的指令
);
//PC生成单元
NPC_Generator U8(
.Jal(Jal),
.Jalr(Jalr),
.Branch(Branch),
.JalT(JalT),
.JalrT(JalrT),
.BrT(BrT),
.PC(PCF),
.NPC(NPC)
);
//寄存器堆
RegisterFile U9(
.clk(clk),
.RS1(RS1), //要读的寄存器编号
.RS2(RS2), //要读的寄存器编号
.RegOut1(RegOut1), //读出内容:Reg[rs1]
.RegOut2(RegOut2), //读出内容:Reg[rs2]
.WD(RegWriteData), //要写入寄存器的数据
.RD(RD), //写寄存器编号
.WE(RegWriteEn) //写使能
);
endmodule
1
https://gitee.com/jmqian1009/multi-cycle-risc-v-cpu-design.git
git@gitee.com:jmqian1009/multi-cycle-risc-v-cpu-design.git
jmqian1009
multi-cycle-risc-v-cpu-design
多周期RISC-V CPU设计
master

搜索帮助