5模型机整体的联调【FPGA模型机课程设计】
5模型机整体的联调【FPGA模型机课程设计】
- 前言
- 推荐
- 5模型机整体的联调
- 安排
- MIPS 基本整数指令集
- MIPS 扩展整数指令集
- 测试与结果
- 1FPGA模型计算机整体方案设计
- 掌握MIPS指令集的相关设计
- 2模型计算机各功能电路设计
- 初始化数据
- I型指令测试
- R型指令测试
- J型指令测试
- 访存指令测试
- 3模型机指令系统设计-1
- 测试slt
- 3模型机指令系统设计-2
- 测试乘除
- 3模型机指令系统设计-3
- 测试剩余4条指令
- 4实现中断异常相关指令-1
- 测试原子指令
- 4实现中断异常相关指令-2
- 测试syscall
- 测试定时中断
- 测试原子指令-失败案例
- 附录
- 0 框架
- 1 define 编码
- 2 IF 取值
- 3 ID 译码
- 4 EX 执行
- 5 MEM 访存
- 6 DataMem 数据存储器
- 7 RegFile 存取
- A HiLo 高位低位寄存器
- B LLbit LLbit寄存器
- C CP0 协处理器
- D Ctrl 控制模块
- 8 MIPS 封装
- 9 InstMem 指令存储器
- 10 SOC 顶层
- 11 soc_tb
- 最后
前言
2023-5-25 08:15:05
以下内容源自《【FPGA模型机课程设计】》
仅供学习交流使用
推荐
0集中实践环节计划书【FPGA模型机课程设计】
5模型机整体的联调
安排
第一周周五:
模型机整体的联调。完成模型机指令系统实现。学生根据设计好的指令系统实现方案,在Modelsim上进行功能仿真。要求将所有设计的机器指令都仿真正确,包括:数据流通、时序节拍、寄存器的读写,输入输出端口的访问、接口控制信号等。所有指令功能测试正确。指导教师对学生进行中期检查,主要观察指令运行结果,包括数据寄存器打入是否正确,转移指令是否正确设置PC,中断异常等指令功能的实现,即能够编写具体测试指令,能够通过简单的中断异常机器指令对中断异常等功能进行测试。
MIPS 基本整数指令集

MIPS 扩展整数指令集


测试与结果
1FPGA模型计算机整体方案设计
掌握MIPS指令集的相关设计
参见:计算机组成原理
- 实验三 ORI指令设计实验【计算机组成原理】
- 实验四 OR指令设计实验【计算机组成原理】
- 实验五 JR指令设计实验【计算机组成原理】
- 实验六 Load和Store指令设计实验【计算机组成原理】
实验内容,其实在计算机组成原理的课程设计做过
有兴趣的同学,可以支持博主,订阅一下计算机组成原理
不订阅也是可以的,实验过程中的代码会写在每篇博客的附录
2模型计算机各功能电路设计
初始化数据
//初始化数据//ori R0,1100 -- R1 --00001100instmem [0] = 32'h34011100;//ori R0,0020 -- R2 --00000020instmem [1] = 32'h34020020;//ori R0,ff00 -- R3 --0000ff00instmem [2] = 32'h3403ff00;//ori R0,ffff -- R4 --0000ffffinstmem [3] = 32'h3404ffff;

I型指令测试
//I型指令测试//andi R0,ffff --R5 --00000000instmem [4] = 32'h3005ffff;//xori R0,ffff --R6 --0000ffffinstmem [5] = 32'h3806ffff;//addi R0,ffff --R7 --ffffffffinstmem [6] = 32'h2007ffff;
// //subi R0,ffff --R8 --00000001
// instmem [7] = 32'h2408ffff;//lui R0,ffff --R9 --ffff0000instmem [8] = 32'h3C09ffff;

R型指令测试
//R型指令测试instmem [6] = 32'b000000_00001_00010_00111_00000_100010;//sub,R7,R1,R2 000010e0instmem [7] = 32'b000000_00001_00010_01000_00000_100100;//and,R8,R1,R2 00000000instmem [8] = 32'b000000_00001_00010_01001_00000_100110;//xor,R9,R1,R2 00001120//lui R0,ffff --R10 --ffff0000instmem [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,R10instmem [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型指令测试
//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
*/
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=0000000Cinstmem [7] = 32'b000000_00111_00000_00000_00000_001001; //jalr R7 编码001001 pc=0000000C R31=00000020
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 --00000001instmem [7] = 32'h34070001; //ori R7 1//ori R8,0001 -- R8 --00000001instmem [8] = 32'h34080001; //ori R8 1
instmem [6] = 32'b000100_00101_00110_0000_0000_0000_0000; //beq r5,r6,0 编码000100 pc=001C
跳转到相对于npc的0位置

instmem [6] = 32'b000100_00101_00110_0000_0000_0000_0001; //beq r5,r6,1 编码000100 pc=0020
跳转到相对于npc的+1位置

instmem [6] = 32'b000101_00001_00110_1111_1111_1111_1110; //bne r5,r6,-2 编码000101 pc=0014
跳转到相对于npc的-2位置

instmem [6] = 32'b000001_00010_00000_0000_0000_0000_0001; //bltz r2,r0,1 编码000001 pc=0020
跳转到相对于npc的+1位置

instmem [6] = 32'b000111_00001_00000_1111_1111_1111_1110; //bgtz r1,r0,-2 编码010011 pc=0014
跳转到相对于npc的-2位置

访存指令测试
//(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)

3模型机指令系统设计-1
测试slt
//测试12条MIPS指令//测试slt//R1=00001100 R2=00000020instmem [6] = 32'b000000_00001_00010_00111_00000_101010;//slt,R7,R1,R2 00000000//lui R0,ffff --R8 --ffff0000instmem [7] = 32'h3C08ffff;//ori R8,ffff --R8 --ffffffffinstmem [8] = 32'b001101_01000_01000_1111_1111_1111_1111;//lui R0,ffff --R9 --ffff0000instmem [9] = 32'h3C09ffff;//ori R9,ffff --R9 --fffffffeinstmem [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

3模型机指令系统设计-2
测试乘除
//测试乘除//R1=00001100 R2=00000020 //multu,R1,R2 0_22000instmem [6] = 32'b000000_00001_00010_00111_00000_011001;//multu,R1,R2//ori R7,ffff -- R7 --0000ffffinstmem [7] = 32'h3407ffff; //ori R7 ffff//sll R7,R7,10h -- R7 --ffff0000instmem [8] = 32'b000000_00000_00111_00111_10000_000000;//sll R7,R7,10h//mult R7,R2 ffffffff_ffe00000instmem [9] = 32'b000000_00111_00010_00000_00000_011000;//mult R7,R2//divu r1,r2 88_0instmem [10] = 32'b000000_00001_00010_00000_00000_011011;//divu r1,r2//div r3,r2 fffff800_0instmem [11] = 32'b000000_00111_00010_00000_00000_011010;//div r7,r2

3模型机指令系统设计-3
测试剩余4条指令
//测试剩余4条指令//R1=00001100 R2=00000020 //mthi,R1--hi=00001100instmem [6] = 32'b000000_00001_00000_00000_00000_010001;//mthi,R1//mtlo,R2--lo=00000020 instmem [7] = 32'b000000_00010_00000_00000_00000_010011;//mtlo,R2//mfhi,R7--R7=00001100instmem [8] = 32'b000000_00000_00000_00111_00000_010001;//mfhi,R7//mflo,R8--R8=00000020 instmem [9] = 32'b000000_00000_00000_01000_00000_010011;//mflo,R8

4实现中断异常相关指令-1
测试原子指令
//测试原子指令//计算地址说明//(r1)=0000 1100// +0000 0020//addr=0000 1120 // =1000100100000 字节地址// =100 0100 1000 字地址// =448H 只有1K空间// =48H 丢掉了高位的1位// =72//mem[72]<-->(r7)//测试功能//R1=00001100 R2=00000020 //Lpt: LL r7,0x20(r1) //读取程序里的信号量,LLibt=1//ll r7,0x20(r2) --(r7)=mem[72]=0instmem [6] = 32'b110000_00001_00111_0000_0000_0010_0000;//ll r7,0x20(r1)//if(r7 == clearFlag) //判断信号是否被占用,为clearFlag表示没占用//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r7,r0,else(+4)instmem [7] = 32'b000101_00111_00000_0000_0000_0000_0100;//bne,r7,r0,else(+4)//{// MOV r7, setFlag //设置本程序的占用标志//ori R7,ffff -- R7 --0000ffffinstmem [8] = 32'h3407ffff; //ori R7 ffff// SC r7, 0x20(r1) //设置到信号量里instmem [9] = 32'b111000_00001_00111_0000_0000_0010_0000;//sc r7,0x20(r1)// if(r7 == 1) goto Success//如果信号量设置成功,r1就会为1//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r1,r0,Success(+2)instmem [10] = 32'b000101_00111_00000_0000_0000_0000_0010;//bne,r7,r0,Success(+2)// //如果信号量没有设置成功,重新读信号量,即重新执行LL指令// else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [11] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //}//else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [12] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //Success:// 访问指定的存储区域// set r7,clearFlag//andi R7,0000 -- R7 --00000000instmem [13] = 32'h30070000; //andi R7,0000// lw r7,(0x20)r1instmem[14]=32'b100011_00001_00111_0000_0000_0010_0000; //lw r7,0x20(r1)

4实现中断异常相关指令-2
测试syscall
//测试中断指令//测试syscallinstmem[6]=32'h0000000c;//syscall instructioninstmem[7]=32'h3407ffff;//oriinstmem[8]=32'h3408ffff;//oriinstmem [16]=32'h340affff;//syscall except programinstmem [17]=32'h340bffff;//oriinstmem [18]=32'h42000018;//eret inatruction

测试定时中断
//测试定时中断instmem[0] =32'h34020000; //ori $2, $0,0instmem[1]= 32'h34010014; //ori $1, $0,20instmem[2]= 32'h40815800; //mtc0 $1,$11 set compare=20instmem[3]=32'h3c011000; //lui $1, 0x1000instmem[4]=32'h34210401; //ori $1, $1,0x0401instmem[5]= 32'h40816000; //mtc0 $1,$12 set status,enable intinstmem[6]= 32'h08000006; //lpt: j lpt//interproc first addr Ox0050instmem[20]= 32'h34030001; //ORI $3,$0,1instmem[21]= 32'h34040014; //ORI S4, $0,20instmem[22]= 32'h00431020; //ADD $2,$2,$3instmem[23]= 32'h40015800; //MFC $1,$11 read compareinstmem[24]=32'h00240820; //ADD $1,$1,$4instmem[25]= 32'h40815800; //MTC0 s1,$11 set compareinstmem[26]= 32'h42000018; //eret
0-6

等待count== compare

然后执行中断程序
执行完成异常返回

继续等待count== compare

测试原子指令-失败案例
在原有的sc指令的前面添加系统调用指令
把LLbit<-0
导致sc把r7<-0
//测试原子功能--失败测试//R1=00001100 R2=00000020 //Lpt: LL r7,0x20(r1) //读取程序里的信号量,LLibt=1//ll r7,0x20(r2) --(r7)=mem[72]=0instmem [6] = 32'b110000_00001_00111_0000_0000_0010_0000;//ll r7,0x20(r1)//if(r7 == clearFlag) //判断信号是否被占用,为clearFlag表示没占用//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r7,r0,else(+4)instmem [7] = 32'b000101_00111_00000_0000_0000_0000_0100;//bne,r7,r0,else(+4)//{// MOV r7, setFlag //设置本程序的占用标志//ori R7,ffff -- R7 --0000ffffinstmem [8] = 32'h3407ffff; //ori R7 ffff//系统调用 把LLbit<-0instmem[9]=32'h0000000c;//syscall instruction// SC r7, 0x20(r1) //设置到信号量里 设置失败因为LLbit=0instmem [10] = 32'b111000_00001_00111_0000_0000_0010_0000;//sc r7,0x20(r1)// if(r7 == 1) goto Success//如果信号量设置成功,r1就会为1//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r1,r0,Success(+2)instmem [11] = 32'b000101_00111_00000_0000_0000_0000_0010;//bne,r7,r0,Success(+2)// //如果信号量没有设置成功,重新读信号量,即重新执行LL指令// else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [12] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //}//else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [13] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //Success:// 访问指定的存储区域// set r7,clearFlag//andi R7,0000 -- R7 --00000000instmem [14] = 32'h30070000; //andi R7,0000// lw r7,(0x20)r1instmem[15]=32'b100011_00001_00111_0000_0000_0010_0000; //lw r7,0x20(r1)//系统调用程序instmem [16]=32'h340affff;//syscall except programinstmem [17]=32'h340bffff;//oriinstmem [18]=32'h42000018;//eret inatruction

附录
其余与上篇一样
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
`define SetFlag 1'b1 //检查LLbit的值,控制信号,不是数据信号
`define ClearFlag 1'b0 //检查LLbit的值,控制信号,不是数据信号//MEM宏编译
`define RamWrite 1'b1
`define RamUnWrite 1'b0
`define RamEnable 1'b1
`define RamDisable 1'b0//中断编码
`define ZeroWord 32'h0000_0000
`define IntrOccur 1'b1
`define IntrNotOccur 1'b0
//cp0中各寄存器地址
`define CP0_count 5'd9
`define CP0_compare 5'd11
`define CP0_status 5'd12
`define CP0_epc 5'd14
`define CP0_cause 5'd13//指令外部编码//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'b110000 //i
`define Inst_sc 6'b111000 //i`define Inst_syscall 32'b000000_00000_000000000000000_001100//全译码
`define Inst_eret 32'b010000_10000_000000000000000_011000//全译码
`define Inst_cp0 6'b010000
`define Inst_mfc0 5'b00000 //010000扩展编码
`define Inst_mtc0 5'b00100 //010000扩展编码//另外
//`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`define Mfhi 6'b010111
`define Mflo 6'b011000
`define Mthi 6'b011001
`define Mtlo 6'b011010
`define Ll 6'b011011
`define Sc 6'b011100`define Syscall 6'b011101
`define Eret 6'b011110
`define Mfc0 6'b011111
`define Mtc0 6'b100001
2 IF 取值
`include "define.v";
//IF 取指模块
//1、控制PC,程序计数器module IF(input wire clk,input wire rst, input wire [31:0] jAddr,//J型input wire jCe,//J型output reg ce, output reg [31:0] pc,input wire[31:0] ejpc, //异常或中断转移地址input wire excpt //异常或中断有效信号
);always@(*)if(rst == `RstEnable)ce = `RomDisable;elsece = `RomEnable;//程序执行 pc+=4//中断-修改always@(posedge clk)if(ce == `RomDisable)pc = `Zero;else if(excpt == 1'b1)pc <=ejpc;//异常或中断的转移地址更新pcelse if(jCe == `Valid)//J型pc = jAddr;elsepc = pc + 4;endmodule
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型input wire [31:0] pc_i,//将原来输入pc变为pc_ioutput wire[31:0] pc,//新增输出pcoutput wire[31:0] excptype//异常信息记录
);//操作指令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;//中断reg is_syscall;reg is_eret;assign pc = pc_i;assign excptype= {22'b0, is_eret, is_syscall,8'b0};always@(*)if(rst == `RstEnable)beginop = `Nop; regaRead = `Invalid;regbRead = `Invalid;regcWrite = `Invalid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = `Zero;imm = `Zero;jCe = `Invalid;//J型jAddr = `Zero;//J型is_eret = `Invalid;//中断is_syscall = `Invalid;//中断endelse if(inst == `Inst_eret)beginop =`Eret;regaRead = `Invalid;regbRead = `Invalid;regcWrite= `Invalid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = `Zero;imm= `Zero;jCe=`Invalid;jAddr=`Zero;is_eret = `Valid;is_syscall = `Invalid;endelse if(inst == `Inst_syscall)beginop = `Syscall;regaRead = `Invalid;regbRead= `Invalid;regcWrite = `Invalid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = `Zero;imm= `Zero;jCe=`Invalid;jAddr=`Zero;is_eret = `Invalid;is_syscall = `Valid;endelse begin//后面的endjCe = `Invalid;//J型jAddr = `Zero;//J型is_eret = `Invalid;//中断is_syscall = `Invalid;//中断case(inst_op)`Inst_cp0:case(inst[25:21])`Inst_mfc0:beginop = `Mfc0;regaRead = `Invalid;regbRead = `Invalid;regcWrite = `Valid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = inst[20:16];imm= {27'h0, inst[15:11]};end`Inst_mtc0:beginop =`Mtc0;regaRead = `Invalid;regbRead = `Valid;regcWrite = `Invalid;regaAddr = `Zero;regbAddr = inst[20:16];regcAddr = `Zero;imm= {27'h0, inst[15:11]};enddefault:beginop= `Nop;regaRead = `Invalid;regbRead = `Invalid;regcWrite = `Invalid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = `Zero;imm= `Zero;endendcase`Inst_ori:beginop = `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:beginop = `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:beginop = `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:beginop = `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:beginop = `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:beginop = `Add; regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[15:11];imm = `Zero;end`Inst_or:beginop = `Or;regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[15:11];imm = `Zero;end`Inst_sub:beginop = `Sub;regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[15:11];imm = `Zero;end`Inst_and:beginop = `And;regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[15:11];imm = `Zero;end`Inst_xor:beginop = `Xor;regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[15:11];imm = `Zero;end`Inst_sll:beginop = `Sll;regaRead = `Invalid;regbRead = `Valid;regcWrite = `Valid;regaAddr = `Zero;regbAddr = inst[20:16];regcAddr = inst[15:11];imm = {27'b0,inst[10:6]};//移位复用immend`Inst_srl:beginop = `Srl;regaRead = `Invalid;regbRead = `Valid;regcWrite = `Valid;regaAddr = `Zero;regbAddr = inst[20:16];regcAddr = inst[15:11];imm = {27'b0,inst[10:6]};//移位复用immend`Inst_sra:beginop = `Sra;regaRead = `Invalid;regbRead = `Valid;regcWrite = `Valid;regaAddr = `Zero;regbAddr = inst[20:16];regcAddr = inst[15:11];imm = {27'b0,inst[10:6]};//移位复用immend//JR型指令`Inst_jr:beginop = `J;regaRead = `Valid;//需要读rsregbRead = `Invalid;regcWrite = `Invalid;regaAddr = inst[25:21];regbAddr = `Zero;regcAddr = `Zero;jAddr = regaData;//regaData=(regaAddr)jCe = `Valid;imm = `Zero;end`Inst_jalr:beginop = `Jal;regaRead = `Valid;regbRead = `Invalid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = `Zero;regcAddr = 5'b11111;jAddr = regaData;jCe = `Valid;imm = npc;//regbData中存imm npcend//12条整数指令`Inst_slt:beginop = `Slt;regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[15:11];imm = `Zero;end //乘除指令`Inst_mult:beginop = `Mult;regaRead = `Valid;regbRead = `Valid;regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = `Zero;imm = `Zero;end `Inst_multu:beginop = `Multu;regaRead = `Valid;regbRead = `Valid;regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = `Zero;imm = `Zero;end `Inst_div:beginop = `Div;regaRead = `Valid;regbRead = `Valid;regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = `Zero;imm = `Zero;end `Inst_divu:beginop = `Divu;regaRead = `Valid;regbRead = `Valid;regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = `Zero;imm = `Zero;end //后4条指令`Inst_mfhi:beginop = `Mfhi;regaRead = `Invalid;regbRead = `Invalid;regcWrite = `Valid;//从HILO寄存器中,写到通用寄存器中regaAddr = `Zero;regbAddr = `Zero;regcAddr = inst[15:11];imm = `Zero;//HiLo的数据在EX中得到end `Inst_mflo:beginop = `Mflo;regaRead = `Invalid;regbRead = `Invalid;regcWrite = `Valid;//从HILO寄存器中,写到通用寄存器中regaAddr = `Zero;regbAddr = `Zero;regcAddr = inst[15:11];imm = `Zero;//HiLo的数据在EX中得到end `Inst_mthi:beginop = `Mthi;regaRead = `Valid;//从通用寄存器读出regbRead = `Invalid;regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中regaAddr = inst[25:21]; regbAddr = `Zero;regcAddr = `Zero;imm = `Zero;end `Inst_mtlo:beginop = `Mtlo;regaRead = `Valid;//从通用寄存器读出regbRead = `Invalid;regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中 regaAddr = inst[25:21];regbAddr = `Zero;regcAddr = `Zero;imm = `Zero;end default:beginregaRead = `Invalid;regbRead = `Invalid;regcWrite = `Invalid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = `Zero;imm = `Zero;endendcase//J型指令`Inst_j:beginop = `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:beginop = `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:beginop = `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;//等于有效elsejCe = `Invalid;imm = `Zero;end `Inst_bne:beginop = `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;//等于有效elsejCe = `Invalid;imm = `Zero;end `Inst_bltz:beginop = `Bltz;regaRead = `Valid;regbRead = `Valid;//若regbRead无效,则regbData=imm=0regcWrite = `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;//小于有效elsejCe = `Invalid;imm = 32'b0;end `Inst_bgtz:beginop = `Bgtz;regaRead = `Valid;//regbRead = `Valid;//若regbRead有效,则regbData=(regbAddr)regbRead = `Invalid;//若regbRead无效,则regbData=imm=0regcWrite = `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;//大于有效elsejCe = `Invalid;imm = 32'b0;end //Load Store指令`Inst_lw:beginop = `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:beginop = `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 //ll sc`Inst_ll:beginop = `Ll;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_sc:beginop = `Sc;regaRead = `Valid;regbRead = `Valid;regcWrite = `Valid;//还需给rt赋值为1regaAddr = inst[25:21];regbAddr = inst[20:16];regcAddr = inst[20:16];//还需给rt赋值为1imm = {{16{inst[15]}},inst[15:0]};end default:beginop = `Nop; regaRead = `Invalid;regbRead = `Invalid;regcWrite = `Invalid;regaAddr = `Zero;regbAddr = `Zero;regcAddr = `Zero;imm = `Zero;endendcase end/*//二选一 regaData= regaData_i : immalways@(*)if(rst == `RstEnable)regaData = `Zero;else if(regaRead == `Valid)regaData = regaData_i;else regaData = imm;//二选一 regbData= regbData_i : immalways@(*)if(rst == `RstEnable)regbData = `Zero; else if(regbRead == `Valid)regbData = regbData_i;elseregbData = 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) regaData = `Zero; else if(op == `Lw || op == `Sw || op==`Ll || op==`Sc) 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 执行
`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数据output reg cp0we, //CPO寄存器的写信号output reg [4:0] cp0Addr, //CPO寄存器的地址信号output reg [31:0] cp0wData, //CPO寄存器的写入数据input wire[31:0] cp0rData, //CPO寄存器的读出数据input wire[31:0] pc_i, //当前指令地址input wire [31:0] excptype_i,//输入的异常或中断信息记录output reg [31:0] excptype, //输出的异常或中断信息记录output wire [31:0] epc, //输出的epc值,用于eret 指令output wire [31:0] pc, //输出的pc值,用于异常或中断响应input wire [31:0] cause, //输入的cause寄存器值input wire [31:0] status //输入的status寄存器值); assign op = op_i;assign memAddr = regaData;assign memData = regbData;//中断assign pc = pc_i;//还是需要给MEM传送指令的 LLbit<-0
// assign op = (excptype == `ZeroWord) ?
// op_i : `Nop;assign regcWrite =(excptype == `ZeroWord) ?regcWrite_i : `Invalid;always@(*)if(rst == `RstEnable)beginregcData = `Zero;whi=`Invalid;wlo=`Invalid;wHiData=`Zero;wLoData=`Zero;endelsebeginregcData = `Zero;whi=`Invalid;wlo=`Invalid;wHiData=`Zero;wLoData=`Zero;cp0we=`Invalid;cp0wData= `Zero;cp0Addr =`CP0_epc; //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:beginregcData = 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:beginif($signed(regaData)<$signed(regbData))regcData={{31{1'b0}},1'b1};elseregcData={32{1'b0}};end//乘除指令`Mult:beginwhi=`Valid;wlo=`Valid;{wHiData,wLoData}=$signed(regaData)*$signed(regbData);end`Multu:beginwhi=`Valid;wlo=`Valid;{wHiData,wLoData}=regaData*regbData;end`Div:beginwhi=`Valid;wlo=`Valid;wHiData=$signed(regaData)%$signed(regbData);wLoData=$signed(regaData)/$signed(regbData);end`Divu:beginwhi=`Valid;wlo=`Valid;wHiData=regaData%regbData;wLoData=regaData/regbData;end//剩余4条指令`Mfhi: regcData = rHiData;`Mflo: regcData = rLoData;`Mthi: begin whi=`Valid;wHiData = regaData;end`Mtlo: begin wlo=`Valid; wLoData = regaData;end//原子`Sc:regcData = 32'b1;//中断`Mfc0:begincp0Addr = regaData[4:0];regcData = cp0rData;end`Mtc0:beginregcData= `Zero;cp0we = `Valid;cp0Addr = regaData[4:0];cp0wData = regbData;enddefault:regcData = `Zero;endcase end/*增加关于中断查询和响应的代码*///tips:cp0rData默认读出的是epc的地址assign epc = (excptype == 32'h0000_0200) ? cp0rData : `Zero;always@(*)if(rst ==`RstEnable)excptype = `Zero;//Cause's IP[2] Status's IM[2]; Status EXL, IEelse if(cause[10]&& status[10]== 1'b1 && status[1:0] == 2'b01)//timerIntexcptype = 32'h0000_0004;else if(excptype_i[8] == 1'b1 && status[1] == 1'b0)//Syscallexcptype = 32'h00000100;else if(excptype_i[9]== 1'b1)//Eretexcptype = 32'h0000_0200;elseexcptype = `Zero;assign regcWrite = regcWrite_i;assign regcAddr = regcAddr_i;endmodule
5 MEM 访存
`include "define.v";
//访存(mem)模块设计
module MEM(input wire rst, input wire [5:0] op,input wire [31:0] regcData,input wire [4:0] regcAddr,input wire regcWr,input wire [31:0] memAddr_i,input wire [31:0] memData, input wire [31:0] rdData,input wire rLLbit, //llscoutput wire [4:0] regAddr,output wire regWr,output wire [31:0] regData, output wire [31:0] memAddr,output reg [31:0] wtData,output reg memWr, output reg memCe,output reg wbit, //llscoutput reg wLLbit //llsc
);assign regAddr = regcAddr; assign regWr = regcWr;
// assign regData = (op == `Lw) ? rdData : regcData; //因为regData是wire型的,所以为了不修改原来的代码,就不使用always//而是修改regcData的值,来传到regData//二选一,选出Sc指令的rt<-1或rt<0wire [31:0]regDataLL= (rLLbit==`SetFlag) ? 32'b1 : 32'b0; //二选一,存往regFile的值 sc指令存的值regcDataLL 还是 寄存器传入的值regcDatawire [31:0]regcDataLL= (op == `Sc ) ? regDataLL : regcData;//二选一,存往regFile的值 lw取得的值rdData 还是 寄存器传入的值regcDataassign regData = (op == `Lw) ? rdData : regcDataLL; assign memAddr = memAddr_i;always @ (*) if(rst == `RstEnable) begin wtData = `Zero; memWr = `RamUnWrite; memCe = `RamDisable; wbit= `Invalid;wLLbit=`ClearFlag;end elsebeginwtData = `Zero; memWr = `RamUnWrite; memCe = `RamDisable; wbit= `Invalid;wLLbit=`ClearFlag;case(op) `Lw: begin wtData = `Zero; memWr = `RamUnWrite; memCe = `RamEnable; end `Sw: begin wtData = memData; memWr = `RamWrite; memCe = `RamEnable; end//Ll Sc`Ll:begin //rt<-datamem[addr]//不需要写到DataMem中wtData = `Zero; memWr = `RamUnWrite; memCe = `RamEnable; //LLbit<-1wbit=`Valid;wLLbit = `SetFlag;end`Sc:begin if(rLLbit==`SetFlag)begin //datamem[addr]<-rtwtData = memData; memWr = `RamWrite; memCe = `RamEnable; //rt<-1//在EX中实现//LLbit<-0wbit=`Valid;wLLbit = `ClearFlag;endelsebegin//把rt<-0//在Mem前面对regcData处理来实现endend`Syscall:begin//LLbit<-0wbit=`Valid;wLLbit = `ClearFlag;end`Eret:begin//LLbit<-0wbit=`Valid;wLLbit = `ClearFlag;enddefault: begin wtData = `Zero; memWr = `RamUnWrite; memCe = `RamDisable; wbit= `Invalid;wLLbit=`ClearFlag; end endcaseend
endmodule
6 DataMem 数据存储器
`include "define.v";
//数据存储器(DataMem)模块设计
module DataMem(input wire clk,input wire ce,input wire we,input wire [31:0] addr,input wire [31:0] wtData,output reg [31:0] rdData
);reg [31:0] datamem [1023 : 0];always@(*) if(ce == `RamDisable)rdData = `Zero;elserdData = datamem[addr[11 : 2]]; always@(posedge clk)if(ce == `RamEnable && we == `RamWrite)datamem[addr[11 : 2]] = wtData;else ;endmodule
7 RegFile 存取
`include "define.v";
//4、为操作数取值存值模块
//取值 regaData regbData
//存值 wdata
module RegFile(input wire clk,input wire rst,input wire we,input wire [4:0] waddr,input wire [31:0] wdata,input wire regaRead,input wire regbRead,input wire [4:0] regaAddr,input wire [4:0] regbAddr,output reg [31:0] regaData,output reg [31:0] regbData
);reg [31:0] reg32 [31 : 0];always@(*)if(rst == `RstEnable) regaData = `Zero;else if(regaAddr == `Zero)regaData = `Zero;elseregaData = reg32[regaAddr];always@(*)if(rst == `RstEnable) regbData = `Zero;else if(regbAddr == `Zero)regbData = `Zero;else regbData = reg32[regbAddr];always@(posedge clk)if(rst == `RstDisable)if((we == `Valid) && (waddr != `Zero))reg32[waddr] = wdata;else ;else ;endmodule
A 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)beginrHiData = `Zero;rLoData = `Zero;endelsebeginrHiData = hi;rLoData = lo;endalways@(posedge clk)if (rst ==`RstDisable && whi==`Valid)hi=wHiData;else ;always@(posedge clk)if (rst ==`RstDisable && wlo==`Valid)lo=wLoData;else ;
endmodule
B LLbit LLbit寄存器
`include "define.v"
//LLbit寄存器
module LLbit(input wire clk,input wire rst,input wire excpt,input wire wbit, //写信号input wire wLLbit, //写数据output reg rLLbit //读数据
);reg LLbit;//内部存储 always@(*)if(rst == `RstEnable)rLLbit = `Zero;elserLLbit = LLbit;always@(posedge clk)if(rst ==`RstDisable && wbit==`Valid)LLbit=wLLbit;else ;endmodule
C CP0 协处理器
`include "define.v"
//协处理器模块
module CP0(input wire clk, //时钟信号input wire rst, //复位信号input wire cp0we, //CP0寄存器的写信号input wire[4:0] cp0Addr, //CP0寄存器的地址信号input wire[31:0] cp0wData, //CP0寄存器的写入数据output reg[31:0] cp0rData, //CP0寄存器的读出数据input wire[5:0] intr, //输入硬件中断output reg intimer, //输出定时中断input wire[31:0] excptype,//异常和中断的记录信息input wire[31:0] pc, //当前指令地址output wire[31:0] cause, //寄存器Cause的输出值output wire[31:0] status //寄存器Status的输出值
);reg[31:0] Count;reg[31:0] Compare;reg[31:0] Status;reg[31:0] Cause;reg[31:0] Epc;assign cause = Cause;assign status = Status;always@(*)Cause[15:10]= intr;//对应IP[7:2]always@(posedge clk)if(rst == `RstEnable)beginCount= `Zero;Compare = `Zero;Status= 32'h10000000;Cause = `ZeroWord;Epc = `Zero;intimer = `IntrNotOccur;endelsebeginCount = Count + 1;if(Compare != `Zero && Count == Compare)intimer = `IntrOccur;if(cp0we == `Valid)case(cp0Addr)`CP0_count:Count = cp0wData;`CP0_compare:beginCompare = cp0wData;intimer = `IntrNotOccur;end`CP0_status:Status = cp0wData;`CP0_epc:Epc = cp0wData;`CP0_cause:beginCause[9:8]=cp0wData[9:8];Cause[23:22]= cp0wData[23:22];enddefault: ;endcasecase(excptype)//timerInt32'h0000_0004:begin//interupt instructionEpc = pc;//Status's Ex1Status[1]=1'b1;//Cause's ExcCodeCause[6:2]= 5'b00000;end//Syscall32'h0000_0100:beginEpc = pc+ 4;Status[1]= 1'b1;Cause[6:2]= 5'b01000;end//Eret32'h0000_0200:Status[1]=1'b0;default : ;endcaseendalways@(*)if(rst==`RstEnable)cp0rData= `Zero;elsecase(cp0Addr)`CP0_count:cp0rData = Count ;`CP0_compare:cp0rData = Compare;`CP0_status:cp0rData = Status;`CP0_epc:cp0rData = Epc;`CP0_cause:cp0rData= Cause;default:cp0rData= `Zero;endcase
endmodule
D Ctrl 控制模块
`include "define.v"
//控制模块
module Ctrl(input wire rst, //复位信号input wire[31:0] excptype, //异常或中断信息记录input wire [31:0] epc, //输入epc的值,用于eret 指令output reg [31:0] ejpc, //输出ejpc的值output reg excpt //中断或异常有效信号
);always@(*)if(rst == `RstEnable)beginexcpt = `Invalid;ejpc = `Zero;endelsebeginexcpt = `Valid;case(excptype)//timerInt32'h0000_0004:ejpc = 32'h00000050;//自己指定:中断服务地址 50h右移2位(即除以4)=20 instMem//Syscall32'h0000_0100:ejpc= 32'h00000040;//自己指定:中断服务地址 40h右移2位(即除以4)=16 instMem//Eret32'h0000_0200:ejpc = epc;default:beginejpc= `Zero;excpt = `Invalid;endendcaseend
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,//lsoutput wire romCe,output wire [31:0] instAddr,output wire [31:0] wtData,//lsoutput wire [31:0] memAddr,//lsoutput wire memCe,//lsoutput wire memWr,//lsinput wire[5:0] intr, //硬件中断的输入信号output wire intimer //定时中断的输出信号
);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;//lswire [5:0] op_ex;wire[31:0] memAddr_ex,memData_ex;wire [4:0] regAddr_mem;wire [31:0] regData_mem;wire regWr_mem;//md-hlwire [31:0] wHiData_ex;wire [31:0] wLoData_ex;wire whi;wire wlo;wire [31:0] rHiData_ex;wire [31:0] rLoData_ex;//llscwire excpt;wire wbit;wire wLLbit;wire rLLbit;//中断wire cp0we;wire[4:0] cp0Addr;wire[31:0] cp0wData;wire[31:0] cp0rData;wire[31:0] epc_ex , ejpc;wire[31:0] excptype_id,excptype_ex;wire[31:0] cause, status;wire[31:0] pc_id, pc_ex;//中断修改IF if0(.clk(clk),.rst(rst),.jAddr(jAddr),//J型.jCe(jCe),//J型.ce(romCe), .pc(instAddr),.ejpc(ejpc),//异常或中断转移地址.excpt(excpt)//异常或中断信号);//中断修改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型.pc_i(instAddr),//pc的输入信号.pc(pc_id), //pc的输出信号.excptype(excptype_id)//中断或异常的记录信息);//乘除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.cp0we(cp0we),//CPO的写信号.cp0Addr(cp0Addr),//CPO的地址信息.cp0wData(cp0wData),//CPO的写入数据.cp0rData(cp0rData),//CPO的读出数据.pc_i(pc_id),//pc的输入值.excptype_i(excptype_id),//异常或中断的记录信息输入值.excptype(excptype_ex),//异常或中断的记录信息输出值.epc(epc_ex),//epc的输出值.pc(pc_ex),//pc的输出值.cause(cause),//cause的输入值.status(status)//status的输入值); //新增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实例化 llscMEM mem0(.rst(rst), .op(op_ex),.regcData(regcData_ex),.regcAddr(regcAddr_ex),.regcWr(regcWrite_ex),.memAddr_i(memAddr_ex),.memData(memData_ex), .rdData(rdData),.rLLbit(rLLbit),//llsc.regAddr(regAddr_mem),.regWr(regWr_mem),.regData(regData_mem), .memAddr(memAddr),.wtData(wtData),.memWr(memWr), .memCe(memCe),.wbit(wbit), //llsc.wLLbit(wLLbit)//llsc);//新增LLbit实例化 llscLLbit llbit0(.clk(clk),.rst(rst),.excpt(excpt),.wbit(wbit), .wLLbit(wLLbit), .rLLbit(rLLbit));//修改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));//中断-新增加模块CP0 cp0(.clk(clk),.rst(rst),.cp0we(cp0we),.cp0wData(cp0wData),.cp0Addr(cp0Addr),.cp0rData(cp0rData),.intr(intr),.intimer(intimer),.pc(pc_ex),.excptype(excptype_ex),.cause(cause),.status(status));//中断-新增加模块Ctrl ctrl0(.rst(rst),.ejpc(ejpc),.excpt(excpt),.excptype(excptype_ex),.epc(epc_ex));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;elsedata = instmem[addr[11 : 2]]; initialbegin//指令测试/*//初始化数据//ori R0,1100 -- R1 --00001100instmem [0] = 32'h34011100;//ori R0,0020 -- R2 --00000020instmem [1] = 32'h34020020;//ori R0,ff00 -- R3 --0000ff00instmem [2] = 32'h3403ff00;//ori R0,ffff -- R4 --0000ffffinstmem [3] = 32'h3404ffff;
*///I型指令测试
/*//andi R0,ffff --R5 --00000000instmem [4] = 32'h3005ffff;//xori R0,ffff --R6 --0000ffffinstmem [5] = 32'h3806ffff;//addi R0,ffff --R7 --ffffffffinstmem [6] = 32'h2007ffff;
// //subi R0,ffff --R8 --00000001
// instmem [7] = 32'h2408ffff;//lui R0,ffff --R9 --ffff0000instmem [8] = 32'h3C09ffff;
*//* //R1=00001100 R2=00000020instmem [4] = 32'b000000_00001_00010_00101_00000_100000;//add,R5,R1,R2 00001120instmem [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 000010e0instmem [7] = 32'b000000_00001_00010_01000_00000_100100;//and,R8,R1,R2 00000000instmem [8] = 32'b000000_00001_00010_01001_00000_100110;//xor,R9,R1,R2 00001120//lui R0,ffff --R10 --ffff0000instmem [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,R10instmem [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=0000000Cinstmem [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 --00000001instmem [7] = 32'h34070001; //ori R7 1//ori R8,0001 -- R8 --00000001instmem [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=00000020instmem [6] = 32'b000000_00001_00010_00111_00000_101010;//slt,R7,R1,R2 00000000//lui R0,ffff --R8 --ffff0000instmem [7] = 32'h3C08ffff;//ori R8,ffff --R8 --ffffffffinstmem [8] = 32'b001101_01000_01000_1111_1111_1111_1111;//lui R0,ffff --R9 --ffff0000instmem [9] = 32'h3C09ffff;//ori R9,ffff --R9 --fffffffeinstmem [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_22000instmem [6] = 32'b000000_00001_00010_00111_00000_011001;//multu,R1,R2//ori R7,ffff -- R7 --0000ffffinstmem [7] = 32'h3407ffff; //ori R7 ffff//sll R7,R7,10h -- R7 --ffff0000instmem [8] = 32'b000000_00000_00111_00111_10000_000000;//sll R7,R7,10h//mult R7,R2 ffffffff_ffe00000instmem [9] = 32'b000000_00111_00010_00000_00000_011000;//mult R7,R2//divu r1,r2 88_0instmem [10] = 32'b000000_00001_00010_00000_00000_011011;//divu r1,r2//div r3,r2 fffff800_0instmem [11] = 32'b000000_00111_00010_00000_00000_011010;//div r7,r2
*//*//测试剩余4条指令//R1=00001100 R2=00000020 //mthi,R1--hi=00001100instmem [6] = 32'b000000_00001_00000_00000_00000_010001;//mthi,R1//mtlo,R2--lo=00000020 instmem [7] = 32'b000000_00010_00000_00000_00000_010011;//mtlo,R2//mfhi,R7--R7=00001100instmem [8] = 32'b000000_00000_00000_00111_00000_010000;//mfhi,R7//mflo,R8--R8=00000020 instmem [9] = 32'b000000_00000_00000_01000_00000_010010;//mflo,R8
*//*//测试原子指令//计算地址说明//(r1)=0000 1100// +0000 0020//addr=0000 1120 // =1000100100000 字节地址// =100 0100 1000 字地址// =448H 只有1K空间// =48H 丢掉了高位的1位// =72//mem[72]<-->(r7)//测试功能//R1=00001100 R2=00000020 //Lpt: LL r7,0x20(r1) //读取程序里的信号量,LLibt=1//ll r7,0x20(r2) --(r7)=mem[72]=0instmem [6] = 32'b110000_00001_00111_0000_0000_0010_0000;//ll r7,0x20(r1)//if(r7 == clearFlag) //判断信号是否被占用,为clearFlag表示没占用//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r7,r0,else(+4)instmem [7] = 32'b000101_00111_00000_0000_0000_0000_0100;//bne,r7,r0,else(+4)//{// MOV r7, setFlag //设置本程序的占用标志//ori R7,ffff -- R7 --0000ffffinstmem [8] = 32'h3407ffff; //ori R7 ffff// SC r7, 0x20(r1) //设置到信号量里instmem [9] = 32'b111000_00001_00111_0000_0000_0010_0000;//sc r7,0x20(r1)// if(r7 == 1) goto Success//如果信号量设置成功,r1就会为1//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r1,r0,Success(+2)instmem [10] = 32'b000101_00111_00000_0000_0000_0000_0010;//bne,r7,r0,Success(+2)// //如果信号量没有设置成功,重新读信号量,即重新执行LL指令// else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [11] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //}//else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [12] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //Success:// 访问指定的存储区域// set r7,clearFlag//andi R7,0000 -- R7 --00000000instmem [13] = 32'h30070000; //andi R7,0000// lw r7,(0x20)r1instmem[14]=32'b100011_00001_00111_0000_0000_0010_0000; //lw r7,0x20(r1)
*///测试中断指令/* //测试syscallinstmem[6]=32'h0000000c;//syscall instructioninstmem[7]=32'h3407ffff;//oriinstmem[8]=32'h3408ffff;//oriinstmem [16]=32'h340affff;//syscall except programinstmem [17]=32'h340bffff;//oriinstmem [18]=32'h42000018;//eret inatruction
*//*//测试定时中断instmem[0] =32'h34020000; //ori $2, $0,0instmem[1]= 32'h34010014; //ori $1, $0,20instmem[2]= 32'h40815800; //mtc0 $1,$11 set compare=20instmem[3]=32'h3c011000; //lui $1, 0x1000instmem[4]=32'h34210401; //ori $1, $1,0x0401instmem[5]= 32'h40816000; //mtc0 $1,$12 set status,enable intinstmem[6]= 32'h08000006; //lpt: j lpt//interproc first addr Ox0050instmem[20]= 32'h34030001; //ORI $3,$0,1instmem[21]= 32'h34040014; //ORI S4, $0,20instmem[22]= 32'h00431020; //ADD $2,$2,$3instmem[23]= 32'h40015800; //MFC $1,$11 read compareinstmem[24]=32'h00240820; //ADD $1,$1,$4instmem[25]= 32'h40815800; //MTC0 s1,$11 set compareinstmem[26]= 32'h42000018; //eret
*///测试原子功能--失败测试//R1=00001100 R2=00000020 //Lpt: LL r7,0x20(r1) //读取程序里的信号量,LLibt=1//ll r7,0x20(r2) --(r7)=mem[72]=0instmem [6] = 32'b110000_00001_00111_0000_0000_0010_0000;//ll r7,0x20(r1)//if(r7 == clearFlag) //判断信号是否被占用,为clearFlag表示没占用//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r7,r0,else(+4)instmem [7] = 32'b000101_00111_00000_0000_0000_0000_0100;//bne,r7,r0,else(+4)//{// MOV r7, setFlag //设置本程序的占用标志//ori R7,ffff -- R7 --0000ffffinstmem [8] = 32'h3407ffff; //ori R7 ffff//系统调用 把LLbit<-0instmem[9]=32'h0000000c;//syscall instruction// SC r7, 0x20(r1) //设置到信号量里 设置失败因为LLbit=0instmem [10] = 32'b111000_00001_00111_0000_0000_0010_0000;//sc r7,0x20(r1)// if(r7 == 1) goto Success//如果信号量设置成功,r1就会为1//pc=jaddr=npc+S14 offset(16) 00(2)//bne,r1,r0,Success(+2)instmem [11] = 32'b000101_00111_00000_0000_0000_0000_0010;//bne,r7,r0,Success(+2)// //如果信号量没有设置成功,重新读信号量,即重新执行LL指令// else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [12] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //}//else goto Lpt//j Lpt(6)//pc=jaddr=npc(4) offset(26) 00(2) instmem [13] = 32'h08000006;//j Lpt(6) 编码000010 pc=0018 //Success:// 访问指定的存储区域// set r7,clearFlag//andi R7,0000 -- R7 --00000000instmem [14] = 32'h30070000; //andi R7,0000// lw r7,(0x20)r1instmem[15]=32'b100011_00001_00111_0000_0000_0010_0000; //lw r7,0x20(r1)//系统调用程序instmem [16]=32'h340affff;//syscall except programinstmem [17]=32'h340bffff;//oriinstmem [18]=32'h42000018;//eret inatructionend
endmodule
10 SOC 顶层
//7、系统封装
//整合MIPS DataMem InstMem
//端口信号只需clk rst,其余信号在MIPS中增加,并且新增使用内部信号连线
module SoC(input wire clk,input wire rst
);wire [31:0] instAddr;wire [31:0] instruction;wire romCe;//lswire memCe, memWr; wire [31:0] memAddr;wire [31:0] rdData;wire [31:0] wtData;//中断wire[5:0] intr;wire intimer;assign intr={5'b0,intimer};//修改MIPS实例//中断-修改MIPS mips0(.clk(clk),.rst(rst),.instruction(instruction),.instAddr(instAddr),.romCe(romCe),.rdData(rdData), .wtData(wtData), .memAddr(memAddr), .memCe(memCe), .memWr(memWr),.intr(intr),//中断.intimer(intr[0])//中断); InstMem instrom0(.ce(romCe),.addr(instAddr),.data(instruction));//新增DataMem实例化DataMem datamem0( .ce(memCe), .clk(clk), .we(memWr), .addr(memAddr), .wtData(wtData), .rdData(rdData) );
endmodule
11 soc_tb
`include "define.v";
//8、测试系统
module soc_tb;reg clk;reg rst;initialbeginclk = 0;rst = `RstEnable;#100rst = `RstDisable;#1000 $stop; endalways #10 clk = ~ clk;SoC soc0(.clk(clk), .rst(rst));
endmodule
最后
2023-5-25 08:19:16
你对我百般注视,
并不能构成万分之一的我,
却是一览无余的你。
祝大家逢考必过
点赞收藏关注哦
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
