我们接下来将使用verilog语言编写一个单周期的mips,话不多说让我们开始吧
编写指令为了确保好上手,我们将有选择性的只完成mips中的八条指令
mips的指令格式形式主要为
实现的指令•Instruction Syntax is rigid:
op dst, src1, src2
–1 operator, 3 operands
•op = operation name (“operator”)
•dst = register getting result (“destination”)
•src1 = first register for operation (“source 1”)
src2 = second register for operation (“source 2
addu
subu :主要实现寄存器内两数的加减
lw
sw :
beq:•Branch If Equal (beq)
–beq reg1,reg2,label
–If value in reg1 = value in reg2, go to label
jump:•Jump (j)
–j label
ori:
lui
指令格式
其中包括i-format , j-format,r-format
三种格式
•I-Format: instructions with immediates, lw/sw (offset is immediate), and beq/bne
–But not the shift instructions
•J-Format: j and jal
–But not jr
•R-Format: all other instructions
•It will soon become clear why the instructions have been partitioned in this way
r指令的格式
addu的rformat格式
i-format
datapath
下面我们就开始写不同组件部分
ext(移位extender)作为一个移位器,主要是用来对外界输入的immediate进行移位,根据输入的extop选项决定进行符号扩展还是0扩展,扩展好变成32位以后,进入下一步的运算,在我们所列的八条指令中,所有i指令的都会需要用到移位器进行运算 而(beq,jump指令会在ifu内置的移位器中完成操作,我们不作考虑)
module ext(imm16,imm32,ExtOp);
input [15:0]imm16;
input [1:0]ExtOp;
output reg[31:0]imm32;
//set ZERO,SIGN,LUI
parameter ZERO
alu
接下来便是十分重要的累加器alu了,alu承担了大部分运算的功能与职责
alu主要用aluctr接受信号
可以执行 add sub or lui
四种操作
因为addu subu ori lui 最后的输出操作是输入到aluout去
而执行lw和sw的时候则需要addr进行访存,因此我们还需要一个输出端口addr
另外还需要产生一个zero信号来供pc判断是否beq的条件相等
module alu(busA,busB,ALUctr,zero,Alu_out,Addr);
input [31:0]busA,busB;
input [1:0]ALUctr;
output [31:0]zero,Addr;
output reg[31:0]Alu_out;
//set ADD,SUB,OR,Lui
parameter ADD
mux 选择器
写一个用三次即可
这里不多加赘述
ifu instruction fetch unit
ifu是最为复杂的一个部件
在其中内置一个ext 我们主要将会用它来beq和jump的扩展,同时也会进行下一轮指令的选择
信号ifu接受npc_sel的信号用来判定是否为j指令或beq指令,zero判断j指令的条件
接受clk作为时钟周期
用rst接受是否初始化的标志,在读取玩数据后,以instruction作为输出
存取指令手下那我们需要知道,在ifu中的指令存取次奥那等是大端序,也就是说第一个位置放的是最大位数的数
因为pc在运行的时候每次运行
都要加4,这是因为每条指令会占四个格子
我们所有的操作也是在+4以后进行的
jump操作因为特定的只有26位,但又因为我们是需要直接跳到指令的头部进行操作,因此必须是四的倍数,所以我们直接移两位
从操作的逻辑中很明显我们也能看出来实现beq操作的时候的相对位移值也必须是4的倍数,这样更节约空间!!!!!
module ifu(nPC_sel,zero,clk,rst,instruction,j_sel,jValue);
input clk,rst;
input [1:0]nPC_sel;
input [31:0]zero;
input j_sel;
input [25:0]jValue;
output [31:0]instruction;
reg [31:0]pc;
reg [7:0]im[1023:0];
reg [31:0]pcnew;
wire [31:0]temp,t0,t1;
wire [15:0]imm16;
reg [31:0]extout;
//give instruction a value
assign instruction