3模型机指令系统设计-2【FPGA模型机课程设计】
- 前言
- 推荐
- 3模型机指令系统设计-2
- 安排
- MIPS 12条整数指令
- 测试与结果
- 乘除法指令实现和功能仿真要点
- 1 乘法除法指令格式
- 2 通路增加部件
- 3 对整体通路的影响
- 4 功能验证
- 代码设计
- define
- ID
- EX
- EX1
- HiLo 高位低位寄存器
- MIPS
- InstMem
- 附录
- 0 框架
- 1 define 编码
- 3 ID 译码
- 4 EX 执行
- EX1 修正EX
- 新增:HiLo 高位低位寄存器
- 8 MIPS
- 9 InstMem 指令存储器
- 最后
前言
2023-5-23 08:02:23
仅供学习交流使用
推荐
0集中实践环节计划书【FPGA模型机课程设计】
3模型机指令系统设计-2
安排
第一周周三:
模型机指令系统设计。学生根据搭建的模型机数据通路图,选择扩展的指令格式和指令功能。扩展指令系统的选择可以参照MIPS 32位处理器指令集,选择MIPS12条整数指令。要求能够画出指令格式和指令功能,能够画出处理器内部实现结构图,包括时序信号和控制信号,可以采用单周期方案。
MIPS 12条整数指令
上篇实现了前4条指令
此篇文章实现乘除相关指令
需要修改框架
测试与结果
//测试乘除
//R1=00001100 R2=00000020
//multu,R1,R2 0_22000
instmem [6] = 32'b000000_00001_00010_00111_00000_011001;//multu,R1,R2
//ori R7,ffff -- R7 --0000ffff
instmem [7] = 32'h3407ffff; //ori R7 ffff
//sll R7,R7,10h -- R7 --ffff0000
instmem [8] = 32'b000000_00000_00111_00111_10000_000000;//sll R7,R7,10h
//mult R7,R2 ffffffff_ffe00000
instmem [9] = 32'b000000_00111_00010_00000_00000_011000;//mult R7,R2
//divu r1,r2 88_0
instmem [10] = 32'b000000_00001_00010_00000_00000_011011;//divu r1,r2
//div r3,r2 fffff800_0
instmem [11] = 32'b000000_00111_00010_00000_00000_011010;//div r7,r2
修改EX增加清零相关信号
在仿真中可以观察到读写HiLo使能和读写HiLo数据会清0
否则:不会被清0
导致影响后面的实验
乘除法指令实现和功能仿真要点
参考:教学资料
1 乘法除法指令格式
2 通路增加部件
通路中增加HiLo寄存器:乘法运算指令完成两个32位的数据相乘,乘积存放到寄存器hi和lo组成的64位寄存器中。除法运算指令完成两个32位数据相除,商存放到寄存器lo中,余数存放到寄存器hi中。
3 对整体通路的影响
IF:无影响,不需要改变
ID:增加判断mult、multu、div、divu的分支。读取rs字段寄存器和rt字段寄存器的值,送入EX完成相应运算。视频中做了详细说明。
EX:实现带符号乘除法和无符号数乘除法。无符号数乘法和除法采用VerilogHDL中的运算符就可以实现。带符号数乘除法现在也有很方便的实现方法,通过$signed可以实现作为带符号数,再结合运算符实现带符号数运算功能描述。
乘法和除法的运算结果都写到HiLo寄存器。所以需要设置写Hi和Lo有效,完成写HiLo寄存器。设置写Hi和Lo有效也可以在ID模块中完成。
HiLo寄存器:HiLo用于存放乘法和除法的运算结果。Hi和Lo均为32bit寄存器。电路描述与实现RegFile思想一致。详细见视频中的说明。
4 功能验证
ori r1, r0, 0x1100 r1=00001100
ori r2, r0, 0x0020 r2=00000020
multu r1,r2 无符号乘法 r1*r2=1100*20=22000
ori r3, r0, 0xffff r3=0000ffff
sll r3, r3, 0x10 r3=ffff0000
mult r3,r2 带符号乘法 r3*r2=ffff0000*20=ffe00000,高位ffffffff
divu r1,r2 无符号除法 r1/r2=1100/20=88h 余数为0
div r3,r2 带符号除法 r3/r2=ffff0000/20=fffff800 余数为0 //此处资料有误 -2^16÷32=-2^11 结果不是ffffff80
用于功能验证的指令可以自己设计,只要指令执行结果和预期一致就说明设计正确。是否功能正确,必须用仿真波形图来说明。
代码设计
参考: 乘除法指令实现和功能仿真要点
define
添加编码
//MIPS 扩展整数指令集
//表2 MIPS 12条整数指令
`define Inst_mult 6'b011000 //r
`define Inst_multu 6'b011001 //r
`define Inst_div 6'b011010 //r
`define Inst_divu 6'b011011 //r
//内部供EX的编码
`define Mult 6'b010011
`define Multu 6'b010100
`define Div 6'b010101
`define Divu 6'b010110
ID
R型扩展编码中添加
`Inst_mult:
begin
op = `Mult;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
`Inst_multu:
begin
op = `Multu;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
`Inst_div:
begin
op = `Div;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
`Inst_divu:
begin
op = `Divu;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
EX
添加两个输入引脚
四个输出引脚
并且实现四个指令功能
module EX (
input wire rst,
//input wire [5:0] op,
input wire [5:0] op_i,
input wire [31:0] regaData,
input wire [31:0] regbData,
input wire regcWrite_i,
input wire [4:0] regcAddr_i,
input wire [31:0] rHiData,//乘除 读hi数据
input wire [31:0] rLoData,//乘除 读hi数据
output reg [31:0] regcData,
output wire regcWrite,
output wire [4:0] regcAddr,
output wire [5:0] op,
output wire [31:0] memAddr,
output wire [31:0] memData,
output reg whi, //乘除 写hi使能
output reg wlo, //乘除 写lo使能
output reg [31:0] wHiData, //乘除 写hi数据
output reg [31:0] wLoData //乘除 写lo数据
);
always@(*)
if(rst == `RstEnable)
begin
regcData = `Zero;
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
end
else
//case(op)
case(op_i)
//乘除指令
`Mult:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=
$signed(regaData)*$signed(regbData);
end
`Multu:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=regaData*regbData;
end
`Div:
begin
whi=`Valid;
wlo=`Valid;
wHiData=$signed(regaData)%$signed(regbData);
wLoData=$signed(regaData)/$signed(regbData);
end
`Divu:
begin
whi=`Valid;
wlo=`Valid;
wHiData=regaData%regbData;
wLoData=regaData/regbData;
end
default:
regcData = `Zero;
endcase
EX1
代码修正:
EX有一点bug
没有把以下数据置为无效
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
导致一直再读写Hi、Lo寄存器
module EX (
input wire rst,
//input wire [5:0] op,
input wire [5:0] op_i,
input wire [31:0] regaData,
input wire [31:0] regbData,
input wire regcWrite_i,
input wire [4:0] regcAddr_i,
input wire [31:0] rHiData,//乘除 读hi数据
input wire [31:0] rLoData,//乘除 读hi数据
output reg [31:0] regcData,
output wire regcWrite,
output wire [4:0] regcAddr,
output wire [5:0] op,
output wire [31:0] memAddr,
output wire [31:0] memData,
output reg whi, //乘除 写hi使能
output reg wlo, //乘除 写lo使能
output reg [31:0] wHiData, //乘除 写hi数据
output reg [31:0] wLoData //乘除 写lo数据
);
always@(*)
if(rst == `RstEnable)
begin
regcData = `Zero;
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
end
else
begin
regcData = `Zero;
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
//case(op)
case(op_i)
//乘除指令
`Mult:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=
$signed(regaData)*$signed(regbData);
end
`Multu:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=regaData*regbData;
end
`Div:
begin
whi=`Valid;
wlo=`Valid;
wHiData=$signed(regaData)%$signed(regbData);
wLoData=$signed(regaData)/$signed(regbData);
end
`Divu:
begin
whi=`Valid;
wlo=`Valid;
wHiData=regaData%regbData;
wLoData=regaData/regbData;
end
default:
regcData = `Zero;
endcase
end
HiLo 高位低位寄存器
添加:HiLo 高位低位寄存器
用于读写乘法除法指令的结果
`include "define.v"
module HiLo (
input wire rst,
input wire clk ,
input wire [31:0] wHiData,
input wire [31:0] wLoData,
input wire whi ,
input wire wlo ,
output reg [31:0] rHiData,
output reg [31:0] rLoData
);
reg [31:0]hi,lo;//内部存储
always@ (*)
if(rst==`RstEnable)
begin
rHiData = `Zero;
rLoData = `Zero;
end
else
begin
rHiData = hi;
rLoData = lo;
end
always@(posedge clk)
if (rst ==`RstDisable && whi==`Valid)
hi=wHiData;
else ;
always@(posedge clk)
if (rst ==`RstDisable && wlo==`Valid)
lo=wLoData;
else ;
endmodule
MIPS
修改相关顶层封装
//md-hl
wire [31:0] wHiData_ex;
wire [31:0] wLoData_ex;
wire whi;
wire wlo;
wire [31:0] rHiData_ex;
wire [31:0] rLoData_ex;
//乘除md-修改EX实例化
EX ex0(
.rst(rst),
//.op(op),
.op_i(op_id),
.regaData(regaData_id),
.regbData(regbData_id),
.regcWrite_i(regcWrite_id),
.regcAddr_i(regcAddr_id),
.rHiData(rHiData_ex),//md
.rLoData(rLoData_ex),//md
.regcData(regcData_ex),
.regcWrite(regcWrite_ex),
.regcAddr(regcAddr_ex),
.op(op_ex),//ls
.memAddr(memAddr_ex),//ls
.memData(memData_ex),//ls
.whi(whi_ex),//md
.wlo(wlo_ex),//md
.wHiData(wHiData_ex),//md
.wLoData(wLoData_ex) //md
);
//新增HiLo寄存器
HiLo hilo0(
.rst(rst),
.clk(clk),
.wHiData(wHiData_ex),
.wLoData(wLoData_ex),
.whi(whi_ex),
.wlo(wlo_ex),
.rHiData(rHiData_ex),
.rLoData(rLoData_ex)
);
InstMem
//测试乘除
//R1=00001100 R2=00000020
//multu,R1,R2 0_22000
instmem [6] = 32'b000000_00001_00010_00111_00000_011001;//multu,R1,R2
//ori R7,ffff -- R7 --0000ffff
instmem [7] = 32'h3407ffff; //ori R7 ffff
//sll R7,R7,10h -- R7 --ffff0000
instmem [8] = 32'b000000_00000_00111_00111_10000_000000;//sll R7,R7,10h
//mult R7,R2 ffffffff_ffe00000
instmem [9] = 32'b000000_00111_00010_00000_00000_011000;//mult R7,R2
//divu r1,r2 88_0
instmem [10] = 32'b000000_00001_00010_00000_00000_011011;//divu r1,r2
//div r3,r2 fffff800_0
instmem [11] = 32'b000000_00111_00010_00000_00000_011010;//div r7,r2
附录
其余与上篇一样
0 框架
顶层设计
代码框架
1 define 编码
//0、宏定义文件
`define RstEnable 1'b1
`define RstDisable 1'b0
`define RomEnable 1'b1
`define RomDisable 1'b0
`define Zero 0
`define Valid 1'b1
`define Invalid 1'b0
//MEM宏编译
`define RamWrite 1'b1
`define RamUnWrite 1'b0
`define RamEnable 1'b1
`define RamDisable 1'b0
//指令外部编码
//MIPS 基本整数指令集
//表1 20条MIPS整数指令
//R型编码
`define Inst_reg 6'b000000
`define Inst_add 6'b100000
`define Inst_sub 6'b100010
`define Inst_and 6'b100100
`define Inst_or 6'b100101
`define Inst_xor 6'b100110
`define Inst_sll 6'b000000
`define Inst_srl 6'b000010
`define Inst_sra 6'b000011
`define Inst_jr 6'b001000
//I型编码
`define Inst_addi 6'b001000
`define Inst_andi 6'b001100
`define Inst_ori 6'b001101
`define Inst_xori 6'b001110
`define Inst_lw 6'b100011
`define Inst_sw 6'b101011
`define Inst_beq 6'b000100
`define Inst_bne 6'b000101
`define Inst_lui 6'b001111
//J型编码
`define Inst_j 6'b000010
`define Inst_jal 6'b000011
//MIPS 扩展整数指令集
//表2 MIPS 12条整数指令
`define Inst_slt 6'b101010
`define Inst_bgtz 6'b000111 //j i
`define Inst_bltz 6'b000001 //j i
`define Inst_jalr 6'b001001 //r
`define Inst_mult 6'b011000 //r
`define Inst_multu 6'b011001 //r
`define Inst_div 6'b011010 //r
`define Inst_divu 6'b011011 //r
`define Inst_mfhi 6'b010000 //r
`define Inst_mflo 6'b010010 //r
`define Inst_mthi 6'b010001 //r
`define Inst_mtlo 6'b010011 //r
//表3 MIPS与中断异常相关6条指令
`define Inst_ll 6'b010011 //i
`define Inst_sc 6'b010011 //i
`define Inst_mfc0 6'b000000 //010000扩展编码
`define Inst_mtc0 6'b000000 //010000扩展编码
`define Inst_eret 6'b011000 //010000扩展编码
`define Inst_eret 6'b001100 //r
//另外
//`define Inst_subi 6'b001001 //i
//内部供EX的编码
`define Nop 6'b000000
`define Or 6'b000001
`define And 6'b000010
`define Xor 6'b000011
`define Add 6'b000100
`define Sub 6'b000101
`define Lui 6'b100000
`define Sll 6'b000110
`define Srl 6'b000111
`define Sra 6'b001000
`define J 6'b001001
`define Jal 6'b001010
`define Jr 6'b001011
`define Beq 6'b001100
`define Bne 6'b001101
`define Bgtz 6'b001110
`define Bltz 6'b001111
`define Lw 6'b010000
`define Sw 6'b010001
`define Slt 6'b010010
`define Mult 6'b010011
`define Multu 6'b010100
`define Div 6'b010101
`define Divu 6'b010110
3 ID 译码
`include "define.v";
//ID 译码模块
//2、为操作数做准备
module ID (
input wire rst,
input wire [31:0] pc, //J型
input wire [31:0] inst,
input wire [31:0] regaData_i,
input wire [31:0] regbData_i,
output reg [5:0] op,
output reg [31:0] regaData,
output reg [31:0] regbData,
output reg regaRead,
output reg regbRead,
output reg regcWrite,
output reg [4:0] regaAddr,
output reg [4:0] regbAddr,
output reg [4:0] regcAddr,
output reg [31:0] jAddr, //J型
output reg jCe//J型
);
//操作指令
wire [5:0] inst_op = inst[31:26];
//扩展的立即数
reg [31:0] imm;
//用于R型指令
wire[5:0] func = inst[5:0];
//用于J型指令
wire [31:0] npc = pc + 4;
always@(*)
if(rst == `RstEnable)
begin
op = `Nop;
regaRead = `Invalid;
regbRead = `Invalid;
regcWrite = `Invalid;
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = `Zero;
imm = `Zero;
jCe = `Invalid;//J型
jAddr = `Zero;//J型
end
else
begin//后面的end
jCe = `Invalid;//J型
jAddr = `Zero;//J型
case(inst_op)
`Inst_ori:
begin
op = `Or;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {16'h0, inst[15:0]};
end
`Inst_andi:
begin
op = `And;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {16'h0, inst[15:0]};
end
`Inst_xori:
begin
op = `Xor;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {16'h0, inst[15:0]};
end
`Inst_addi:
begin
op = `Add;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {{16{inst[15]}}, inst[15:0]};
end
// `Inst_subi:
// begin
// op = `Sub;
// regaRead = `Valid;
// regbRead = `Invalid;
// regcWrite = `Valid;
// regaAddr = inst[25:21];
// regbAddr = `Zero;
// regcAddr = inst[20:16];
// imm = {{16{inst[15]}}, inst[15:0]};
// end
`Inst_lui:
begin
op = `Lui;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {inst[15:0],16'h0};
end
`Inst_reg:
case(func)
`Inst_add:
begin
op = `Add;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
`Inst_or:
begin
op = `Or;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
`Inst_sub:
begin
op = `Sub;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
`Inst_and:
begin
op = `And;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
`Inst_xor:
begin
op = `Xor;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
`Inst_sll:
begin
op = `Sll;
regaRead = `Invalid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = `Zero;
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = {27'b0,inst[10:6]};//移位复用imm
end
`Inst_srl:
begin
op = `Srl;
regaRead = `Invalid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = `Zero;
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = {27'b0,inst[10:6]};//移位复用imm
end
`Inst_sra:
begin
op = `Sra;
regaRead = `Invalid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = `Zero;
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = {27'b0,inst[10:6]};//移位复用imm
end
//JR型指令
`Inst_jr:
begin
op = `J;
regaRead = `Valid;//需要读rs
regbRead = `Invalid;
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = `Zero;
jAddr = regaData;//regaData=(regaAddr)
jCe = `Valid;
imm = `Zero;
end
`Inst_jalr:
begin
op = `Jal;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = 5'b11111;
jAddr = regaData;
jCe = `Valid;
imm = npc;//regbData中存imm npc
end
//12条整数指令
`Inst_slt:
begin
op = `Slt;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
`Inst_mult:
begin
op = `Mult;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
`Inst_multu:
begin
op = `Multu;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
`Inst_div:
begin
op = `Div;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
`Inst_divu:
begin
op = `Divu;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = `Zero;
end
default:
begin
regaRead = `Invalid;
regbRead = `Invalid;
regcWrite = `Invalid;
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = `Zero;
imm = `Zero;
end
endcase
//J型指令
`Inst_j:
begin
op = `J;
regaRead = `Invalid;
regbRead = `Invalid;
regcWrite = `Invalid;//不需要写
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = `Zero;
jAddr = {npc[31:28], inst[25:0], 2'b00};
jCe = `Valid;
imm = `Zero;
end
`Inst_jal:
begin
op = `Jal;
regaRead = `Invalid;
regbRead = `Invalid;
regcWrite = `Valid;//需要把npc写入R31中
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = 5'b11111;
jAddr = {npc[31:28], inst[25:0], 2'b00};
jCe = `Valid;
imm = npc;
end
//J+型指令
`Inst_beq:
begin
op = `Beq;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
jAddr = npc+{{14{inst[15]}},inst[15:0], 2'b00};
if(regaData==regbData)
jCe = `Valid;//等于有效
else
jCe = `Invalid;
imm = `Zero;
end
`Inst_bne:
begin
op = `Beq;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
jAddr = npc+{{14{inst[15]}},inst[15:0], 2'b00};
if(regaData!=regbData)
jCe = `Valid;//等于有效
else
jCe = `Invalid;
imm = `Zero;
end
`Inst_bltz:
begin
op = `Bltz;
regaRead = `Valid;
regbRead = `Valid;//若regbRead无效,则regbData=imm=0
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
jAddr = npc+{{14{inst[15]}},inst[15:0], 2'b00};
if(regaData<regbData)
jCe = `Valid;//小于有效
else
jCe = `Invalid;
imm = 32'b0;
end
`Inst_bgtz:
begin
op = `Bgtz;
regaRead = `Valid;
//regbRead = `Valid;//若regbRead有效,则regbData=(regbAddr)
regbRead = `Invalid;//若regbRead无效,则regbData=imm=0
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
jAddr = npc+{{14{inst[15]}},inst[15:0], 2'b00};
if(regaData>regbData)
jCe = `Valid;//大于有效
else
jCe = `Invalid;
imm = 32'b0;
end
//Load Store指令
`Inst_lw:
begin
op = `Lw;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {{16{inst[15]}},inst[15:0]};
end
`Inst_sw:
begin
op = `Sw;
regaRead = `Valid;
regbRead = `Valid;
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = `Zero;
imm = {{16{inst[15]}},inst[15:0]};
end
default:
begin
op = `Nop;
regaRead = `Invalid;
regbRead = `Invalid;
regcWrite = `Invalid;
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = `Zero;
imm = `Zero;
end
endcase
end
/*
//二选一 regaData= regaData_i : imm
always@(*)
if(rst == `RstEnable)
regaData = `Zero;
else if(regaRead == `Valid)
regaData = regaData_i;
else
regaData = imm;
//二选一 regbData= regbData_i : imm
always@(*)
if(rst == `RstEnable)
regbData = `Zero;
else if(regbRead == `Valid)
regbData = regbData_i;
else
regbData = imm;
*/
always@(*)
if(rst == `RstEnable)
regaData = `Zero;
else if(op == `Lw || op == `Sw)
regaData = regaData_i + imm;
else if(regaRead == `Valid)
regaData = regaData_i;
else
regaData = imm;
always@(*)
if(rst == `RstEnable)
regbData = `Zero;
else if(regbRead == `Valid)
regbData = regbData_i;
else
regbData = imm;
endmodule
4 EX 执行
复制EX请复制修正后的版本
`include "define.v";
//3、执行指令模块
module EX (
input wire rst,
//input wire [5:0] op,
input wire [5:0] op_i,
input wire [31:0] regaData,
input wire [31:0] regbData,
input wire regcWrite_i,
input wire [4:0] regcAddr_i,
input wire [31:0] rHiData,//乘除 读hi数据
input wire [31:0] rLoData,//乘除 读hi数据
output reg [31:0] regcData,
output wire regcWrite,
output wire [4:0] regcAddr,
output wire [5:0] op,
output wire [31:0] memAddr,
output wire [31:0] memData,
output reg whi, //乘除 写hi使能
output reg wlo, //乘除 写lo使能
output reg [31:0] wHiData, //乘除 写hi数据
output reg [31:0] wLoData //乘除 写lo数据
);
assign op = op_i;
assign memAddr = regaData;
assign memData = regbData;
always@(*)
if(rst == `RstEnable)
begin
regcData = `Zero;
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
end
else
//case(op)
case(op_i)
`Or:
regcData = regaData | regbData;
`And:
regcData = regaData & regbData;
`Xor:
regcData = regaData ^ regbData;
`Add:
regcData = regaData + regbData;
`Sub:
regcData = regaData - regbData;
`Lui:
begin
regcData = regaData | regbData;
end
`Sll:
regcData = regbData << regaData;
`Srl:
regcData = regbData >> regaData;
`Sra:
regcData = ($signed(regbData)) >>> regaData;
//J- JR型
`J:
regcData = `Zero;
`Jal:
regcData = regbData;//regaData有其他用处 jr给pc=jaddr=(rs)
//J+型
`Beq:
regcData = `Zero;
`Bne:
regcData = `Zero;
`Bltz:
regcData = `Zero;
`Bgtz:
regcData = `Zero;
//12条整数指令
`Slt:
begin
if($signed(regaData)<$signed(regbData))
regcData={{31{0}},1};
else
regcData={32{0}};
end
//乘除指令
`Mult:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=
$signed(regaData)*$signed(regbData);
end
`Multu:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=regaData*regbData;
end
`Div:
begin
whi=`Valid;
wlo=`Valid;
wHiData=$signed(regaData)%$signed(regbData);
wLoData=$signed(regaData)/$signed(regbData);
end
`Divu:
begin
whi=`Valid;
wlo=`Valid;
wHiData=regaData%regbData;
wLoData=regaData/regbData;
end
default:
regcData = `Zero;
endcase
assign regcWrite = regcWrite_i;
assign regcAddr = regcAddr_i;
endmodule
EX1 修正EX
复制EX请复制此版本
`include "define.v";
//3、执行指令模块
// 修正EX
//注意修改模块名为EX
//或者 MIPS 封装EX1
module EX1 (
input wire rst,
//input wire [5:0] op,
input wire [5:0] op_i,
input wire [31:0] regaData,
input wire [31:0] regbData,
input wire regcWrite_i,
input wire [4:0] regcAddr_i,
input wire [31:0] rHiData,//乘除 读hi数据
input wire [31:0] rLoData,//乘除 读hi数据
output reg [31:0] regcData,
output wire regcWrite,
output wire [4:0] regcAddr,
output wire [5:0] op,
output wire [31:0] memAddr,
output wire [31:0] memData,
output reg whi, //乘除 写hi使能
output reg wlo, //乘除 写lo使能
output reg [31:0] wHiData, //乘除 写hi数据
output reg [31:0] wLoData //乘除 写lo数据
);
assign op = op_i;
assign memAddr = regaData;
assign memData = regbData;
always@(*)
if(rst == `RstEnable)
begin
regcData = `Zero;
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
end
else
begin
regcData = `Zero;
whi=`Invalid;
wlo=`Invalid;
wHiData=`Zero;
wLoData=`Zero;
//case(op)
case(op_i)
`Or:
regcData = regaData | regbData;
`And:
regcData = regaData & regbData;
`Xor:
regcData = regaData ^ regbData;
`Add:
regcData = regaData + regbData;
`Sub:
regcData = regaData - regbData;
`Lui:
begin
regcData = regaData | regbData;
end
`Sll:
regcData = regbData << regaData;
`Srl:
regcData = regbData >> regaData;
`Sra:
regcData = ($signed(regbData)) >>> regaData;
//J- JR型
`J:
regcData = `Zero;
`Jal:
regcData = regbData;//regaData有其他用处 jr给pc=jaddr=(rs)
//J+型
`Beq:
regcData = `Zero;
`Bne:
regcData = `Zero;
`Bltz:
regcData = `Zero;
`Bgtz:
regcData = `Zero;
//12条整数指令
`Slt:
begin
if($signed(regaData)<$signed(regbData))
regcData={{31{0}},1};
else
regcData={32{0}};
end
//乘除指令
`Mult:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=
$signed(regaData)*$signed(regbData);
end
`Multu:
begin
whi=`Valid;
wlo=`Valid;
{wHiData,wLoData}=regaData*regbData;
end
`Div:
begin
whi=`Valid;
wlo=`Valid;
wHiData=$signed(regaData)%$signed(regbData);
wLoData=$signed(regaData)/$signed(regbData);
end
`Divu:
begin
whi=`Valid;
wlo=`Valid;
wHiData=regaData%regbData;
wLoData=regaData/regbData;
end
default:
regcData = `Zero;
endcase
end
assign regcWrite = regcWrite_i;
assign regcAddr = regcAddr_i;
endmodule
新增:HiLo 高位低位寄存器
`include "define.v"
module HiLo (
input wire rst,
input wire clk ,
input wire [31:0] wHiData,
input wire [31:0] wLoData,
input wire whi ,
input wire wlo ,
output reg [31:0] rHiData,
output reg [31:0] rLoData
);
reg [31:0]hi,lo;//内部存储
always@ (*)
if(rst==`RstEnable)
begin
rHiData = `Zero;
rLoData = `Zero;
end
else
begin
rHiData = hi;
rLoData = lo;
end
always@(posedge clk)
if (rst ==`RstDisable && whi==`Valid)
hi=wHiData;
else ;
always@(posedge clk)
if (rst ==`RstDisable && wlo==`Valid)
lo=wLoData;
else ;
endmodule
8 MIPS
`include "define.v";
//5、MIPS封装
//修改EX实例化,新增Mem实例化
//新增端口rdData wtData memAddr memCe memWr
//原op变为op_i
//新增ls内部变量
module MIPS(
input wire clk,
input wire rst,
input wire [31:0] instruction,
input wire [31:0] rdData,//ls
output wire romCe,
output wire [31:0] instAddr,
output wire [31:0] wtData,//ls
output wire [31:0] memAddr,//ls
output wire memCe,//ls
output wire memWr//ls
);
wire [31:0] regaData_regFile, regbData_regFile;
wire [31:0] regaData_id, regbData_id;
wire [31:0] regcData_ex;
//wire [5:0] op;
wire [5:0] op_id; //ls
wire regaRead, regbRead;
wire [4:0] regaAddr, regbAddr;
wire regcWrite_id, regcWrite_ex;
wire [4:0] regcAddr_id, regcAddr_ex;
//J型
wire [31:0] jAddr;
wire jCe;
//ls
wire [5:0] op_ex;
wire[31:0] memAddr_ex,memData_ex;
wire [5:0] regAddr_mem;
wire [31:0] regData_mem;
wire regWr_mem;
//md-hl
wire [31:0] wHiData_ex;
wire [31:0] wLoData_ex;
wire whi;
wire wlo;
wire [31:0] rHiData_ex;
wire [31:0] rLoData_ex;
IF if0(
.clk(clk),
.rst(rst),
.jAddr(jAddr),//J型
.jCe(jCe),//J型
.ce(romCe),
.pc(instAddr)
);
ID id0(
.rst(rst),
.pc(instAddr),//J型
.inst(instruction),
.regaData_i(regaData_regFile),
.regbData_i(regbData_regFile),
//.op(op),
.op(op_id),//ls
.regaData(regaData_id),
.regbData(regbData_id),
.regaRead(regaRead),
.regbRead(regbRead),
.regaAddr(regaAddr),
.regbAddr(regbAddr),
.regcWrite(regcWrite_id),
.regcAddr(regcAddr_id),
.jAddr(jAddr),//J型
.jCe(jCe)//J型
);
//乘除md-修改EX实例化
EX ex0(
.rst(rst),
//.op(op),
.op_i(op_id),
.regaData(regaData_id),
.regbData(regbData_id),
.regcWrite_i(regcWrite_id),
.regcAddr_i(regcAddr_id),
.rHiData(rHiData_ex),//md
.rLoData(rLoData_ex),//md
.regcData(regcData_ex),
.regcWrite(regcWrite_ex),
.regcAddr(regcAddr_ex),
.op(op_ex),//ls
.memAddr(memAddr_ex),//ls
.memData(memData_ex),//ls
.whi(whi_ex),//md
.wlo(wlo_ex),//md
.wHiData(wHiData_ex),//md
.wLoData(wLoData_ex) //md
);
//新增HiLo寄存器
HiLo hilo0(
.rst(rst),
.clk(clk),
.wHiData(wHiData_ex),
.wLoData(wLoData_ex),
.whi(whi_ex),
.wlo(wlo_ex),
.rHiData(rHiData_ex),
.rLoData(rLoData_ex)
);
//新增Mem实例化
MEM mem0(
.rst(rst),
.op(op_ex),
.regcData(regcData_ex),
.regcAddr(regcAddr_ex),
.regcWr(regcWrite_ex),
.memAddr_i(memAddr_ex),
.memData(memData_ex),
.rdData(rdData),
.regAddr(regAddr_mem),
.regWr(regWr_mem),
.regData(regData_mem),
.memAddr(memAddr),
.wtData(wtData),
.memWr(memWr),
.memCe(memCe)
);
//修改RegFile实例化
RegFile regfile0(
.clk(clk),
.rst(rst),
//.we(regcWrite_ex),
.we(regWr_mem),
//.waddr(regcAddr_ex),
.waddr(regAddr_mem),
//.wdata(regcData_ex),
.wdata(regData_mem),
.regaRead(regaRead),
.regbRead(regbRead),
.regaAddr(regaAddr),
.regbAddr(regbAddr),
.regaData(regaData_regFile),
.regbData(regbData_regFile)
);
endmodule
9 InstMem 指令存储器
`include "define.v";
//6、指令存储器
module InstMem(
input wire ce,
input wire [31:0] addr,
output reg [31:0] data
);
reg [31:0] instmem [1023 : 0];
always@(*)
if(ce == `RomDisable)
data = `Zero;
else
data = instmem[addr[11 : 2]];
initial
begin
//指令测试
//初始化数据
//ori R0,1100 -- R1 --00001100
instmem [0] = 32'h34011100;
//ori R0,0020 -- R2 --00000020
instmem [1] = 32'h34020020;
//ori R0,ff00 -- R3 --0000ff00
instmem [2] = 32'h3403ff00;
//ori R0,ffff -- R4 --0000ffff
instmem [3] = 32'h3404ffff;
//I型指令测试
/*
//andi R0,ffff --R5 --00000000
instmem [4] = 32'h3005ffff;
//xori R0,ffff --R6 --0000ffff
instmem [5] = 32'h3806ffff;
//addi R0,ffff --R7 --ffffffff
instmem [6] = 32'h2007ffff;
// //subi R0,ffff --R8 --00000001
// instmem [7] = 32'h2408ffff;
//lui R0,ffff --R9 --ffff0000
instmem [8] = 32'h3C09ffff;
*/
//R1=00001100 R2=00000020
instmem [4] = 32'b000000_00001_00010_00101_00000_100000;//add,R5,R1,R2 00001120
instmem [5] = 32'b000000_00001_00010_00110_00000_100101;//or,R6,R1,R2 00001120
//R型指令测试
/*
instmem [6] = 32'b000000_00001_00010_00111_00000_100010;//sub,R7,R1,R2 000010e0
instmem [7] = 32'b000000_00001_00010_01000_00000_100100;//and,R8,R1,R2 00000000
instmem [8] = 32'b000000_00001_00010_01001_00000_100110;//xor,R9,R1,R2 00001120
//lui R0,ffff --R10 --ffff0000
instmem [9] = 32'h3C0Affff;
//R11=fffe0000 R12=7fff8000 R13=ffff8000
// Ra=sa={25'b0,imm[10:6]}
instmem [10] = 32'b000000_00000_01010_01011_00001_000000;//sll,R11,Ra,R10
instmem [11] = 32'b000000_00000_01010_01100_00001_000010;//srl,R12,Ra,R10
instmem [12] = 32'b000000_00000_01010_01101_00001_000011;//sra,R13,Ra,R10
*/
//J- JR型指令测试
/*
//pc=jaddr=npc(4) offset(26) 00(2)
//instmem [6] = 32'h08000001; //j 1 编码000010 pc=0004
instmem [6] = 32'h0C000002; //jal 2 编码000011 pc=0008 r31=npc001c
*/
/*
//pc=jaddr=(rs)
instmem [6] = 32'h3407000C;//ori,R7,000C
//instmem [7] = 32'b000000_00111_00000_00000_00000_001000; //jr R7 编码001000 pc=0000000C
instmem [7] = 32'b000000_00111_00000_00000_00000_001001; //jalr R7 编码001001 pc=0000000C R31=00000020
*/
/*
//J+型指令测试
//pc=jaddr=npc+S14 offset(16) 00(2)
//R1=00001100 R2=00000020 R3=000000ff R4=0000ffff R5=00001120 R6=00001120
//instmem [6] = 32'b000100_00101_00110_0000_0000_0000_0000; //beq r5,r6,0 编码000100 pc=001C
//instmem [6] = 32'b000100_00101_00110_0000_0000_0000_0001; //beq r5,r6,1 编码000100 pc=0020
//instmem [6] = 32'b000101_00001_00110_1111_1111_1111_1110; //bne r5,r6,-2 编码000101 pc=0014
//instmem [6] = 32'b000001_00010_00000_0000_0000_0000_0001; //bltz r2,r0,1 编码000001 pc=0020
instmem [6] = 32'b000111_00001_00000_1111_1111_1111_1110; //bgtz r1,r0,-2 编码010011 pc=0014
//ori R7,0001 -- R7 --00000001
instmem [7] = 32'h34070001; //ori R7 1
//ori R8,0001 -- R8 --00000001
instmem [8] = 32'h34080001; //ori R8 1
*/
/*
//(r1)=0000 1100
// +0000 0018
//addr=0000 1118
// =1000100011000 字节地址
// =100 0100 0110 字地址
// =446H 只有1K空间
// =46H 丢掉了高位的1位
// =70
//mem[70]=(r6)
instmem[6]=32'b101011_00001_00110_0000_0000_0001_1000; //sw r6,0x18(r1)
//(r7)=mem[70]
instmem[7]=32'b100011_00001_00111_0000_0000_0001_1000; //lw r7,0x18(r1)
*/
//测试12条MIPS指令
/*
//测试slt
//R1=00001100 R2=00000020
instmem [6] = 32'b000000_00001_00010_00111_00000_101010;//slt,R7,R1,R2 00000000
//lui R0,ffff --R8 --ffff0000
instmem [7] = 32'h3C08ffff;
//ori R8,ffff --R8 --ffffffff
instmem [8] = 32'b001101_01000_01000_1111_1111_1111_1111;
//lui R0,ffff --R9 --ffff0000
instmem [9] = 32'h3C09ffff;
//ori R9,ffff --R9 --fffffffe
instmem [10] = 32'b001101_01001_01001_1111_1111_1111_1110;
//R8=ffffffff(-1) R9=fffffffe(-2)
instmem [11] = 32'b000000_01001_01000_01010_00000_101010;//slt,R10,R9,R8 00000001
*/
//测试乘除
//R1=00001100 R2=00000020
//multu,R1,R2 0_22000
instmem [6] = 32'b000000_00001_00010_00111_00000_011001;//multu,R1,R2
//ori R7,ffff -- R7 --0000ffff
instmem [7] = 32'h3407ffff; //ori R7 ffff
//sll R7,R7,10h -- R7 --ffff0000
instmem [8] = 32'b000000_00000_00111_00111_10000_000000;//sll R7,R7,10h
//mult R7,R2 ffffffff_ffe00000
instmem [9] = 32'b000000_00111_00010_00000_00000_011000;//mult R7,R2
//divu r1,r2 88_0
instmem [10] = 32'b000000_00001_00010_00000_00000_011011;//divu r1,r2
//div r3,r2 fffff800_0
instmem [11] = 32'b000000_00111_00010_00000_00000_011010;//div r7,r2
end
endmodule
最后
2023-5-23 13:42:23
你对我百般注视,
并不能构成万分之一的我,
却是一览无余的你。
祝大家逢考必过
点赞收藏关注哦