[FPGA] MIPS 12条整数指令【2】
目录
仿真
代码
完整代码
实现slt
仿真
ori r1,r0,1100h
ori r2,r0,0020h
ori r3,r0,ff00h
ori r4,r0,ffffhaddi r5,r0,ffff
slt r6,r5,r4
slt r6,r4,r3
代码
EX
`Slt:
regcData = ($signed(regaData)<$signed(regbData))?1'b1:1'b0;
ID
`Inst_slt:
begin
op = `Slt;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
imm = `Zero;
end
完整代码
`include "define.v";
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
);
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;
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
end
else
begin
jCe = `Invalid;//J
jAddr = `Zero;//J
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_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 = `Invalid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = inst[20:16];
imm = {inst[15:0],16'h0};
end
`Inst_r:
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]};
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]};
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]};
end
`Inst_jr:
begin
op = `Jr;
regaRead = `Valid;//rs
regbRead = `Invalid;
regcWrite = `Invalid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = 5'b11111;
jAddr = regaData;
jCe = `Valid;
imm = `Zero;
end
`Inst_jalr:
begin
op = `Jal;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = `Zero;
regcAddr = inst[15:11]; //
jAddr = regaData;
jCe = `Valid;
imm = npc;
end
`Inst_slt:
begin
op = `Slt;
regaRead = `Valid;
regbRead = `Invalid;
regcWrite = `Valid;
regaAddr = inst[25:21];
regbAddr = inst[20:16];
regcAddr = inst[15:11];
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;
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};
jCe=(regaData==regbData)?`Valid:`Invalid;
/* if(regaData==regbData)
jCe = `Valid;
else
jCe = `Invalid;*/
imm = `Zero;
end
`Inst_bne:
begin
op = `Bne;
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};
jCe=(regaData!=regbData)?`Valid:`Invalid;
/* if(regaData!=regbData)
jCe = `Valid;
else
jCe = `Invalid;
*/
imm = `Zero;
end
`Inst_bgtz:
begin
op = `Bgtz;
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};
jCe = (regaData[31]==0)?`Valid:`Invalid;
imm = 32'b0; //
end
`Inst_bltz:
begin
op = `Bgtz;
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};
jCe = (regaData[31]==1)?`Valid:`Invalid; //
imm = 32'b0; //
end
`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
default:
begin
op = `Nop;
regaRead = `Invalid;
regbRead = `Invalid;
regcWrite = `Invalid;
regaAddr = `Zero;
regbAddr = `Zero;
regcAddr = `Zero;
imm = `Zero;
end
endcase
end
/*
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;
*/
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)
regbData = `Zero;
else if(regbRead == `Valid)
regbData = regbData_i;
else
regbData = imm;
endmodule
`include "define.v";
module DataMem(
input wire clk,
input wire ce,
input wire we,
input wire [31:0] addr,
input wire [31:0] wtData,
output reg [31:0] rdData
);
reg [31:0] datamem [1023 : 0];
always@(*)
if(ce == `RamDisable)
rdData = `Zero;
else
rdData = datamem[addr[11 : 2]];
always@(posedge clk)
if(ce == `RamEnable && we == `RamWrite)
datamem[addr[11 : 2]] = wtData;
else ;
endmodule
`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
//I
`define Inst_ori 6'b001101
`define Inst_addi 6'b001000
`define Inst_andi 6'b001100
`define Inst_xori 6'b001110
`define Inst_lui 6'b001111
`define Inst_subi 6'b001001
//lw sw
`define Inst_lw 6'b100011
`define Inst_sw 6'b101011
//beq bne
`define Inst_beq 6'b000100
`define Inst_bne 6'b000101
//R
`define Inst_r 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
//J
`define Inst_j 6'b000010
`define Inst_jal 6'b000011
//12
`define Inst_slt 6'b101010
`define Inst_bgtz 6'b000111
`define Inst_bltz 6'b000001
`define Inst_jalr 6'b001001
`define Inst_mult 6'b011000
`define Inst_multu 6'b011001
`define Inst_div 6'b011010
`define Inst_divu 6'b011011
`define Inst_mfhi 6'b010000
`define Inst_mflo 6'b010010
`define Inst_mthi 6'b010001
`define Inst_mtlo 6'b010011
//
`define Inst_ll 6'b110000
`define Inst_sc 6'b111000
`define Inst_mfc0 6'b000000
`define Inst_mtc0 6'b000000
`define Inst_eret 6'b011000
`define syscall 6'b001100
`define Nop 6'b000000
`define Or 6'b000001
`define Add 6'b000010
`define And 6'b000011
`define Xor 6'b000100
`define Lui 6'b000101
`define Sub 6'b000110
`define Sll 6'b000111
`define Srl 6'b001000
`define Sra 6'b001001
`define J 6'b001010
`define Jal 6'b001011
`define Beq 6'b001100
`define Bne 6'b001101
`define Jr 6'b001110
`define Lw 6'b010000
`define Sw 6'b010001
`define Bgtz 6'b010010
`define Bltz 6'b010011
`define Slt 6'b010100
//MEM
`define RamWrite 1'b1
`define RamUnWrite 1'b0
`define RamEnable 1'b1
`define RamDisable 1'b0
`include "define.v"
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,
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
);
assign op = op_i;
assign memAddr = regaData;
assign memData = regbData;
always@(*)
if(rst == `RstEnable)
regcData = `Zero;
else
begin
//case(op)
case(op_i)
`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;
`Sll:
regcData = regbData << regaData;
`Srl:
regcData = regbData >> regaData;
`Sra:
regcData = ($signed(regbData)) >>> regaData;
`J:
regcData = `Zero;
`Jr:
regcData = `Zero;
`Jal:
regcData = regbData;
`Beq:
regcData = `Zero;
`Bne:
regcData = `Zero;
`Bltz:
regcData = `Zero;
`Bgtz:
regcData = `Zero;
`Slt:
regcData = ($signed(regaData)<$signed(regbData))?1'b1:1'b0;
default:
regcData = `Zero;
endcase
end
assign regcWrite = regcWrite_i;
assign regcAddr = regcAddr_i;
endmodule
`include "define.v"
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
);
always@(*)
if(rst == `RstEnable)
ce = `RomDisable;
else
ce = `RomEnable;
/* always@(posedge clk)
if(ce == `RomDisable)
pc = `Zero;
else
pc = pc + 4;
*/
always@(posedge clk)
if(ce == `RomDisable)
pc = `Zero;
else if(jCe == `Valid)//J
pc = jAddr;
else
pc = pc + 4;
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'h2005ffff; //addi r5,r0,ffff r5--32'hffff ffff
instmem [5] =32'b000000_00101_00100_00110_00000_101010; //slt r6,r5,r4
instmem [6] =32'b000000_00100_00011_00110_00000_101010; //slt r6,r4,r3
end
endmodule
`include "define.v";
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,
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
);
assign regAddr = regcAddr;
assign regWr = regcWr;
assign regData = (op == `Lw) ? rdData : regcData;
assign memAddr = memAddr_i;
always @(*)
if(rst == `RstEnable)
begin
wtData = `Zero;
memWr = `RamUnWrite;
memCe = `RamDisable;
end
else
case(op)
`Lw:
begin
wtData = `Zero;
memWr = `RamUnWrite;
memCe = `RamEnable;
end
`Sw:
begin
wtData = memData;
memWr = `RamWrite;
memCe = `RamEnable;
end
default:
begin
wtData = `Zero;
memWr = `RamUnWrite;
memCe = `RamDisable;
end
endcase
endmodule
`include "define.v";
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
);
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 [5:0] regAddr_mem;
wire [31:0] regData_mem;
wire regWr_mem;
IF if0(
.clk(clk),
.rst(rst),
.jAddr(jAddr),//J
.jCe(jCe),//J
.ce(romCe),
.pc(instAddr)
);
ID id0(
.rst(rst),
.pc(instAddr),//J
.inst(instruction),
.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
);
EX ex0(
.rst(rst),
//.op(op),
.op_i(op_id),
.regaData(regaData_id),
.regbData(regbData_id),
.regcWrite_i(regcWrite_id),
.regcAddr_i(regcAddr_id),
.regcData(regcData_ex),
.regcWrite(regcWrite_ex),
.regcAddr(regcAddr_ex),
.op(op_ex),//ls
.memAddr(memAddr_ex),//ls
.memData(memData_ex)//ls
);
MEM mem0(
.rst(rst),
.op(op_ex),
.regcData(regcData_ex),
.regcAddr(regcAddr_ex),
.regcWr(regcWrite_ex),
.memAddr_i(memAddr_ex),
.memData(memData_ex),
.rdData(rdData),
.regAddr(regAddr_mem),
.regWr(regWr_mem),
.regData(regData_mem),
.memAddr(memAddr),
.wtData(wtData),
.memWr(memWr),
.memCe(memCe)
);
RegFile regfile0(
.clk(clk),
.rst(rst),
//.we(regcWrite_ex),
.we(regWr_mem),
//.waddr(regcAddr_ex),
.waddr(regAddr_mem),
//.wdata(regcData_ex),
.wdata(regData_mem),
.regaRead(regaRead),
.regbRead(regbRead),
.regaAddr(regaAddr),
.regbAddr(regbAddr),
.regaData(regaData_regFile),
.regbData(regbData_regFile)
);
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
module SoC(
input wire clk,
input wire rst
);
wire [31:0] instAddr;
wire [31:0] instruction;
wire romCe;
//ls
wire memCe, memWr;
wire [31:0] memAddr;
wire [31:0] rdData;
wire [31:0] wtData;
MIPS mips0(
.clk(clk),
.rst(rst),
.instruction(instruction),
.instAddr(instAddr),
.romCe(romCe),
.rdData(rdData),
.wtData(wtData),
.memAddr(memAddr),
.memCe(memCe),
.memWr(memWr)
);
InstMem instrom0(
.ce(romCe),
.addr(instAddr),
.data(instruction)
);
//DataMem
DataMem datamem0(
.ce(memCe),
.clk(clk),
.we(memWr),
.addr(memAddr),
.wtData(wtData),
.rdData(rdData)
);
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