【计组】实验三 ORI指令设计实验

一、实验目的

  1. 理解MIPS处理器指令格式及功能。

  2. 掌握ori指令格式与功能。

  3. 掌握ModelSim和ISE\Vivado工具软件。

  4. 掌握基本的测试代码编写和FPGA开发板使用方法。

二、实验环境

  1. 装有ModelSim和ISE\Vivado的计算机。

  2. Sword\Basys3\EGo1实验系统。

三、实验原理

MIPS是一款作为上世纪80年代的推出处理器,在美国与我国许多著名高校都作为教学研究的处理器。本次实验以32位MIPS为例,通过设计基本的MIPS指令集,从而掌握现代处理器的设计原理与方法。

MIPS处理器的指令格式分为R型、I型和J型。R型为寄存器型,即两个源操作数和目的操作数都是寄存器性。I型为操作数含有立即数。而J型特指转移类型指令,如图1所示。

如图2所示,本次实验及其后续实验挑选部分MIPS处理器指令进行实现。以ori指令为例说明,其中rs为源操作数寄存器,imm为立即数型源操作数,由于是逻辑运算,所以imm按无符号数(零)扩展为32位数,运算结果存入rt目的操作数寄存器。

如图3所示为按照单指令周期设计MIPS处理器内部结构。所有控制信号及字段均标注出来。另外,每条指令周期都包含2个clk,即PC模块用1个clk,Regfile和DataMem模块用1个clk,也可以说是由2个时钟构成的指令流水线。

为了便于今后的扩展,将MIPS处理器在图3的基础上进行了分阶段设计,这样结构更清晰,也有利于流水线的设计。随着后续指令的不断添加,处理器内部结构设计也会进行相应的调整。

用Verilog HDL设计32位MIPS处理器ORI指令实现,参照图4的MIPS内部结构示意图,将设计的MIPS处理器改造为分阶段实现方案,注意每条指令周期平均只包含1个时钟周期。先编写基本实现代码,即能实现ORI指令的取指令和执行指令。

`include "define.v"
module IF(
    input wire clk,
    input wire rst,
    output reg ce, 
output reg [31:0] pc
);
    always@(*)
        if(rst == `RstEnable)
            ce = `RomDisable;
        else
            ce = `RomEnable;
    always@(posedge clk)
        if(ce == `RomDisable)
            pc = `Zero;
        else
            pc = pc + 4;
endmodule
`include "define.v"
module  ID (
    input wire rst,    
    input wire [31:0] inst,
    input wire [31:0] regaData_i,
    input wire [31:0] regbData_i,
    output reg [5:0] op,
    output reg [4:0] regaAddr,
    output reg [4:0] regbAddr,    
    output reg [4:0] regcAddr,    
    output reg [31:0] regaData,
    output reg [31:0] regbData,
    output reg regaRead,
    output reg regbRead,
    output reg regcWrite    
);
    wire [5:0] inst_op = inst[31:26];    
    reg [31:0] imm;
    always@(*)
        if(rst == `RstEnable)
          begin
            op = `Nop;
            regaRead = `Invalid;
            regbRead = `Invalid;
            regcWrite = `Invalid;
            regaAddr = `Zero;
            regbAddr = `Zero;
            regcAddr = `Zero;
            imm = `Zero;
          end
        else  
            case(inst_op)
                `Inst_ori:
                  begin
                    op = `Or;
                    regaRead = `Valid;
                    regbRead = `Invalid;
                    regcWrite = `Valid;
                    regaAddr = inst[25:21];
                    regbAddr = `Zero;
                    regcAddr = inst[20:16];
                    imm = {16'h0, inst[15:0]};
                  end
		`Inst_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_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_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 = `Invalid;
                    regbRead = `Invalid;
                    regcWrite = `Valid;
                    regaAddr = `Zero;
                    regbAddr = `Zero;
                    regcAddr = inst[20:16];
                    imm = {inst[15:0],16'h0};
                  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
		*/
                default:
                  begin
                    op = `Nop;
                    regaRead = `Invalid;
                    regbRead = `Invalid;
                    regcWrite = `Invalid;
                    regaAddr = `Zero;
                    regbAddr = `Zero;
                    regcAddr = `Zero;
                    imm = `Zero;
                  end
            endcase
    always@(*)
      if(rst == `RstEnable)
          regaData = `Zero;
      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
`include "define.v"
module EX(
    input wire rst,
    input wire [5:0] op,    
    input wire [31:0] regaData,
    input wire [31:0] regbData,
    input wire regcWrite_i,
    input wire [4:0]regcAddr_i,
    output reg [31:0] regcData,
    output wire regcWrite,
    output wire [4:0] regcAddr
);    
    always@(*)
        if(rst == `RstEnable)
            regcData = `Zero;
        else
          begin
            case(op)
                `Or:
                    regcData = regaData | regbData;
	     	`Add:
		    regcData = regaData + regbData;
		`And:
		    regcData = regaData & regbData;
		`Xor:
		    regcData = regaData ^ regbData;
		`Lui:
		    regcData = regaData;
		/*`Lui:
		    regcData = regaData | regbData;
		*/
		`Sub:
		    regcData = regaData - regbData;
                default:
                    regcData = `Zero;
            endcase

          end
    assign regcWrite = regcWrite_i;
    assign regcAddr = regcAddr_i;
endmodule
`include "define.v"
module RegFile(
    input wire clk,
    input wire rst,
    input wire we,
    input wire [4:0] waddr,
    input wire [31:0] wdata,
    input wire regaRead,
    input wire regbRead,
    input wire [4:0] regaAddr,
    input wire [4:0] regbAddr,
    output reg [31:0] regaData,
    output reg [31:0] regbData
);
    reg [31:0] reg32 [31 : 0];    
    always@(*)
        if(rst == `RstEnable)
            regaData = `Zero;
        else if(regaAddr == `Zero)
            regaData = `Zero;
        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 != `RstEnable)
            if((we == `Valid) && (waddr != `Zero))
                reg32[waddr] = wdata;
        else ;          
endmodule
`include "define.v"
module MIPS(
    input wire clk,
    input wire rst,
    input wire [31:0] instruction,
    output wire romCe,
    output wire [31:0] instAddr
);
    wire [31:0] regaData_regFile, regbData_regFile;
    wire [31:0] regaData_id, regbData_id; 
    wire [31:0] regcData_ex;
    wire [5:0] op;    
    wire regaRead, regbRead;
    wire [4:0] regaAddr, regbAddr;
    wire regcWrite_id, regcWrite_ex;
    wire [4:0] regcAddr_id, regcAddr_ex;
    IF if0(
        .clk(clk),
        .rst(rst),
        .ce(romCe), 
        .pc(instAddr)
    );
    ID id0(
        .rst(rst),        
        .inst(instruction),
        .regaData_i(regaData_regFile),
        .regbData_i(regbData_regFile),
        .op(op),
        .regaData(regaData_id),
        .regbData(regbData_id),
        .regaRead(regaRead),
        .regbRead(regbRead),
        .regaAddr(regaAddr),
        .regbAddr(regbAddr),
        .regcWrite(regcWrite_id),
        .regcAddr(regcAddr_id)
    );
    EX ex0(
        .rst(rst),
        .op(op),        
        .regaData(regaData_id),
        .regbData(regbData_id),
        .regcWrite_i(regcWrite_id),
        .regcAddr_i(regcAddr_id),


        .regcData(regcData_ex),
        .regcWrite(regcWrite_ex),
        .regcAddr(regcAddr_ex)
    );    
    RegFile regfile0(
        .clk(clk),
        .rst(rst),

        .we(regcWrite_ex),
        .waddr(regcAddr_ex),
        .wdata(regcData_ex),

        .regaRead(regaRead),
        .regbRead(regbRead),
        .regaAddr(regaAddr),
        .regbAddr(regbAddr),
        .regaData(regaData_regFile),
        .regbData(regbData_regFile)
    );
endmodule
`include "define.v"
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
        instmem [0] = 32'h34011100;   //ori r1,r0,1100h         r1--32'h0000 1100
        instmem [1] = 32'h34020020;   //ori r2,r0,0020h		r2--32'h0000 0020
        instmem [2] = 32'h3403ff00;   //ori r3,r0,ff00h		r3--32'h0000 ff00
        instmem [3] = 32'h3404ffff;   //ori r4,r0,ffffh		r4--32'h0000 ffff
	
	instmem [4] = 32'h3005ffff;	//andi r5,r0,ffff	r5--32'h0000 0000
	instmem [5] = 32'h3806ffff;	//xori r6,r0,ffff	r6--32'h0000 ffff
	instmem [6] = 32'h2007ffff;	//addi r7,r0,ffff	r7--32'hffff ffff
	instmem [7] = 32'h3c081234;     //lui r8,1234		r8--32'h1234 0000
		
	instmem [8] = 32'h35095679;     //ori r9,r8,5678	r9--32'h1234 5679
	instmem [9] = 32'h212aa011;     //addi r10,r9,a011	r10--32'h1233 f68a
	instmem [10] = 32'h306b1111;	//andi r11,r3,1111	r10--32'h0000 1100
	instmem [11] = 32'h254C1111;    //subi r12,r10,1111     r12--32'h1234 e579
      end
endmodule
module SoC(
    input wire clk,
    input wire rst
);
    wire [31:0] instAddr;
    wire [31:0] instruction;
    wire romCe;    
    MIPS mips0(
        .clk(clk),
        .rst(rst),
        .instruction(instruction),
        .instAddr(instAddr),
        .romCe(romCe)
    );    
    InstMem instrom0(
        .ce(romCe),
        .addr(instAddr),
        .data(instruction)
    );
endmodule

`include "define.v"
module soc_tb;
    reg clk;
    reg rst;
    initial
      begin
        clk = 0;
        rst = `RstEnable;
        #100
        rst = `RstDisable;
        #10000 $stop;        
      end
    always #10 clk = ~ clk;
    SoC soc0(
        .clk(clk), 
        .rst(rst)
    );
endmodule

在完成基本实验的基础上,如图4所示,将ANDI, XOI, ADDI,SUBI和LUI等指令添加进去,然后进行设计实现和验证结果。

相关推荐
超能力MAX3 小时前
时钟分频模块
fpga开发
Anin蓝天(北京太速科技-陈)1 天前
211-基于FMC的1路1.5G ADC 1路 2.5G DAC子卡
嵌入式硬件·5g·fpga开发·信号处理
LabVIEW开发1 天前
基于X410的LabVIEW FPGA跳频通信系统开发
fpga开发·labview知识
北京太速科技股份有限公司1 天前
太速科技-365-基于XC7Z045+AD9361的双收双发无线电射频板卡
fpga开发
北京太速科技股份有限公司1 天前
太速科技-428-基于XC7Z100+ADRV9009的双收双发无线电射频板卡
fpga开发
luoganttcc2 天前
优秀的 Verilog/FPGA开源项目介绍(二)-RISC-V
fpga开发·开源·risc-v
luoganttcc2 天前
FPGA有哪些优质的带源码的IP开源网站
网络协议·tcp/ip·fpga开发
cckkppll2 天前
移位寄存器和延迟线
fpga开发
国科安芯2 天前
低成本抗辐照MCU控制板
单片机·嵌入式硬件·fpga开发·安全威胁分析