首页 > 其他分享 >6设计指令流水线-2【FPGA模型机课程设计】

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

时间:2023-06-03 12:02:19浏览次数:43  
标签:课程设计 wire FPGA Zero inst ex 流水线 id op



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

  • 前言
  • 推荐
  • 6设计指令流水线-2
  • 安排
  • 测试与结果
  • 指令流水线理论
  • MIPS的一种简单实现
  • 基本的MIPS流水线
  • 指令流水线实现
  • MIPS五段流水CPU设计
  • 视频中的测试代码
  • 设计分析
  • 设计思路
  • 问题回答
  • 代码设计
  • ID
  • EX
  • MEM
  • RegFile
  • MIPS
  • InstMem
  • 附录
  • 3 ID 译码
  • 4 EX 执行
  • 5 MEM 访存
  • 7 RegFile 存取
  • 8 MIPS 封装
  • 9 InstMem 指令存储器
  • 最后


前言


6设计指令流水线-2

安排

第二周周一:

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

前篇只是实现了基本的流水线的功能
该篇实现数据冲突
分支和中断异常之后实现

测试与结果

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


		//相邻两条指令 	//ori R4,0000 -- R5 --0000ffff
        instmem [4] = 32'h34850000;	
		//相隔一条指令	//ori R4,0000 -- R6 --0000ffff
        instmem [5] = 32'h34860000;	
		//相隔两条指令	//ori R4,0000 -- R7 --0000ffff
		instmem [6] = 32'h34870000;	
		//load 相关
		//mem[0]=(r1)
		instmem[7]=32'b101011_00000_00001_0000_0000_0000_0000; //sw r1,0x0(r0)
		//(r8)=mem[0]
		instmem[8]=32'b100011_00000_01000_0000_0000_0000_0000; //lw r8,0x0(r0)
		instmem[9]=32'b001101_01000_01001_0000_0000_0000_0000; // ori r9 r8,0000

对比单周期CPU的结果

6设计指令流水线-2【FPGA模型机课程设计】_数据

流水线的结果

load相关有点问题

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_02

load处理类似于

6设计指令流水线-2【FPGA模型机课程设计】_fpga开发_03

但是,在停顿周期pc=28时

regaRead与regaAddr清0了

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_04

指令流水线理论

MIPS的一种简单实现

MIPS的一种简单实现

主要理解MIPS的五个功能段的作用

基本的MIPS流水线

基本的MIPS流水线

主要理解MIPS的数据通路
各个功能段怎么传递数据

指令流水线实现

MIPS五段流水CPU设计

MIPS五段流水CPU设计

主要理解MIPS的流水线的设计

分别需要掌握数据通路

  • 支持基本R型运算的流水cpu数据通路图
  • 支持除了跳转指令的基本流水cpu通路图,需要分别理解R型运算、移位指令、I型运算、访存指令
  • 相邻指令间存在数据相关,判断依据:寄存器地址
  • 将EX段的执行结果通过反馈回路反馈给ID段,也要传递地址让ID段进行比较判断是否产生了相关
  • 相隔一条指令间存在数据相关,判断依据:寄存器地址
  • 将MEM段的执行结果通过反馈回路反馈给ID段,也要传递地址让ID段进行比较判断是否产生了相关
  • 相隔两条指令间存在数据相关
  • 所以,让写回段以时钟下降沿写入,提前送入regs
  • 出现Load相关,反馈无法解决,必须CPU暂停
  • 判断条件:操作码为Lw且产生结果寄存器与后面指令源寄存器一致的情况

视频中的测试代码

_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

设计分析

设计思路

结合视频资料,进行设计分析

相邻指令间存在数据相关,判断依据:寄存器地址

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

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_05

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

23:14

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

EX执行的结果反馈给ID段
ID段就变成了三选一的输入

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

问题1:所以ID段和EX的连线设计需要怎么设计?

相隔一条指令间存在数据相关,判断依据:寄存器地址

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

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_07

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

所以在MEM段依然要反馈给ID段

26:33

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_08

问题2:所以ID段和MEM的连线设计需要怎么设计?

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

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

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_09


所以,让写回段以时钟下降沿写入,提前送入regs

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

01:17

6设计指令流水线-2【FPGA模型机课程设计】_数据_10

问题3:所以MEM段和regFIle的连线设计需要怎么设计?

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

没有办法提前传寄存器的值

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


使用停顿

可以看到译码停顿了两个周期

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

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

CPU暂停是什么意思?

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

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_13


流水线的数据通路:07:52

问题回答

对于相邻WAR冲突

问题1:所以ID段的引脚设计需要怎么设计?
回答1:需要增加一个反馈接口从EX输出到ID输入

对于相隔一条WAR冲突
问题2:所以ID段和MEM的连线设计需要怎么设计?
回答2:需要增加一个反馈接口从MEM输出到ID输入

对于相隔两条WAR冲突
问题3:所以MEM段和regFIle的连线设计需要怎么设计?
回答3:需要增加一个反向器连接regFile的clk输入
对于相邻Load相关
判断是否是Load冲突,停顿

代码设计

按照设计分析进行代码设计

ID

input wire[5:0] ex_op_i,			//ex 反馈 id op码
	input wire[4:0] ex_wd_to_id_i,  	//ex 反馈 id 写地址
	input wire ex_wreg_to_id_i,			//ex 反馈 给 id 写信号
	input wire [31:0] ex_wdata_to_id_i, //ex 反馈 给 id 写数据
	input wire[4:0] mem_wd_to_id_i,  	//mem 反馈 id写地址
	input wire mem_wreg_to_id_i,			//mem 反馈 给 id 写信号
	input wire [31:0] mem_wdata_to_id_i  //mem 反馈 给 id 写数据

	//流水线
	reg stall_for_rega_loadreleate;
	reg stall_for_regb_loadreleate;
	wire pre_inst_is_load;
	
	wire stall_for_loadreleate=stall_for_rega_loadreleate|stall_for_regb_loadreleate;
	assign pre_inst_is_load =(ex_op_i==`Lw)?1'b1:1'b0;


	//原子-修改
	//流水线需要有反馈数据的输入 选择器
	always@(*)    
		begin
			stall_for_rega_loadreleate=`NoStop;  
		    if(rst == `RstEnable)          
		        regaData = `Zero;      
		    //load相关 如果上一条指令是load 结果寄存器 == 当前指令源寄存器
			else if(pre_inst_is_load==1'b1 && ex_wd_to_id_i==regaAddr &®aRead==`Valid)
				stall_for_rega_loadreleate =`Stop;
			//相邻指令的冲突WAR
			else if(regaRead==`Valid&&ex_wreg_to_id_i==`Invalid&&ex_wd_to_id_i==regaAddr)
				regaData=ex_wdata_to_id_i;		
			//相隔一条指令的冲突WAR
			else if(regaRead==`Valid&&mem_wreg_to_id_i==`Invalid&&mem_wd_to_id_i==regaAddr)
				regaData=mem_wdata_to_id_i;		
			else if(op == `Lw || op == `Sw || op==`Ll || op==`Sc)               
		        regaData = regaData_i + imm;      
		    else if(regaRead == `Valid)          
		        regaData = regaData_i;      
		    else          
		        regaData = imm;    
		end


	always@(*) 
		begin     
			stall_for_regb_loadreleate=`NoStop;  
		    if(rst == `RstEnable)          
		        regbData = `Zero;    
		    //load相关 如果上一条指令是load 结果寄存器 == 当前指令源寄存器
			else if(pre_inst_is_load==1'b1 && ex_wd_to_id_i==regbAddr &®bRead==`Valid)
				stall_for_regb_loadreleate =`Stop;
			//相邻指令的冲突WAR
			else if(regbRead==`Valid&&ex_wreg_to_id_i==`Valid&&ex_wd_to_id_i==regbAddr)
				regbData=ex_wdata_to_id_i;		
			//相隔一条指令的冲突WAR
			else if(regbRead==`Valid&&mem_wreg_to_id_i==`Valid&&mem_wd_to_id_i==regbAddr)  
				regbData=mem_wdata_to_id_i;		
		    else if(regbRead == `Valid)          
		        regbData = regbData_i;      
		    else          
		    	regbData = imm;	
		end

EX

output reg[5:0] ex_op_o,			 //ex 反馈 给 id op码
		output reg [4:0] ex_wd_to_id_o,		 //ex 反馈 给 id 读地址
		output reg ex_wreg_to_id_o,			 //ex 反馈 给 id 读信号
		output reg [31:0] ex_wdata_to_id_o 	 //ex 反馈 给 id 读数据

	always@(*)
		begin
			ex_op_o=op_i;		
			ex_wd_to_id_o=regcAddr;
			ex_wreg_to_id_o=regcWrite;
			ex_wdata_to_id_o=regcData;
		end

MEM

output reg [4:0] mem_wd_to_id_o,		 //mem 反馈 给 id 读地址
	output reg mem_wreg_to_id_o,			 //mem 反馈 给 id 读信号
	output reg [31:0] mem_wdata_to_id_o 	 //mem 反馈 给 id 读数据


	always@(*)
		begin
			mem_wd_to_id_o=regcAddr;
			mem_wreg_to_id_o=regcWr;
			mem_wdata_to_id_o=regData;
		end

RegFile

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

MIPS

//流水线
	wire[5:0] ex_op;				//ex 反馈 id op码
	wire[4:0] ex_wd_to_id; 			//ex 反馈 id读地址
	wire ex_wreg_to_id;				//ex 反馈 给 id 读信号
	wire [31:0] ex_wdata_to_id; 	//ex 反馈 给 id 读数据
	wire[4:0] mem_wd_to_id; 		//mem 反馈 id读地址
	wire mem_wreg_to_id;			//mem 反馈 给 id 读信号
	wire [31:0] mem_wdata_to_id;  	//mem 反馈 给 id 读数据


	//中断修改
	//流水线修改
    ID id0(

		.ex_op_i(ex_op),						//ex 反馈 id op码
		.ex_wd_to_id_i(ex_wd_to_id),  			//ex 反馈 id读地址
		.ex_wreg_to_id_i(ex_wreg_to_id),		//ex 反馈 给 id 读信号
		.ex_wdata_to_id_i(ex_wdata_to_id), 		//ex 反馈 给 id 读数据
		.mem_wd_to_id_i(mem_wd_to_id),  		//mem 反馈 id读地址
		.mem_wreg_to_id_i(mem_wreg_to_id),		//mem 反馈 给 id 读信号
		.mem_wdata_to_id_i(mem_wdata_to_id) 	//mem 反馈 给 id 读数据		
    );



    //乘除md-修改EX实例化
	//中断修改
	//流水线修改
    EX ex0(

		.ex_op_o(ex_op),			 			//ex 反馈 给 id op码
		.ex_wd_to_id_o(ex_wd_to_id),		 	//ex 反馈 给 id 读地址
		.ex_wreg_to_id_o(ex_wreg_to_id),		//ex 反馈 给 id 读信号
		.ex_wdata_to_id_o(ex_wdata_to_id) 		//ex 反馈 给 id 读数据
    );   
 

	//新增Mem实例化
	//修改Mem实例化 llsc
	//流水线修改
	MEM mem0(

		.mem_wd_to_id_o(mem_wd_to_id),		 		//mem 反馈 给 id 读地址
		.mem_wreg_to_id_o(mem_wreg_to_id),			//mem 反馈 给 id 读信号
		.mem_wdata_to_id_o(mem_wdata_to_id) 	 	//mem 反馈 给 id 读数据
	);


	//修改RegFile实例化
	//流水线修改
    RegFile regfile0(
        .clk(~clk),  //反向器

    );

InstMem

本人有点强迫症,但是已经累了,不想改了

以下指令不对,请忽略

//指令测试

		instmem[0]= 32'b000000_00000_00000_00001_00000_100101;	 //_start:   or     $1, $0, $0
		instmem[1] = 32'b001000_00001_00100_0000_0000_0100_0000; //addi   $4, $1, 0x40
        instmem[2] = 32'b001101_00001_00001_0000_0000_0000_0001;  //ori    $1, $1, 0x1
        instmem[3] = 32'b001000_00000_01011_0000_0000_0101_0000;  //addi   $11,$0, 0x50		
		instmem[4] = 32'b101011_00100_00001_0000_0000_0000_0000;//loop1:	 sw     $1, 0($4)
		instmem[5] = 32'b000000_00001_00001_00001_00000_100000;//	 add    $1, $1, $1          #0x1 0x2 0x4 0x8 0x10 
		instmem[6] = 32'b000100_00100_01011_1111_1111_1111_1101;//	 beq    $4, $11,loop1 fffd(-3)
		instmem[7] = 32'b001100_00100_00100_0000_0000_0000_0100;//	 addi   $4, $4, 4
		instmem[8] = 32'b000011_000000_0000_0000_0000_0001_1010;//	 jal    sum
		instmem[9] = 32'b001100_00101_00101_0000_0000_0000_0000;//	 addi   $5, $0, 5

		instmem[10] = 32'b101011_00100_00010_0000_0000_0000_0000;//return:  sw     $2, 0($4)     # store 0x1f
		instmem[11] = 32'b100011_00100_01001_0000_0000_0000_0000;//	 lw     $9, 0($4)           # load 0x1f
		instmem[12] = 32'b000000_01001_00010_01111_00000_100010;//	 sub    $15, $9, $2          # 0x00000000
		instmem[13] = 32'b001100_00000_00101_0000_0000_0000_0100;//	 addi   $5, $0, 0            # 0x00000000
		instmem[14] = 32'b001111_00000_00001_1111_1111_1111_1111;//	 lui    $1, 0xffff
		instmem[15] = 32'b100101_00001_00001_1111_1111_1111_1111;//	 ori    $1, $1, 0xffff     

		//相邻两条指令 
		instmem[16] = 32'b00000_00101_00001_01111_00000_100101;//     or     $15, $5, $1          # 0xffffffff  
        instmem[17] = 32'b100110_01111_01111_1010_1010_1010_1010; //	 xori   $15, $15, 0xaaaa      # 0xffff5555
	
		instmem[18] = 32'b001111_00000_00010_0000_0000_0000_0000;//         lui    $2, 0x0000
		instmem[19] = 32'b100101_00010_00010_1111_1111_1111_1111;//	 ori    $2, $2, 0xffff         #0x0000ffff
	
		//相隔一条指令
		instmem[20] = 32'b000000_00010_00001_01010_00000_100000;//         add    $10,  $2, $1        # 0x0000fffe
		instmem[21] = 32'b001100_00001_00111_0011_0011_0011_0011;//	 andi   $7, $1, 0x3333       # 0x00003333
		instmem[22] = 32'b000000_01010_01111_00110_00000_100101;//	 or     $6, $10, $15         # 0xffffffff
		instmem[23] = 32'b000000_00110_01010_01000_00000_000000;//	 xor    $8, $6, $10          # 0xffff0001
	

		instmem[24] = 32'b000000_01010_00110_00111_00000_100100;//         and    $7, $10, $6          # 0x0000fffe
		instmem[25] = 32'b000100_00101_00000_0000_0000_0000_1010;//	 beq    $5, $0, shift_addr  
		instmem[26] = 32'b00000_00000_00000_00000_00000_100101;//	 nop
		instmem[27] = 32'b00000_00000_00000_01111_00000_100101;//sum:	 or     $15, $0, $0
		instmem[28] = 32'b100101_00000_00100_0000_0000_0101_0000;//	 ori    $4, $0, 0x50
		instmem[29] = 32'b100011_00100_01001_0000_0000_0000_0000;//loop:	 lw     $9, 0($4)            # 0x10 0x8 0x4 0x2 0x1 
		instmem[30] = 32'b000000_01111_01001_01111_00000_100000;//	 add    $15, $15, $9
		instmem[31] = 32'b001100_00101_00101_1111_1111_1111_1111;//	 addi   $5, $5, -1 ffff
		instmem[32] = 32'b001100_00101_00000_1111_1111_1111_1100;//	 bne    $5, $0, loop fffc
		instmem[33] = 32'b001100_00100_00100_1111_1111_1111_1100;//	 addi   $4, $4, -4 fffc
		instmem[34] = 32'b000000_11111_00000_00000_00000_001000;//jr      $31
		instmem[35] = 32'b100101_01111_00010_0000_0000_0000_0000;//	 ori    $2, $15, 0
		instmem[36] = 32'b001100_00000_00101_0000_0000_0000_0000;//shift_addr: addi   $5, $0, -1
		instmem[37] = 32'b000000_00000_00101_01111_01111_000000;//	 sll    $15, $5, 15         # 0xffff8000
		instmem[38] = 32'b000000_00000_01111_01111_10000_000000;//	 sll    $15, $15, 16        # 0x80000000 
		instmem[39] = 32'b000000_00000_01111_01111_01111_000011;//	 sra    $15, $15, 15        # 0xffff0000
		instmem[40] = 32'b000000_00000_01111_01111_10000_000010;//	 srl    $15, $15, 16        # 0x0000ffff
		instmem[41] = 32'b000010_0000000_0000_0000_0000_0010_0111;//end:	     j      end
		instmem[42] = 32'b00000_00000_00000_00000_00000_100101;//	 nop

请使用以下测试

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


		//相邻两条指令 	//ori R4,0000 -- R5 --0000ffff
        instmem [4] = 32'h34850000;	
		//相隔一条指令	//ori R4,0000 -- R6 --0000ffff
        instmem [5] = 32'h34860000;	
		//相隔两条指令	//ori R4,0000 -- R7 --0000ffff
		instmem [6] = 32'h34870000;	
		//load 相关
		//mem[0]=(r1)
		instmem[7]=32'b101011_00000_00001_0000_0000_0000_0000; //sw r1,0x0(r0)
		//(r8)=mem[0]
		instmem[8]=32'b100011_00000_01000_0000_0000_0000_0000; //lw r8,0x0(r0)
		instmem[9]=32'b001101_01000_01001_0000_0000_0000_0000; // ori r9 r8,0000

流水线的结果

load相关没有解决

但是有停顿出现

6设计指令流水线-2【FPGA模型机课程设计】_寄存器_02


load处理类似于

6设计指令流水线-2【FPGA模型机课程设计】_fpga开发_03

附录

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
	input wire[5:0] ex_op_i,			//ex 反馈 id op码
	input wire[4:0] ex_wd_to_id_i,  	//ex 反馈 id 写地址
	input wire ex_wreg_to_id_i,			//ex 反馈 给 id 写信号
	input wire [31:0] ex_wdata_to_id_i, //ex 反馈 给 id 写数据
	input wire[4:0] mem_wd_to_id_i,  	//mem 反馈 id写地址
	input wire mem_wreg_to_id_i,			//mem 反馈 给 id 写信号
	input wire [31:0] mem_wdata_to_id_i  //mem 反馈 给 id 写数据
);

	//方便修改
	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};

	//流水线
	reg stall_for_rega_loadreleate;
	reg stall_for_regb_loadreleate;
	wire pre_inst_is_load;

	//对stall先不处理
	assign stallreq=stall_for_rega_loadreleate|stall_for_regb_loadreleate;
	assign pre_inst_is_load =(ex_op_i==`Lw)?1'b1: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;	
*/

	//原子-修改
	//流水线需要有反馈数据的输入 选择器
	always@(*)    
		begin
			stall_for_rega_loadreleate=`NoStop;  
		    if(rst == `RstEnable)          
		        regaData = `Zero;      
		    //load相关 如果上一条指令是load 结果寄存器 == 当前指令源寄存器
			else if(pre_inst_is_load==1'b1 && ex_wd_to_id_i==regaAddr &®aRead==`Valid)
				stall_for_rega_loadreleate =`Stop;
			//相隔一条指令的冲突WAR
			else if(regaRead==`Valid&&ex_wreg_to_id_i==`Valid&&ex_wd_to_id_i==regaAddr)
				regaData=ex_wdata_to_id_i;		
			//相隔两条指令的冲突WAR
			else if(regaRead==`Valid&&mem_wreg_to_id_i==`Valid&&mem_wd_to_id_i==regaAddr)
				regaData=mem_wdata_to_id_i;		
			else if(op == `Lw || op == `Sw || op==`Ll || op==`Sc)               
		        regaData = regaData_i + imm;      
		    else if(regaRead == `Valid)          
		        regaData = regaData_i;      
		    else          
		        regaData = imm;    
		end

	always@(*) 
		begin     
			stall_for_regb_loadreleate=`NoStop;  
		    if(rst == `RstEnable)          
		        regbData = `Zero;    
		    //load相关 如果上一条指令是load 结果寄存器 == 当前指令源寄存器
			else if(pre_inst_is_load==1'b1 && ex_wd_to_id_i==regbAddr &®bRead==`Valid)
				stall_for_regb_loadreleate =`Stop;
			//相邻指令的冲突WAR
			else if(regbRead==`Valid&&ex_wreg_to_id_i==`Valid&&ex_wd_to_id_i==regbAddr)
				regbData=ex_wdata_to_id_i;		
			//相隔一条指令的冲突WAR
			else if(regbRead==`Valid&&mem_wreg_to_id_i==`Valid&&mem_wd_to_id_i==regbAddr)  
				regbData=mem_wdata_to_id_i;		
		    else if(regbRead == `Valid)          
		        regbData = regbData_i;      
		    else          
		    	regbData = imm;	
		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,	//传送
		output reg[5:0] ex_op_o,			 //ex 反馈 给 id op码
		output reg [4:0] ex_wd_to_id_o,		 //ex 反馈 给 id 读地址
		output reg ex_wreg_to_id_o,			 //ex 反馈 给 id 读信号
		output reg [31:0] ex_wdata_to_id_o 	 //ex 反馈 给 id 读数据
    );    

	assign op = op_i;
    assign memAddr = regaData;
    assign memData = regbData;

	//中断
	assign pc = pc_i;
	assign op = (excptype == `Zero) ?
				 op_i : `Nop;
	assign regcWrite =(excptype == `Zero) ?
				 regcWrite_i : `Invalid;


    always@(*)
		inst_o=inst_i;

	always@(*)
		begin
			ex_op_o=op_i;
			ex_wd_to_id_o=regcAddr;
			ex_wreg_to_id_o=regcWrite;
			ex_wdata_to_id_o=regcData;
		end

	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

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, 	//传送

	output reg [4:0] mem_wd_to_id_o,		 //mem 反馈 给 id 读地址
	output reg mem_wreg_to_id_o,			 //mem 反馈 给 id 读信号
	output reg [31:0] mem_wdata_to_id_o 	 //mem 反馈 给 id 读数据
	
);

	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@(*)
		begin
			mem_wd_to_id_o=regcAddr;
			mem_wreg_to_id_o=regcWr;
			mem_wdata_to_id_o=regData;
		end

	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
								wbit=`Valid;
								wLLbit = `ClearFlag;
							end
					end
				default:                  
				    begin                    
				        wtData = `Zero;                    
				        memWr = `RamUnWrite;                    
				        memCe = `RamDisable;  
				 		wbit=	`Invalid;
	   			  		wLLbit=`ClearFlag;                
				    end             
			endcase
		  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] 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;


	//流水线
	wire[5:0] ex_op;				//ex 反馈 id op码
	wire[4:0] ex_wd_to_id; 			//ex 反馈 id读地址
	wire ex_wreg_to_id;				//ex 反馈 给 id 读信号
	wire [31:0] ex_wdata_to_id; 	//ex 反馈 给 id 读数据
	wire[4:0] mem_wd_to_id; 		//mem 反馈 id读地址
	wire mem_wreg_to_id;			//mem 反馈 给 id 读信号
	wire [31:0] mem_wdata_to_id;  	//mem 反馈 给 id 读数据




	//中断修改
	//流水线修改
    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(instAddr),//pc的输入信号
		.pc(pc_id),	//pc的输出信号
		.excptype(excptype_id),//中断或异常的记录信息
		.inst_i(instruction_o_ifid),
		.inst_o(instruction_o_id),
		.stallreq(stall_id),
		.ex_op_i(ex_op),						//ex 反馈 id op码
		.ex_wd_to_id_i(ex_wd_to_id),  			//ex 反馈 id读地址
		.ex_wreg_to_id_i(ex_wreg_to_id),		//ex 反馈 给 id 读信号
		.ex_wdata_to_id_i(ex_wdata_to_id), 		//ex 反馈 给 id 读数据
		.mem_wd_to_id_i(mem_wd_to_id),  		//mem 反馈 id读地址
		.mem_wreg_to_id_i(mem_wreg_to_id),		//mem 反馈 给 id 读信号
		.mem_wdata_to_id_i(mem_wdata_to_id) 	//mem 反馈 给 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_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_op_o(ex_op),			 			//ex 反馈 给 id op码
		.ex_wd_to_id_o(ex_wd_to_id),		 	//ex 反馈 给 id 读地址
		.ex_wreg_to_id_o(ex_wreg_to_id),		//ex 反馈 给 id 读信号
		.ex_wdata_to_id_o(ex_wdata_to_id) 		//ex 反馈 给 id 读数据
    );    

	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_wd_to_id_o(mem_wd_to_id),		 		//mem 反馈 给 id 读地址
		.mem_wreg_to_id_o(mem_wreg_to_id),			//mem 反馈 给 id 读信号
		.mem_wdata_to_id_o(mem_wdata_to_id) 	 	//mem 反馈 给 id 读数据
	);

	//新增流水线寄存器
	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 R3,ffff -- R4 --0000ffff
        instmem [3] = 32'h3464ffff;


		//相邻两条指令 	//ori R4,0000 -- R5 --0000ffff
        instmem [4] = 32'h34850000;	
		//相隔一条指令	//ori R3,0000 -- R6 --0000ff00
        instmem [5] = 32'h34660000;	
		//相隔两条指令	//ori R5,0000 -- R7 --0000ffff
		instmem [6] = 32'h34A70000;	
		//load 相关
		//mem[0]=(r1)
		instmem[7]=32'b101011_00000_00001_0000_0000_0000_0000; //sw r1,0x0(r0)
		//(r8)=mem[0]
		instmem[8]=32'b100011_00000_01000_0000_0000_0000_0000; //lw r8,0x0(r0)
		instmem[9]=32'b001101_01000_01001_0000_0000_0000_0000; // ori r9 r8,0000	


      end
endmodule

标签:课程设计,wire,FPGA,Zero,inst,ex,流水线,id,op
From: https://blog.51cto.com/u_15719556/6407686

相关文章

  • 3.5 Y84-64的流水线实现
    我们终于准备好要开始本章的主要任务——设计一个流水线化的Y86-64处理器。首先,对顺序的SEQ处理器做一点小的改动,将PC的计算挪到取指阶段。然后,在各个阶段之间加上流水线寄存器。到这个时候,我们的尝试还不能正确处理各种数据和控制相关。不过,做一些修改,就能实现我们的目标——一个......
  • m基于FPGA的RGB转ycrcb颜色空间转换算法实现,包含testbench,对比三种转换方法
    1.算法仿真效果vivado2019.2仿真结果如下:其中1为直接乘法公式计算;2为移位法计算;3为分布式计算;2.算法涉及理论知识概要人类获得信息的主要方式是视觉,通常情况下颜色有2种描述方式,一种是RGB色度空间表示,一种是YCbCr色度空间表示。然而,普通的RGB颜色空间对视频的显示存在......
  • m基于FPGA的RGB转ycrcb颜色空间转换算法实现,包含testbench,对比三种转换方法
    1.算法仿真效果vivado2019.2仿真结果如下: 其中1为直接乘法公式计算; 2为移位法计算; 3为分布式计算; 2.算法涉及理论知识概要        人类获得信息的主要方式是视觉,通常情况下颜色有2种描述方式,一种是RGB色度空间表示,一种是YCbCr色度空间表示。然而,普通......
  • C/C++数据结构课程设计[2023-05-31]
    C/C++数据结构课程设计[2023-05-31]数据结构课程设计实验(训)指导书所在学院:计算机科学与工程学院编写说明一.实验总体目标《数据结构》是一门实践性较强的课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践。本实验的目标是,学生能正确理解和熟练掌握常用数据结构和算......
  • 基于FPGA的LFSR16位伪随机数产生算法实现,可以配置不同的随机数种子和改生成多项式,包
    1.算法仿真效果vivado2019.2仿真结果如下:2.算法涉及理论知识概要LFSR(线性反馈移位寄存器)提供了一种在微控制器上快速生成非序列数字列表的简单方法。生成伪随机数只需要右移操作和XOR操作。LFSR完全由其多项式指定。例如,6千-次多项式与每个项存在用方程x表示6+x5+x4+x3......
  • 三方仓库如何实现Zadig流水线自动触发
    !!大家好,我是乔克,一个爱折腾的运维工程,一个睡觉都被自己丑醒的云原生爱好者。作者:乔克公众号:运维开发故事博客:www.jokerbai.com最近因为公司的产研调整,决定将代码仓库从本地的Gitlab迁移到云效的Codeup,不是Gitlab不够好,而是Codeup在度量、安全等方面比原生的Gitlab要好,再......
  • C语言课程设计题目[2023-05-29]
    C语言课程设计题目[2023-05-29]C语言课程设计题目一、设计要求与设计报告设计要求1.任意选定以下一个题目完成2.模块化程序设计3.锯齿型程序书写格式4.必须上机调试通过设计报告格式1.设计目的2.总体设计(程序设计组成框图、流程图)3.详细设计(模块功能说明(如函数功能、入......
  • 3.4 流水线的通用原理
    流水线化的一个重要特性就是提高了系统的吞吐量,不过会轻微增加延迟。计算流水线在现代逻辑设计中,电路延迟以微微秒或皮秒,也就是10的负12次方秒为单位进行计算。假设将系统执行的计算分为三个阶段,每个阶段需要100ps,然后在每个阶段之间放上流水线寄存器,流水线寄存器的延迟为20ps,这......
  • 3模型机指令系统设计-2【FPGA模型机课程设计】
    3模型机指令系统设计-2【FPGA模型机课程设计】前言推荐3模型机指令系统设计-2安排MIPS12条整数指令测试与结果乘除法指令实现和功能仿真要点1乘法除法指令格式2通路增加部件3对整体通路的影响4功能验证代码设计defineIDEXEX1HiLo高位低位寄存器MIPSInstMem附录0框架1defin......
  • C++“高级程序设计实践(C++)”课程设计任务书[2023-05-28]
    C++“高级程序设计实践(C++)”课程设计任务书[2023-05-28]“高级程序设计实践(C++)”课程设计任务书一.课程设计的目的与任务本设计是课程——《面向对象编程(C++)》的一个关键实践环节。它是根据教学计划的要求,在教师的指导下,对学生实施程序设计训练的必要过程,是对前期课堂学习内......