当前位置:   article > 正文

6设计指令流水线-1【FPGA模型机课程设计】_1idiiiif::if

1idiiiif::if

前言

2023-5-25 09:25:05

以下内容源自《【FPGA模型机课程设计】》
仅供学习交流使用

推荐

0集中实践环节计划书【FPGA模型机课程设计】

修改

2023-5-30 16:03:03

添加MEM_WB模块

2023-5-30 19:00:25
IF模块添加stall

2023-5-30 21:08:26
修改stall相关的处理
在id ctrl 流水寄存器中修改

因为原来没有理解stall[5:0]是什么意思

它的意思就是
当id传入stallreq(1bit)
做一些处理使其扩展为6bit
stall[0]控制pc寄存器,此处是if模块取值
stall[1]控制if_id
stall[2]控制id_ex
stall[3]控制ex_mem
stall[4]控制mem_wb
如果当前是Stop但是下一个stall是NoStop,意味着只停顿一个周期
所以多一个stall[5]

所以在Ctrl中stall和stallreq是左移寄存器的关系

2023-5-30 21:32:36
修改一些Warning
一些信号的位数不匹配

现在,仿真时应该是0Error 0Warning

提示:博客中的代码可能没有修改到位
在这里插入图片描述

2023-6-4 11:30:33

修改MIPS中IF IF_ID ID ID_EX关于pc连线的问题

6设计指令流水线

安排

第二周周一:

设计指令流水线,按照指令周期不同阶段进行划分,实现指令基本流水处理功能。注意数据相关冲突的解决。编写机器指令程序,对指令逐一进行测试,可以使用原有的测试程序,但检测结果时需注意功能和时序的对应关系。

测试与结果

不知道我到底是实现了流水线的功能吗

好像是已经实现了流水功能

但是现在只是基本的流水线的功能
数据冲突和分支和中断异常没有实现

原来的单周期CPU的波形

一个周期产生一个数据

在这里插入图片描述

现在的流水CPU的设计波形

流水线满载(C)后,一个周期产生一个数据
在这里插入图片描述

修改:增加MEM_WB

因为多了一个流水寄存器
所以满载的时候会多一个时钟周期

发现R5 没有结果,因为有数据冲突

在这里插入图片描述
可以看到以下测试代码

		//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;
		//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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到inst[1]和inst[4],中间隔离两条命令,所以有了数据冲突
当inst1执行到MEM时,准备写回R2时
inst4在ID段读出R2,还是没有值的,所以它的R5结果不对

但是inst5的R6结果是对的,因为这个时候R2的结果已经写入进去了

在这里插入图片描述

2023-5-30 16:38:36

指令流水线理论

参考:教学资料

MIPS的一种简单实现

实现MIPS指令子集的一种简单数据通路。
该数据通路的操作分成5个时钟周期

  • 取指令
  • 指令译码/读寄存器
  • 执行/有效地址计算
  • 存储器访问/分支完成
  • 写回

只讨论整数指令的实现(包括:load和store,等于0转移,整数ALU指令等。)

在这里插入图片描述
一条MIPS指令最多需要以下5个时钟周期:

取指令周期(IF)

  • IR←Mem[PC]
  • NPC←PC+4

指令译码/读寄存器周期(ID)

  • A ← Regs[rs]
  • B ← Regs[rt]
  • Imm ← ((IR16)16##IR16…31)
    指令的译码操作和读寄存器操作是并行进行的。
    原因:在MIPS指令格式中,操作码字段以及rs、rt
    字段都是在固定的位置。
    这种技术称为固定字段译码技术。

执行/有效地址计算周期(EX)

 不同指令所进行的操作不同:
  • 1
  • 存储器访问指令
    ALUo←A + Imm
  • 寄存器-寄存器ALU指令
    ALUo←A func B
  • 寄存器-立即值ALU指令
    ALUo←A op Imm
  • 分支指令
    ALUo←NPC+(Imm<<2);
    cond←(A = = 0)

将有效地址计算周期和执行周期合并为一个时钟周期,这是因为MIPS指令集采用load/store结构,没有任何指令需要同时进行数据有效地址的计算、转移目标地址的计算和对数据进行运算。

存储器访问/分支完成周期(MEM)

  • 所有指令都要在该周期对PC进行更新。
    除了分支指令,其他指令都是做PC←NPC
  • 在该周期内处理的MIPS指令仅仅有load、store和分支三种指令。
  • 存储器访问指令
    LMD←Mem[ALUo]
    或者 Mem[ALUo]←B
  • 分支指令
    if (cond) PC ←ALUo else PC←NPC

写回周期(WB)

不同的指令在写回周期完成的工作也不一样。

  • 寄存器-寄存器ALU指令
    Regs[rd]← ALUo
  • 寄存器-立即数ALU指令
    Regs[rt]← ALUo
  • load指令
    Regs[rt]← LMD

基本的MIPS流水线

每一个时钟周期完成的工作看作是流水线的一段,每个时钟周期启动一条新的指令。

1.流水实现的数据通路

设置了流水寄存器

  • 段与段之间设置流水寄存器
  • 流水寄存器的命名
    用其相邻的两个段的名称拼合而成。
    例如:ID段与EX段之间的流水寄存器用ID/EX表示
  • 每个流水寄存器是由若干个寄存器构成的

在这里插入图片描述

  • 寄存器的命名形式为:x.y
  • 所包含的字段的命名形式为:x.y[s]
    其中:x:流水寄存器名称
    y:具体寄存器名称
    s:字段名称
    例如:
    ID/EX.IR:流水寄存器ID/EX中的子寄存器IR
    IRID/EX.IR[op]:该寄存器的op字段(即操作码字段)
  • 流水寄存器的作用
    将各段的工作隔开,使得它们不会互相干扰。
    保存相应段的处理结果。

例如:
EX/MEM.ALUo:保存EX段ALU的运算结果
MEM/WB.LMD:保存MEM段从数据存储器读出的数据
向后传递后面将要用到的数据或者控制信息
所有有用的数据和控制信息每个时钟周期
会随着指令在流水线中的流动往后流动一段。

增加了向后传递IR和从MEM/WB.IR回送到通用寄存
器组的连接。

将对PC的修改移到了IF段,以便PC能及时地加
4,为取下一条指令做好准备。

2.每一个流水段进行的操作

  • IR[rs]=IR6…10
  • IR[rt]=IR11…15
  • IR[rd]=IR16…20

在这里插入图片描述
在这里插入图片描述

3.流水线的控制
主要是如何控制4个多路选择器。

  • MUX2:若ID/EX.IR中的指令是分支指令,则选择ID/EX.NPC,否则选ID/EX.A。
  • MUX3:若ID/EX.IR中的指令是寄存器-寄存器型ALU指令,则选ID/EX.B,否则选ID/EX.Imm。
  • MUX1:若EX/MEM.IR中的指令是分支指令,而且EX/MEM.cond为真,则选EX/MEM.ALUo,即分支目标地址,否则选PC+4。
  • MUX4:若MEM/WB.IR中的指令是load指令,则选MEM/WB.LMD,否则选MEM/WB.ALUo。
  • 第5个多路器:从MEM/WB回传至通用寄存器组的写入地址应该是从MEM/WB.IR[rd] 和MEM/WB.IR[rt]中选一个。
    • 寄存器-寄存器型ALU指令:选择MEM/WB.IR[rd] ;
    • 寄存器-立即数型ALU指令和load指令:选择MEM/WB.IR[rt] 。

4.控制冲突

分支指令的条件测试和分支目标地址计算在EX段完成,对PC的修改在MEM段完成。

它所带来的分支延迟是3个时钟周期。

减少分支延迟:

(把上述工作提前到ID段进行)

  • 在ID段增设一个加法器,用于计算分支目标地址。
  • 把条件测试“=0?”的逻辑电路移到ID段。
  • 这些结果直接回送到IF段的MUX1。
  • 改进后的流水线对分支指令的处理。

在这里插入图片描述
在这里插入图片描述

指令流水线实现

参考:教学资料

MIPS五段流水CPU设计

五段流水线CPU通路基本构成

流水线设计的时候,必须增加流水寄存器
在这里插入图片描述
单周期、多周期、流水执行方式

单周期的每一条指令执行周期必须是一样的,取决于最长指令执行的时间
多周期的每一条指令执行周期长度可以不同

多周期的执行效率比单周期的高

流水线各个功能段大多数的情况下不会有空闲
流水寄存器的作用
在这里插入图片描述

支持基本R型运算的流水cpu数据通路图

流水寄存器的功能
数据通路
在这里插入图片描述
支持除了跳转指令的基本流水cpu通路图,需要分别理解R型运算、移位指令、I型运算、访存指令

ID中需要SA移位数据字段、imm(扩展)立即数字段

EX需要有效地址的计算

Mem需要写读DataMem

对比于单周期,流水CPU增加了4个流水寄存器
ID段产生所有的控制信号,并一级一级往需要的地方传送
传送最远的信号是wreg写寄存器信号

有些资料里会把MUX放到WB之后进行
在这里插入图片描述相邻指令间存在数据相关,判断依据:寄存器地址

先写后读相关
不做处理的话,会读到写之前的旧数据

在这里插入图片描述

将EX段的执行结果通过反馈回路反馈给ID段,也要传递地址让ID段进行比较判断是否产生了相关

把EX段的执行结果通过反馈回路反馈给ID段,
类似于定向技术:数据真正产生的地方送到数据真正需要的地方
此时MUX的输入不仅是IF传送的信号,还有EX反馈的信号

在这里插入图片描述
相隔一条指令间存在数据相关,判断依据:寄存器地址

在写回没有完成之前,读的仍是旧数据

在这里插入图片描述

将MEM段的执行结果通过反馈回路反馈给ID段,也要传递地址让ID段进行比较判断是否产生了相关

所以在MEM段依然要反馈给ID段
在这里插入图片描述

相隔两条指令间存在数据相关

在写回没有完成之前,读的仍是旧数据
在这里插入图片描述
所以,让写回段以时钟下降沿写入,提前送入regs

在clk到达regFile之前,加了反向器

在这里插入图片描述

出现Load相关,反馈无法解决,必须CPU暂停

没有办法提前传寄存器的值
在这里插入图片描述
使用停顿
可以看到译码停顿了两个周期
在这里插入图片描述

判断条件:操作码为Lw且产生结果寄存器与后面指令源寄存器一致的情况

CPU暂停是什么意思?

ID检测到Load相关,
产生stall_req信号
传送到ctrl模块
ctrl产生stall信号
使得流水寄存器写入无效

在这里插入图片描述

目前的电路图:

针对20条基本指令

MIOC和IO为下版增加的模块
在这里插入图片描述

ID段判断数据先写后读数据相关的代码
在这里插入图片描述

视频中的测试代码

_start:   or     $1, $0, $0
          addi   $4, $1, 0x40
          ori    $1, $1, 0x1
         addi   $11,$0, 0x50
loop1:	 sw     $1, 0($4)
	 add    $1, $1, $1          #0x1 0x2 0x4 0x8 0x10 
	 bne    $4, $11,loop1
	 addi   $4, $4, 4
	 jal    sum
	 addi   $5, $0, 5
return:  sw     $2, 0($4)           # store 0x1f
	 lw     $9, 0($4)           # load 0x1f
	 sub    $15, $9, $2          # 0x00000000
	 addi   $5, $0, 0            # 0x00000000
	 lui    $1, 0xffff
	 ori    $1, $1, 0xffff
	
         
         or     $15, $5, $1          # 0xffffffff  
	 xori   $15, $15, 0xaaaa      # 0xffff5555
	 

         lui    $2, 0x0000
	 ori    $2, $2, 0xffff         #0x0000ffff
	

         add    $10,  $2, $1        # 0x0000fffe
	 andi   $7, $1, 0x3333       # 0x00003333
	 or     $6, $10, $15         # 0xffffffff
	 xor    $8, $6, $10          # 0xffff0001
	

         and    $7, $10, $6          # 0x0000fffe
	 beq    $5, $0, shift_addr  
	 nop
sum:	 or     $15, $0, $0
	 ori    $4, $0, 0x50
loop:	 lw     $9, 0($4)            # 0x10 0x8 0x4 0x2 0x1 
	 add    $15, $15, $9
	 addi   $5, $5, -1
	 bne    $5, $0, loop
	 addi   $4, $4, -4
jr      $31
	 ori    $2, $15, 0
shift_addr: addi   $5, $0, -1
	 sll    $15, $5, 15         # 0xffff8000
	 sll    $15, $15, 16        # 0x80000000 
	 sra    $15, $15, 15        # 0xffff0000
	 srl    $15, $15, 16        # 0x0000ffff
end:	     j      end
	 nop	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

另外,针对分支指令
还需才要延迟分支的原理来进行设计
或者使用停顿技术
当分支有效地址计算出来,再进行分支

基于单周期CPU的流水线设计

2023-5-28 10:32:14

以下是我设计中遇到的困难

主要是学习通里的流水线视频的设计框图,和原来单周期的设计框图不一样
他们两个的信号名称不一样
导致设计难度增加

视频中流水线的设计框图

在这里插入图片描述

原来的单周期的设计框图

在这里插入图片描述

按我的理解是:
流水寄存器中输入输出的信号与前后两个模块相关

比如IF_ID:
输入信号:就是原IF给原ID传递的信号
输出信号:就是原ID接受原IF的信号

另外添加:clk与rst控制与存储inst取到的指令
在IF_ID模块不需要inst,因为还没有得到此信号

在这里插入图片描述

所以,IF_ID引脚设计是这样的

input wire clk,
input wire rst, 
input wire[5:0] stall,		//Ctrl input
input wire [31:0] pc_i, //IF to
input wire[31:0] inst_i,//IF to
output reg [31:0] pc_o, //to ID
output reg [31:0] inst_o//to ID
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

主要原理就是这样,

但是,如果一些接口细节可能想不全,极有可能会不能正确地实现功能。

以下是按我的想法进行设计
参考视频中的顶层框图与流水CPU的数据通路
改造单周期的CPU设计,添加流水寄存器

代码设计

流水寄存器的引脚设计

按我的理解是:
流水寄存器中输入输出的信号与前后两个模块相关

比如IF_ID:
输入信号:就是原IF给原ID传递的信号
输出信号:就是原ID接受原IF的信号

另外添加:clk与rst控制与存储inst取到的指令
在IF_ID模块不需要inst,因为还没有得到此信号

另外,结合了数据通路实现

IF_ID

module IF_ID(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,	//Ctrl input
    input wire [31:0] pc_i, //from IF
	input wire[31:0] inst_i,//from instMem
    output reg [31:0] pc_o, //to ID
	output reg [31:0] inst_o//to ID
);

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述

ID_EX

module ID_EX(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//id to ID_EX input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
	input wire [31:0] excptype_i,//输入的异常或中断信息记录 
	input wire [5:0] op_i,  
	input wire [31:0] pc_i,  	
    input wire [31:0] regaData_i,
    input wire [31:0] regbData_i,
    input wire regcWrite_i,
    input wire [4:0] regcAddr_i,	

	//ID_EX to EX output 
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
	output reg [31:0] excptype_o,//输入的异常或中断信息记录
	output reg [5:0] op_o,
	output reg  [31:0] pc_o, 
    output reg [31:0] regaData_o,
    output reg [31:0] regbData_o,
    output reg regcWrite_o,
    output reg [4:0] regcAddr_o
);

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

EX_MEM

module EX_MEM(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//EX to EX_MEM input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
    input reg [31:0] regcData_i,
    input wire regcWrite_i,
    input wire [4:0] regcAddr_i,
	input wire [5:0] op_i,
    input wire [31:0] memAddr_i,
    input wire [31:0] memData_i,

	//EX_MEM to MEM output
	output wire[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
    output reg [31:0] regcData_o,
    output wire regcWrite_o,
    output wire [4:0] regcAddr_o,
	output wire [5:0] op_o,
    output wire [31:0] memAddr_o,
    output wire [31:0] memData_o

);

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在这里插入图片描述

MEM_WB

module MEM_WB(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//MEM to MEM_WB input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
	input wire [4:0]  regAddr,
	input wire regWr,
	input wire [31:0] regData,		

	//MEM_WB to regFile output
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
    output reg we,
    output reg [4:0] waddr,
    output reg [31:0] wdata

);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述

流水寄存器的功能设计

以下是简单的功能设计,没有实现流水功能

就是根据时钟信号
如果是复位信号有效,输出清零数据
如果是停顿信号有效,输出停顿数据
否则,输出传送数据

IF_ID

12:37

`include "define.v";
//IF_ID 流水寄存器

module IF_ID(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,	//Ctrl input
    input wire [31:0] pc_i, //from IF
	input wire[31:0] inst_i,//from instMem
    output reg [31:0] pc_o, //to ID
	output reg [31:0] inst_o//to ID
);


    always@(posedge clk)
        if(rst == `RstEnable)
			begin
            	inst_o<=`ZeroWord;
				pc_o<=`ZeroWord;
			end
        else if(stall[1]==`Stop&&stall[2]==`NoStop)//停顿周期
            begin
            	inst_o<=`ZeroWord;
				pc_o<=`ZeroWord;				
			end

        else if(stall[1]==`NoStop)
            begin
            	inst_o<=inst_i;
				pc_o<=pc_i;				
			end

 
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

ID_EX

`include "define.v";
//ID_EX 流水寄存器

module ID_EX(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//id to ID_EX input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
	input wire [31:0] excptype_i,
	input wire [5:0] op_i,  
	input wire [31:0] pc_i,  	
    input wire [31:0] regaData_i,
    input wire [31:0] regbData_i,
    input wire regcWrite_i,
    input wire [4:0] regcAddr_i,	

	//ID_EX to EX output 
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
	output reg [31:0] excptype_o,//
	output reg [5:0] op_o,
	output reg  [31:0] pc_o, 
    output reg [31:0] regaData_o,
    output reg [31:0] regbData_o,
    output reg regcWrite_o,
    output reg [4:0] regcAddr_o
);

    always@(posedge clk)
		begin
			if(rst==`RstEnable)
				begin
					inst_o=`ZeroWord;
					excptype_o=excptype_i;
					op_o=`Nop;
					pc_o=`Zero;
					regaData_o=`Zero;
					regbData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;
				end
        	else if(stall[2]==`Stop&&stall[3]==`NoStop)//停顿周期
            	begin
					inst_o=`ZeroWord;
					excptype_o=excptype_i;
					op_o=`Nop;
					pc_o=`Zero;
					regaData_o=`Zero;
					regbData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;		
				end

        	else if(stall[2]==`NoStop)
            	begin
            		inst_o<=inst_i;	
					excptype_o=excptype_i;
					op_o=op_i;
					pc_o=pc_i;
					regaData_o=regaData_i;
					regbData_o=regbData_i;
					regcWrite_o=regcWrite_i;
					regcAddr_o=regcAddr_i;		
				end

		end
 
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

EX_MEM

`include "define.v"
//EX_MEM 流水寄存器
module EX_MEM(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//EX to EX_MEM input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
    input reg [31:0] regcData_i,
    input wire regcWrite_i,
    input wire [4:0] regcAddr_i,
	input wire [5:0] op_i,
    input wire [31:0] memAddr_i,
    input wire [31:0] memData_i,

	//EX_MEM to MEM output
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
    output reg [31:0] regcData_o,
    output reg regcWrite_o,
    output reg [4:0] regcAddr_o,
	output reg [5:0] op_o,
    output reg [31:0] memAddr_o,
    output reg [31:0] memData_o

);

    always@(posedge clk)
		begin
			if(rst==`RstEnable)
				begin
					inst_o=`ZeroWord;
					regcData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;
					op_o=`Nop;
					memAddr_o=`Zero;
					memData_o=`Zero;
				end
        	else if(stall[3]==`Stop&&stall[4]==`NoStop)//停顿周期
            	begin
					inst_o=`ZeroWord;
					regcData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;
					op_o=`Nop;
					memAddr_o=`Zero;
					memData_o=`Zero;
				end

        	else if(stall[3]==`NoStop)
            	begin
					inst_o=inst_i;
					regcData_o=regcData_i;
					regcWrite_o=regcWrite_i;
					regcAddr_o=regcAddr_i;
					op_o=op_i;
					memAddr_o=memAddr_i;
					memData_o=memData_i;
				end

		end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

MEM_WB

`include "define.v"
//MEM_WB 流水寄存器
module MEM_WB(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//MEM to MEM_WB input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
	input wire [5:0]  regAddr,
	input wire regWr,
	input wire [31:0] regData,		

	//MEM_WB to regFile output
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
    output reg we,
    output reg [5:0] waddr,
    output reg [31:0] wdata

);

    always@(posedge clk)
		begin
			if(rst==`RstEnable)
				begin
					inst_o=`ZeroWord;
					wdata=`Zero;
					we=`Invalid;
					waddr=`Zero;
				end
        	else if(stall[4]==`Stop&&stall[5]==`NoStop)//停顿周期
            	begin
					inst_o=`ZeroWord;
					wdata=`Zero;
					we=`Invalid;
					waddr=`Zero;
				end

        	else if(stall[4]==`NoStop)
            	begin
					inst_o=inst_i;
					wdata=regData;
					we=regWr;
					waddr=regAddr;
				end

		end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

原来模块的改造

define

//流水线CPU
`define ZeroWord 32'h0000	
`define Stop 1'b1
`define NoStop 1'b0
  • 1
  • 2
  • 3
  • 4

多了个inst的处理
取得上一个流水寄存器的值inst_i
传送下一个流水寄存器的值inst_o

IF

11:25

对应教学视频的PC寄存器

	input wire[5:0] stall   //流水线

    //程序执行 pc+=4
	//中断-修改
	//流水线修改
    always@(posedge clk)
        if(ce == `RomDisable)
            pc = `Zero;
		else if(stall[0]==`NoStop) //流水线
			begin 
				if(excpt == 1'b1)
					pc <=ejpc;//异常或中断的转移地址更新pc
 				else if(jCe == `Valid)//J型
            		pc = jAddr;

        		else
        		    pc = pc + 4;
			end


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

ID

14:31

最复杂的模块

译码出所有的控制信号



//    input wire [31:0] inst,


	input wire[31:0] inst_i, 	//接受
	output reg[31:0] inst_o,	 	//传送
	output wire stallreq	//to Ctrl


	//方便修改
	wire [31:0] inst=inst_i;

	//对stall先不处理
	assign stallreq =1'b0;

    always@(*)
		inst_o=inst_i;
	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

EX

		input wire[31:0] inst_i, 	//接受
		output reg[31:0] inst_o	 	//传送

    always@(*)
		inst_o=inst_i;




  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

MEM

		input wire[31:0] inst_i, 	//接受
		output reg[31:0] inst_o	 	//传送

    always@(*)
		inst_o=inst_i;


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Ctrl

	input wire stall_id,  		//from id
	output reg[5:0] stall_o    //to 流水寄存器

	//左移寄存器
	always@(*)
		if(rst == `RstEnable)
			stall_o=6'b0;
		else
			stall_o={stall_o[4:0],stall_id};
		
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

regFile

	input wire[31:0] inst, //流水线

  • 1
  • 2

MIPS

需要把相邻两个模块拆开,用流水寄存器相联

举例:说明怎么修改

比如:ID ID_EX EX
原来:ID输出–>EX输入
(一条线连接)

修改:
把原ID输出的信号–>ID_EX输入
把ID_EX的输出信号–>原EX输入
(两条线连接)

对比来看,把原EX输入信号量与ID_EX输入相连
并且新增连线
把ID_EX的输出信号与原EX输入连接起来

下面代码可能会遗漏,会连线错误
如若发现,请指正

	//流水线
	wire  stall_id;		//from id to ctrl
	wire [5:0] stall_o; //form ctrl to 流水寄存器

	//IF_ID输出 ID输入
	wire [31:0] instruction_o_ifid;

	//ID输出 ID_EX输入
	wire [31:0] pc_o_id;
	wire[31:0] instruction_o_id;

	//ID_EX输出 EX输入
	wire[31:0] instruction_o_idex;
	wire[31:0] excptype_o;
    wire [5:0] op_o; 
	wire[31:0] pc_o;
    wire [31:0] regaData_o, regbData_o; 
	wire regcWrite_o_ex;
	wire [4:0]regcAddr_o_ex; 
	
	//EX输出 EX_MEM输入
	wire [31:0] instruction_o_ex;

	//EX_MEM输出 MEM输入
	wire[31:0] instruction_o_exmem;
	wire [31:0] regcData_o_exmem;
	wire regcWrite_o_exmem;
	wire [4:0] regcAddr_o_exmem;
	wire [5:0] op_o_exmem;
	wire [31:0] memAddr_o_exmem;
	wire [31:0] memData_o_exmem;

	//MEM 输出 MEM_WB 输入
	wire [31:0] instruction_o_mem;

	//MEM_WB 输出 regFile 输入
	wire [31:0] instruction_o_memwb;	
	wire [4:0] regAddr_memwb;
	wire regWr_memwb;
	wire [31:0] regData_memwb;

	//中断修改
	//流水线修改
    IF if0(
        .clk(clk),
        .rst(rst),
		.jAddr(jAddr),//J型
		.jCe(jCe),//J型
        .ce(romCe), 
        .pc(instAddr),
		.ejpc(ejpc),//异常或中断转移地址
		.excpt(excpt),//异常或中断信号
		.stall(stall_o)
    );

	//流水线-添加
    IF_ID if_id0(
	    .clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//Ctrl input
	    .pc_i(instAddr), 		//from IF
		.inst_i(instruction),	//from instMem
	    .pc_o(pc_id), 			//to ID
		.inst_o(instruction_o_ifid)	//to ID
	);
	
	//中断修改
	//流水线修改
    ID id0(
        .rst(rst), 
//       .pc(instAddr),//J型
//        .inst(instruction_o),   //流水线修改
        .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(pc_id),//pc的输入信号
		.pc(pc_o_id),	//pc的输出信号
		.excptype(excptype_id),//中断或异常的记录信息
		.inst_i(instruction_o_ifid),
		.inst_o(instruction_o_id),
		.stallreq(stall_id)
    );
    
	//流水线-添加
	ID_EX id_ex0(
	    .clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//from Ctrl
		//id to ID_EX input
		.inst_i(instruction_o_id),
		.excptype_i(excptype_id),
		.op_i(op_id), 
		.pc_i(pc_o_id),		    
	    .regaData_i(regaData_id),
	    .regbData_i(regbData_id),
	    .regcWrite_i(regcWrite_id),
	    .regcAddr_i(regcAddr_id),	
		//ID_EX to EX output 
		.inst_o(instruction_o_idex),
		.excptype_o(excptype_o),
		.op_o(op_o), 
		.pc_o(pc_o),	   
	    .regaData_o(regaData_o),
	    .regbData_o(regbData_o),
	    .regcWrite_o(regcWrite_o_ex),
	    .regcAddr_o(regcAddr_o_ex)
	);
	
    //乘除md-修改EX实例化
	//中断修改
	//流水线修改
    EX ex0(
        .rst(rst),
        //.op(op),    
		.op_i(op_o),    
        .regaData(regaData_o),
        .regbData(regbData_o),
        .regcWrite_i(regcWrite_o_ex),
        .regcAddr_i(regcAddr_o_ex),
		.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_o),//pc的输入值
		.excptype_i(excptype_o),//异常或中断的记录信息输入值
		.excptype(excptype_ex),//异常或中断的记录信息输出值
		.epc(epc_ex),//epc的输出值
		.pc(pc_ex),//pc的输出值
		.cause(cause),//cause的输入值
		.status(status),//status的输入值
		.inst_i(instruction_o_idex),
		.inst_o(instruction_o_ex)

    );    
    
	EX_MEM ex_mem0(
		.clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//from Ctrl
	
		//EX to EX_MEM input
		.inst_i(instruction_o_ex),	//根据数据通路,所有流水寄存器必须要加的
	    .regcData_i(regcData_ex),
	    .regcWrite_i(regcWrite_ex),
	    .regcAddr_i(regcAddr_ex),
		.op_i(op_ex),
	    .memAddr_i(memAddr_ex),
	    .memData_i(memData_ex),
	
		//EX_MEM to MEM output
		.inst_o(instruction_o_exmem),	//根据数据通路,所有流水寄存器必须要加的
	    .regcData_o(regcData_o_exmem),
	    .regcWrite_o(regcWrite_o_exmem),
	    .regcAddr_o(regcAddr_o_exmem),
		.op_o(op_o_exmem),
	    .memAddr_o(memAddr_o_exmem),
	    .memData_o(memData_o_exmem)
	);



	//新增Mem实例化
	//修改Mem实例化 llsc
	MEM mem0(
        .rst(rst),		
	    .op(op_o_exmem),
	 	.regcData(regcData_o_exmem),
		.regcAddr(regcAddr_o_exmem),
		.regcWr(regcWrite_o_exmem),
		.memAddr_i(memAddr_o_exmem),
		.memData(memData_o_exmem),	
		.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
		.inst_i(instruction_o_exmem),
		.inst_o(instruction_o_mem)
	);

	//新增流水线寄存器
	MEM_WB mem_wb0(
	    .clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//from Ctrl
	
		//MEM to MEM_WB input
		.inst_i(instruction_o_mem),	//根据数据通路,所有流水寄存器必须要加的
		.regAddr(regAddr_mem),
		.regWr(regWr_mem),
		.regData(regData_mem),		
	
		//MEM_WB to regFile output
		.inst_o(instruction_o_memwb),	//根据数据通路,所有流水寄存器必须要加的
	    .we(regWr_memwb),
	    .waddr(regAddr_memwb),
	    .wdata(regData_memwb)		
	);


	//流水线修改
    RegFile regfile0(
        .clk(clk),
        .rst(rst),
		.inst(instruction_o_memwb),
		.we(regWr_memwb),
		.waddr(regAddr_memwb),
		.wdata(regData_memwb),
        .regaRead(regaRead),
        .regbRead(regbRead),
        .regaAddr(regaAddr),
        .regbAddr(regbAddr),
        .regaData(regaData_regFile),
        .regbData(regbData_regFile)
    );

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245

InstMem

		//指令流水测试
		
		//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;

		
	
		//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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

测试设计

测试数据连接是否正确

如果是以下连线
代表MIPS内部连线没有问题

在这里插入图片描述

算了,附个图,好看点吧

以下流水线,应该能看懂吧

流水寄存器获取上一个模块的信号是时序逻辑
模块获取上一个流水寄存器的信号是组合逻辑

所以
另外说明:此处IF只执行pc+4(时序逻辑),IF_ID根据pc从instMem中取出inst(组合逻辑)
IF_ID:inst_o=inst_i[clk↑]
ID:inst_o=inst_i
ID_EX:inst_o=inst_i[clk↑]
EX:inst_o=inst_i
EX_MEM:inst_o=inst_i[clk↑]
MEM:inst_o=inst_i

因为模块的组合逻辑
ID_EX.inst_i与ID.inst_i(ID.inst_o)相同
EX_MEM.inst_i与EX.inst_i(ID.inst_o)相同

下图没有画出,仿真图有此体现
在这里插入图片描述

增加MEM_WB之后的结果

因为多了一个流水寄存器
所以满载的时候会多一个时钟周期
在这里插入图片描述

流水图如下
在这里插入图片描述

测试功能

原来的单周期CPU的波形

一个周期产生一个数据

在这里插入图片描述

现在的流水CPU的设计波形

流水线满载(C)后,一个周期产生一个数据
在这里插入图片描述

修改:增加MEM_WB

因为多了一个流水寄存器
所以满载的时候会多一个时钟周期

发现R5 没有结果,因为有数据冲突

在这里插入图片描述
pc=14时

可以看到inst4在ID段
但是inst1在WB段

在时钟上升沿
真正写入regFile

在这里插入图片描述

2023-5-30 16:59:31

附录

其余与上篇一样

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 CP0_epc 32'b0
`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

//流水线CPU
`define ZeroWord 32'h0000	
`define Stop 1'b1
`define NoStop 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'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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141

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,		//异常或中断有效信号
	input wire[5:0] stall
);
    always@(*)
        if(rst == `RstEnable)
            ce = `RomDisable;
        else
            ce = `RomEnable;

    //程序执行 pc+=4
	//中断-修改
    always@(posedge clk)
        if(ce == `RomDisable)
            pc = `Zero;
		else if(stall[0]==`NoStop)
			begin
				if(excpt == 1'b1)
					pc <=ejpc;//异常或中断的转移地址更新pc
 				else if(jCe == `Valid)//J型
            		pc = jAddr;
        		else
           			 pc = pc + 4;
			end

endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

I IF_ID 流水寄存器

`include "define.v";
//IF_ID 流水寄存器

module IF_ID(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,	//Ctrl input
    input wire [31:0] pc_i, //from IF
	input wire[31:0] inst_i,//from instMem
    output reg [31:0] pc_o, //to ID
	output reg [31:0] inst_o//to ID
);


    always@(posedge clk)
        if(rst == `RstEnable)
			begin
            	inst_o<=`ZeroWord;
				pc_o<=`ZeroWord;
			end
        else if(stall[1]==`Stop&&stall[2]==`NoStop)//停顿周期
            begin
            	inst_o<=`ZeroWord;
				pc_o<=`ZeroWord;				
			end

        else if(stall[1]==`NoStop)
            begin
            	inst_o<=inst_i;
				pc_o<=pc_i;				
			end

 
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

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_i
	output wire[31:0] pc,//新增输出pc
	output wire[31:0] excptype,//异常信息记录
	input wire[31:0] inst_i, 	//接受
	output reg[31:0] inst_o, 	//传送
	output wire stallreq		//to Ctrl
);

	//方便修改
	wire [31:0] inst=inst_i;

    //操作指令
    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};

	//对stall先不处理
	assign stallreq =1'b0;

    always@(*)
		inst_o=inst_i;


    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型
				is_eret = `Invalid;//中断
				is_syscall = `Invalid;//中断

          	 end
		else if(inst == `Inst_eret)
			 begin
				op =`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;
			  end
		else if(inst == `Inst_syscall)
			  begin
				op = `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;
			  end


		else 
			begin//后面的end
			    jCe = `Invalid;//J型
		        jAddr = `Zero;//J型
				is_eret = `Invalid;//中断
				is_syscall = `Invalid;//中断

	          	case(inst_op)
					`Inst_cp0:
						case(inst[25:21])
							`Inst_mfc0:
								begin
									op = `Mfc0;
									regaRead = `Invalid;
									regbRead = `Invalid;
									regcWrite = `Valid;
									regaAddr = `Zero;
									regbAddr = `Zero;
									regcAddr = inst[20:16];
									imm= {27'h0, inst[15:11]};
								end
							`Inst_mtc0:
								begin
									op =`Mtc0;
									regaRead = `Invalid;
									regbRead = `Valid;
									regcWrite = `Invalid;
									regaAddr = `Zero;
									regbAddr = inst[20:16];
									regcAddr = `Zero;
									imm= {27'h0, inst[15:11]};
								end
								
							default:
								begin
									op= `Nop;
									regaRead = `Invalid;
									regbRead = `Invalid;
									regcWrite = `Invalid;
									regaAddr = `Zero;
									regbAddr = `Zero;
									regcAddr = `Zero;
									imm= `Zero;
								end
						endcase

	               	`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		
									//后4条指令
									`Inst_mfhi:
						 				begin
							 				op = `Mfhi;
						      				regaRead = `Invalid;
							  				regbRead = `Invalid;
							  				regcWrite = `Valid;//从HILO寄存器中,写到通用寄存器中
							  				regaAddr = `Zero;
							  				regbAddr = `Zero;
							  				regcAddr = inst[15:11];
							  				imm = `Zero;//HiLo的数据在EX中得到
						 				end		
									`Inst_mflo:
						 				begin
							 				op = `Mflo;
						      				regaRead = `Invalid;
							  				regbRead = `Invalid;
							  				regcWrite = `Valid;//从HILO寄存器中,写到通用寄存器中
							  				regaAddr = `Zero;
							  				regbAddr = `Zero;
							  				regcAddr = inst[15:11];
							  				imm = `Zero;//HiLo的数据在EX中得到
						 				end		
									`Inst_mthi:
						 				begin
							 				op = `Mthi;
						      				regaRead = `Valid;//从通用寄存器读出
							  				regbRead = `Invalid;
							  				regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中
							  				regaAddr = inst[25:21];	
							  				regbAddr = `Zero;
							  				regcAddr = `Zero;
							  				imm = `Zero;
						 				end		
									`Inst_mtlo:
						 				begin
							 				op = `Mtlo;
						      				regaRead = `Valid;//从通用寄存器读出
							  				regbRead = `Invalid;
							  				regcWrite = `Invalid;//写到HILO寄存器中,而不是通用寄存器中			
							  				regaAddr = inst[25:21];
							  				regbAddr = `Zero;
							  				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		

					//ll sc
				    `Inst_ll:
						 begin
							  op = `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:
						 begin
							 op = `Sc;
						      regaRead = `Valid;
							  regbRead = `Valid;
							  regcWrite = `Valid;//还需给rt赋值为1
							  regaAddr = inst[25:21];
							  regbAddr = inst[20:16];
							  regcAddr = inst[20:16];//还需给rt赋值为1
							  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)          
	        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;
*/

	//原子-修改
	//流水线需要判断冲突
	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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700

II ID_EX 流水寄存器

`include "define.v";
//ID_EX 流水寄存器

module ID_EX(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//id to ID_EX input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
	input wire [31:0] excptype_i,
	input wire [5:0] op_i,  
	input wire [31:0] pc_i,  	
    input wire [31:0] regaData_i,
    input wire [31:0] regbData_i,
    input wire regcWrite_i,
    input wire [4:0] regcAddr_i,	

	//ID_EX to EX output 
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
	output reg [31:0] excptype_o,//
	output reg [5:0] op_o,
	output reg  [31:0] pc_o, 
    output reg [31:0] regaData_o,
    output reg [31:0] regbData_o,
    output reg regcWrite_o,
    output reg [4:0] regcAddr_o
);

    always@(posedge clk)
		begin
			if(rst==`RstEnable)
				begin
					inst_o=`ZeroWord;
					excptype_o=excptype_i;
					op_o=`Nop;
					pc_o=`Zero;
					regaData_o=`Zero;
					regbData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;
				end
        	else if(stall[1]==`Stop&&stall[2]==`NoStop)//停顿周期
            	begin
					inst_o=`ZeroWord;
					excptype_o=excptype_i;
					op_o=`Nop;
					pc_o=`Zero;
					regaData_o=`Zero;
					regbData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;		
				end

        	else if(stall[1]==`NoStop)
            	begin
            		inst_o<=inst_i;	
					excptype_o=excptype_i;
					op_o=op_i;
					pc_o=pc_i;
					regaData_o=regaData_i;
					regbData_o=regbData_i;
					regcWrite_o=regcWrite_i;
					regcAddr_o=regcAddr_i;		
				end

		end
 
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

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寄存器值
		input wire[31:0] inst_i, 	//接受
		output reg[31:0] inst_o	 	//传送


    );    

	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@(*)
		inst_o=inst_i;


	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;
			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:
					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
				//剩余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:
					begin
						cp0Addr = regaData[4:0];
						regcData = cp0rData;
					end
				`Mtc0:
					begin
						regcData= `Zero;
						cp0we = `Valid;
						cp0Addr = regaData[4:0];
						cp0wData = regbData;
					end
                default:
                    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, IE
		else if(cause[10]&& status[10]== 1'b1 && status[1:0] == 2'b01)
			//timerInt
			excptype = 32'h0000_0004;
		else if(excptype_i[8] == 1'b1 && status[1] == 1'b0)
			//Syscall
			excptype = 32'h00000100;
		else if(excptype_i[9]== 1'b1)
			//Eret
			excptype = 32'h0000_0200;
		else
			excptype = `Zero;
  
	assign regcWrite = regcWrite_i;
	assign regcAddr = regcAddr_i;




endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216

III EX_MEM 流水寄存器

`include "define.v"
//EX_MEM 流水寄存器
module EX_MEM(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//EX to EX_MEM input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
    input reg [31:0] regcData_i,
    input wire regcWrite_i,
    input wire [4:0] regcAddr_i,
	input wire [5:0] op_i,
    input wire [31:0] memAddr_i,
    input wire [31:0] memData_i,

	//EX_MEM to MEM output
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
    output reg [31:0] regcData_o,
    output reg regcWrite_o,
    output reg [4:0] regcAddr_o,
	output reg [5:0] op_o,
    output reg [31:0] memAddr_o,
    output reg [31:0] memData_o

);

    always@(posedge clk)
		begin
			if(rst==`RstEnable)
				begin
					inst_o=`ZeroWord;
					regcData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;
					op_o=`Nop;
					memAddr_o=`Zero;
					memData_o=`Zero;
				end
        	else if(stall[1]==`Stop&&stall[2]==`NoStop)//停顿周期
            	begin
					inst_o=`ZeroWord;
					regcData_o=`Zero;
					regcWrite_o=`Invalid;
					regcAddr_o=`Zero;
					op_o=`Nop;
					memAddr_o=`Zero;
					memData_o=`Zero;
				end

        	else if(stall[1]==`NoStop)
            	begin
					inst_o=inst_i;
					regcData_o=regcData_i;
					regcWrite_o=regcWrite_i;
					regcAddr_o=regcAddr_i;
					op_o=op_i;
					memAddr_o=memAddr_i;
					memData_o=memData_i;
				end

		end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

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,		//llsc
	output 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,		//llsc
	output reg wLLbit,		//llsc

	input wire[31:0] inst_i, 	//接受
	output reg[31:0] inst_o	 	//传送

);

	assign regAddr = regcAddr;    
	assign regWr = regcWr;    
//	assign regData = (op == `Lw) ? rdData : regcData;    

	//因为regData是wire型的,所以为了不修改原来的代码,就不使用always
	//而是修改regcData的值,来传到regData


	//二选一,选出Sc指令的rt<-1或rt<0
	wire [31:0]regDataLL= (rLLbit==`SetFlag) ? 32'b1 : 32'b0; 
	//二选一,存往regFile的值 sc指令存的值regcDataLL 还是  寄存器传入的值regcData
	wire [31:0]regcDataLL=  (op == `Sc ) ? regDataLL : regcData;
	//二选一,存往regFile的值 lw取得的值rdData 还是 寄存器传入的值regcData
    assign regData = (op == `Lw) ? rdData : regcDataLL;  

	assign memAddr = memAddr_i;
	

    always@(*)
		inst_o=inst_i;


	always @ (*)        
	    if(rst == `RstEnable)          
	      begin            
	          wtData = `Zero;            
	          memWr = `RamUnWrite;            
	          memCe = `RamDisable;  
			  wbit=	`Invalid;
   			  wLLbit=`ClearFlag;
	      end        
		else
		  begin
	        wtData = `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<-1
						wbit=`Valid;
						wLLbit = `SetFlag;
					end
				`Sc:
					begin	
						if(rLLbit==`SetFlag)
							begin	
								//datamem[addr]<-rt
			         			wtData = memData;                    
			         			memWr = `RamWrite;                      
			        			memCe = `RamEnable;    
								//rt<-1
								//在EX中实现
								//LLbit<-0
								wbit=`Valid;
								wLLbit = `ClearFlag;
							end
						else
							begin
								//把rt<-0
								//在Mem前面对regcData处理来实现
							end
					end

				`Syscall:
					begin
						//LLbit<-0
						wbit=`Valid;
						wLLbit = `ClearFlag;
					end

				`Eret:
					begin
						//LLbit<-0
						wbit=`Valid;
						wLLbit = `ClearFlag;
					end


				default:                  
				    begin                    
				        wtData = `Zero;                    
				        memWr = `RamUnWrite;                    
				        memCe = `RamDisable;  
				 		wbit=	`Invalid;
	   			  		wLLbit=`ClearFlag;                
				    end             
			endcase
		  end
endmodule



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142

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,			//中断或异常有效信号
	input wire stall_id,  		//from id
	output reg[5:0] stall_o    //to 流水寄存器
);

	//左移寄存器
	always@(*)
		if(rst == `RstEnable)
			stall_o=6'b0;
		else
			stall_o={stall_o[4:0],stall_id};
	

	always@(*)
		if(rst == `RstEnable)
			begin
				excpt = `Invalid;
				ejpc = `Zero;
			end
		else
			begin
				excpt = `Valid;
				case(excptype)
					//timerInt
					32'h0000_0004:
						ejpc = 32'h00000050;//自己指定:中断服务地址 50h右移2位(即除以4)=20 instMem
					//Syscall
					32'h0000_0100:
						ejpc= 32'h00000040;//自己指定:中断服务地址 40h右移2位(即除以4)=16 instMem
					//Eret
					32'h0000_0200:
						ejpc = epc;
					default:
						begin
							ejpc= `Zero;
							excpt = `Invalid;
						end
				endcase
			end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

IV MEM_WB 流水寄存器

`include "define.v"
//MEM_WB 流水寄存器
module MEM_WB(
    input wire clk,
    input wire rst, 
    input wire[5:0] stall,		//from Ctrl

	//MEM to MEM_WB input
	input wire[31:0] inst_i,	//根据数据通路,所有流水寄存器必须要加的
	input wire [4:0]  regAddr,
	input wire regWr,
	input wire [31:0] regData,		

	//MEM_WB to regFile output
	output reg[31:0] inst_o,	//根据数据通路,所有流水寄存器必须要加的
    output reg we,
    output reg [4:0] waddr,
    output reg [31:0] wdata

);

    always@(posedge clk)
		begin
			if(rst==`RstEnable)
				begin
					inst_o=`ZeroWord;
					wdata=`Zero;
					we=`Invalid;
					waddr=`Zero;
				end
        	else if(stall[1]==`Stop&&stall[2]==`NoStop)//停顿周期
            	begin
					inst_o=`ZeroWord;
					wdata=`Zero;
					we=`Invalid;
					waddr=`Zero;
				end

        	else if(stall[1]==`NoStop)
            	begin
					inst_o=inst_i;
					wdata=regData;
					we=regWr;
					waddr=regAddr;
				end

		end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

7 RegFile 存取

`include "define.v";
//4、为操作数取值存值模块
//取值 regaData regbData
//存值 wdata
module RegFile(
    input wire clk,
    input wire rst,
    input wire we,
	input wire[31:0] inst, //流水线
    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;
        else
            regaData = 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

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
	input 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;

	//ls
	wire [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-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;

	//llsc
	wire 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;
    wire regcWrite_o;
    wire [4:0] regcAddr_o;


	//流水线
	wire stall_id;		//from id to ctrl
	wire [5:0] stall_o; //form ctrl to 流水寄存器

	//IF_ID输出 ID输入

	wire [31:0] instruction_o_ifid;

	//ID输出 ID_EX输入
	wire [31:0] pc_o_id;	
	wire[31:0] instruction_o_id;

	//ID_EX输出 EX输入
	wire[31:0] instruction_o_idex;
	wire[31:0] excptype_o;
    wire [5:0] op_o; 
	wire[31:0] pc_o;
    wire [31:0] regaData_o, regbData_o; 
	wire regcWrite_o_ex;
	wire [4:0]regcAddr_o_ex; 

	//EX输出 EX_MEM输入
	wire [31:0] instruction_o_ex;

	//EX_MEM输出 MEM输入
	wire[31:0] instruction_o_exmem;
	wire [31:0] regcData_o_exmem;
	wire regcWrite_o_exmem;
	wire [4:0] regcAddr_o_exmem;
	wire [5:0] op_o_exmem;
	wire [31:0] memAddr_o_exmem;
	wire [31:0] memData_o_exmem;

	//MEM 输出 MEM_WB 输入
	wire [31:0] instruction_o_mem;

	//MEM_WB 输出 regFile 输入
	wire [31:0] instruction_o_memwb;	
	wire [4:0] regAddr_memwb;
	wire regWr_memwb;
	wire [31:0] regData_memwb;



	//中断修改
    IF if0(
        .clk(clk),
        .rst(rst),
		.jAddr(jAddr),//J型
		.jCe(jCe),//J型
        .ce(romCe), 
        .pc(instAddr),
		.ejpc(ejpc),//异常或中断转移地址
		.excpt(excpt),//异常或中断信号
		.stall(stall_o)
    );


	//流水线-添加
    IF_ID if_id0(
	    .clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//Ctrl input
	    .pc_i(instAddr), 		//from IF
		.inst_i(instruction),	//from instMem
	    .pc_o(pc_id), 			//to ID
		.inst_o(instruction_o_ifid)	//to ID
	);




	//中断修改
	//流水线修改
    ID id0(
        .rst(rst), 
//       .pc(instAddr),//J型
//       .inst(instruction_o),   //流水线修改
        .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(pc_id),//pc的输入信号
		.pc(pc_o_id),	//pc的输出信号
		.excptype(excptype_id),//中断或异常的记录信息
		.inst_i(instruction_o_ifid),
		.inst_o(instruction_o_id),
		.stallreq(stall_id)
    );


	//流水线-添加
	ID_EX id_ex0(
	    .clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//from Ctrl
		//id to ID_EX input
		.inst_i(instruction_o_id),
		.excptype_i(excptype_id),
		.op_i(op_id), 
		.pc_i(pc_o_id),		    
	    .regaData_i(regaData_id),
	    .regbData_i(regbData_id),
	    .regcWrite_i(regcWrite_id),
	    .regcAddr_i(regcAddr_id),	
		//ID_EX to EX output 
		.inst_o(instruction_o_idex),
		.excptype_o(excptype_o),
		.op_o(op_o), 
		.pc_o(pc_o),	   
	    .regaData_o(regaData_o),
	    .regbData_o(regbData_o),
	    .regcWrite_o(regcWrite_o_ex),
	    .regcAddr_o(regcAddr_o_ex)
	);

	


    //乘除md-修改EX实例化
	//中断修改
	//流水线修改
    EX ex0(
        .rst(rst),
        //.op(op),    
		.op_i(op_o),    
        .regaData(regaData_o),
        .regbData(regbData_o),
        .regcWrite_i(regcWrite_o_ex),
        .regcAddr_i(regcAddr_o_ex),
		.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_o),//pc的输入值
		.excptype_i(excptype_o),//异常或中断的记录信息输入值
		.excptype(excptype_ex),//异常或中断的记录信息输出值
		.epc(epc_ex),//epc的输出值
		.pc(pc_ex),//pc的输出值
		.cause(cause),//cause的输入值
		.status(status),//status的输入值
		.inst_i(instruction_o_idex),
		.inst_o(instruction_o_ex)

    );    

	EX_MEM ex_mem0(
		.clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//from Ctrl
	
		//EX to EX_MEM input
		.inst_i(instruction_o_ex),	//根据数据通路,所有流水寄存器必须要加的
	    .regcData_i(regcData_ex),
	    .regcWrite_i(regcWrite_ex),
	    .regcAddr_i(regcAddr_ex),
		.op_i(op_ex),
	    .memAddr_i(memAddr_ex),
	    .memData_i(memData_ex),
	
		//EX_MEM to MEM output
		.inst_o(instruction_o_exmem),	//根据数据通路,所有流水寄存器必须要加的
	    .regcData_o(regcData_o_exmem),
	    .regcWrite_o(regcWrite_o_exmem),
	    .regcAddr_o(regcAddr_o_exmem),
		.op_o(op_o_exmem),
	    .memAddr_o(memAddr_o_exmem),
	    .memData_o(memData_o_exmem)
	);

	//新增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实例化 llsc
	MEM mem0(
        .rst(rst),		
	    .op(op_o_exmem),
	 	.regcData(regcData_o_exmem),
		.regcAddr(regcAddr_o_exmem),
		.regcWr(regcWrite_o_exmem),
		.memAddr_i(memAddr_o_exmem),
		.memData(memData_o_exmem),	
		.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
		.inst_i(instruction_o_exmem),
		.inst_o(instruction_o_mem)
	);

	//新增流水线寄存器
	MEM_WB mem_wb0(
	    .clk(clk),
	    .rst(rst), 
	    .stall(stall_o),		//from Ctrl
	
		//MEM to MEM_WB input
		.inst_i(instruction_o_mem),	//根据数据通路,所有流水寄存器必须要加的
		.regAddr(regAddr_mem),
		.regWr(regWr_mem),
		.regData(regData_mem),		
	
		//MEM_WB to regFile output
		.inst_o(instruction_o_memwb),	//根据数据通路,所有流水寄存器必须要加的
	    .we(regWr_memwb),
	    .waddr(regAddr_memwb),
	    .wdata(regData_memwb)		
	);


	//新增LLbit实例化 llsc
	LLbit llbit0(
		.clk(clk),
		.rst(rst),
		.excpt(excpt),
		.wbit(wbit), 	
		.wLLbit(wLLbit),	
		.rLLbit(rLLbit)
	);

	

	//修改RegFile实例化
	//流水线修改
    RegFile regfile0(
        .clk(clk),
        .rst(rst),
		.inst(instruction_o_memwb),
		.we(regWr_memwb),
		.waddr(regAddr_memwb),
		.wdata(regData_memwb),
        .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),
		.stall_id(stall_id),  //from id
		.stall_o(stall_o)     //to 流水寄存器
	);

endmodule


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379

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;

		
	
		//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


      end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

最后

2023-5-28 16:21:39

添加MEM_WB
2023-5-30 16:42:28

修改没有问题了
2023-5-30 22:57:15

你对我百般注视,
并不能构成万分之一的我,
却是一览无余的你。

祝大家逢考必过
点赞收藏关注哦

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/659969
推荐阅读
相关标签
  

闽ICP备14008679号