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

这篇具有很好参考价值的文章主要介绍了6设计指令流水线-1【FPGA模型机课程设计】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

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

提示:博客中的代码可能没有修改到位
6设计指令流水线-1【FPGA模型机课程设计】

2023-6-4 11:30:33

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

6设计指令流水线

安排

第二周周一:

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

测试与结果

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

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

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

原来的单周期CPU的波形

一个周期产生一个数据

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

现在的流水CPU的设计波形

流水线满载(C)后,一个周期产生一个数据
6设计指令流水线-1【FPGA模型机课程设计】

修改:增加MEM_WB

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

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

6设计指令流水线-1【FPGA模型机课程设计】
可以看到以下测试代码

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

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

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

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

2023-5-30 16:38:36

指令流水线理论

参考:教学资料

MIPS的一种简单实现

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

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

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

6设计指令流水线-1【FPGA模型机课程设计】
一条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)

 不同指令所进行的操作不同:
  • 存储器访问指令
    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表示
  • 每个流水寄存器是由若干个寄存器构成的

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

  • 寄存器的命名形式为: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

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

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。
  • 改进后的流水线对分支指令的处理。

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

指令流水线实现

参考:教学资料

MIPS五段流水CPU设计

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

流水线设计的时候,必须增加流水寄存器
6设计指令流水线-1【FPGA模型机课程设计】
单周期、多周期、流水执行方式

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

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

流水线各个功能段大多数的情况下不会有空闲
流水寄存器的作用
6设计指令流水线-1【FPGA模型机课程设计】

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

流水寄存器的功能
数据通路
6设计指令流水线-1【FPGA模型机课程设计】
支持除了跳转指令的基本流水cpu通路图,需要分别理解R型运算、移位指令、I型运算、访存指令

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

EX需要有效地址的计算

Mem需要写读DataMem

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

有些资料里会把MUX放到WB之后进行
6设计指令流水线-1【FPGA模型机课程设计】相邻指令间存在数据相关,判断依据:寄存器地址

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

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

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

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

6设计指令流水线-1【FPGA模型机课程设计】
相隔一条指令间存在数据相关,判断依据:寄存器地址

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

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

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

所以在MEM段依然要反馈给ID段
6设计指令流水线-1【FPGA模型机课程设计】

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

在写回没有完成之前,读的仍是旧数据
6设计指令流水线-1【FPGA模型机课程设计】
所以,让写回段以时钟下降沿写入,提前送入regs

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

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

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

没有办法提前传寄存器的值
6设计指令流水线-1【FPGA模型机课程设计】
使用停顿
可以看到译码停顿了两个周期
6设计指令流水线-1【FPGA模型机课程设计】

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

CPU暂停是什么意思?

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

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

目前的电路图:

针对20条基本指令

MIOC和IO为下版增加的模块
6设计指令流水线-1【FPGA模型机课程设计】

ID段判断数据先写后读数据相关的代码
6设计指令流水线-1【FPGA模型机课程设计】

视频中的测试代码

_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	

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

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

2023-5-28 10:32:14

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

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

视频中流水线的设计框图

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

原来的单周期的设计框图

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

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

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

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

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

所以,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

主要原理就是这样,

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

以下是按我的想法进行设计
参考视频中的顶层框图与流水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

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

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

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

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

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

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

);

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

流水寄存器的功能设计

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

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

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

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

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

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

原来模块的改造

define

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

多了个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


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;
	

EX

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

    always@(*)
		inst_o=inst_i;




MEM

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

    always@(*)
		inst_o=inst_i;


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

regFile

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

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

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

测试设计

测试数据连接是否正确

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

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

算了,附个图,好看点吧

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

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

所以
另外说明:此处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)相同

下图没有画出,仿真图有此体现
6设计指令流水线-1【FPGA模型机课程设计】

增加MEM_WB之后的结果

因为多了一个流水寄存器
所以满载的时候会多一个时钟周期
6设计指令流水线-1【FPGA模型机课程设计】

流水图如下
6设计指令流水线-1【FPGA模型机课程设计】

测试功能

原来的单周期CPU的波形

一个周期产生一个数据

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

现在的流水CPU的设计波形

流水线满载(C)后,一个周期产生一个数据
6设计指令流水线-1【FPGA模型机课程设计】

修改:增加MEM_WB

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

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

6设计指令流水线-1【FPGA模型机课程设计】
pc=14时

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

在时钟上升沿
真正写入regFile

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

2023-5-30 16:59:31

附录

其余与上篇一样

0 框架

顶层设计

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

代码框架

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

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

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

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

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

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

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

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

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



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

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

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

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


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

最后

2023-5-28 16:21:39

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

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

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

祝大家逢考必过
点赞收藏关注哦文章来源地址https://www.toymoban.com/news/detail-479517.html

到了这里,关于6设计指令流水线-1【FPGA模型机课程设计】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 8位加法器的流水线设计(2级流水、四级流水)

    思考:流水线的设计是为了提高频率,在一个耗时比较长的组合逻辑中,加入寄存器, 可以将这个较长的组合逻辑分裂几份,从而提升主频,缺点是增加了寄存器的资源。 二级流水线的加法器的设计思想如下: 在第一个周期完成低四位的加法计算,使用一个四位加法器即可

    2024年02月11日
    浏览(47)
  • Verilog流水线设计——Pipeline

    在工程师实际开发过程中,可能会经常遇到这样的需求:数据从数据源端不断地持续输入FPGA,FPGA需要对数据进行处理,最后将处理好的数据输出至客户端。 在数据处理过程中,可能需要一系列的处理步骤。比如常规的信号进行处理步骤有(这里的处理步骤只是举个例子):

    2024年02月08日
    浏览(51)
  • 【软件架构】流水线设计模式

    流水线模式 流水线 模式是一种软件设计模式,它提供了构建 和执行 一系列 操作的能力。 此模式最好与 插件 模式结合使用,以便在应用程序启动时 动态 构建流水线。 顺序 流水线的最基本实现是一个简单的操作序列。 可以调用 操作 的接口来 处理 数据。 流水线一个一个

    2024年02月10日
    浏览(50)
  • 【CPU设计实战】简单流水线CPU设计

    CPU输入的、运算的、存储的、输出的数据都在组合逻辑和时序逻辑电路上流转,这些逻辑电路称为 数据通路 。 32位处理器用32位触发器来存放PC。PC的输出送到 虚实地址转换部件进行转换 ,PC的输入有两个,一个是复位值0xBFC00000,一个是复位撤销后每执行一条指令更新为当前

    2024年02月12日
    浏览(49)
  • 16位流水线CPU设计(部分)

    概括:本文介绍一个16位的流水线CPU设计与模拟过程,该流水线CPU由 IF 、 ID 、 EXE 、 MEM 和 WB 五个功能段组成,结构如下图所示。在各功能段之间分别设计了四个锁存段,即 IF_LATCH、ID_LATCH、EXE_LATCH和 WB_LATCH 。各基本模块使用 VHDL 硬件描述语言进行描述,各段的大部分功能模

    2024年02月03日
    浏览(39)
  • 【【verilog典型电路设计之流水线结构】】

    下图是一个4位的乘法器结构,用verilog HDL 设计一个两级流水线加法器树4位乘法器 对于流水线结构 其实需要做的是在每级之间增加一个暂存的数据用来存储 我们得到的东西 我们一般来说会通过在每一级之间插入D触发器来保证数据的联通 通过在第一级和第二级,第二级和第

    2024年02月12日
    浏览(39)
  • 南京观海微电子----Verilog流水线设计——Pipeline

    1.  前言 在工程师实际开发过程中,可能会经常遇到这样的需求:数据从数据源端不断地持续输入FPGA,FPGA需要对数据进行处理,最后将处理好的数据输出至客户端。 在数据处理过程中,可能需要一系列的处理步骤。比如常规的信号进行处理步骤有(这里的处理步骤只是举个

    2024年01月19日
    浏览(44)
  • 从零开始设计RISC-V处理器——五级流水线之数据通路的设计

    (一)从零开始设计RISC-V处理器——指令系统 (二)从零开始设计RISC-V处理器——单周期处理器的设计 (三)从零开始设计RISC-V处理器——单周期处理器的仿真 (四)从零开始设计RISC-V处理器——ALU的优化 (五)从零开始设计RISC-V处理器——五级流水线之数据通路的设计

    2024年02月08日
    浏览(53)
  • 【计组实验】基于Verilog的多周期非流水线MIPS处理器设计

    设计多周期非流水线MIPS处理器,包括: 完成多周期MIPS处理器的Verilog代码; 在Vivado软件上进行仿真; 编写MIPS代码验证MIPS处理器; 相关代码及资源的下载地址如下: 本实验的Vivado工程文件和实验文档:Multi-Cycle MIPS Processor.zip(272KB) QtSpim 9.1.23和Vivado 2019.2的安装包:QtSpim Viv

    2024年02月11日
    浏览(47)
  • 1.6流水线:流水线、流水线周期、流水线执行时间、流水线吞吐率、流水线加速比

    相关参数计算:流水线执行时间计算、流水线吞吐率、流水线加速比等。 流水线是指在程序执行时多条指令重叠进行操作的一种准并行处理实现技术。各种部件同时处理是针对不同指令而言的,它们可同时为多条指令的不同部分进行工作,以提高各部件的利用率和指令的平均

    2024年02月09日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包