/// LSU EE 3755 -- Spring 2002 -- Computer Architecture
//
/// MIPS Processor Functional Simulator
//
// Implements a small subset of MIPS32 instructions and features.
//
// Time-stamp: <29 April 2002, 15:30:56 CDT, koppel@neptune>
//
/// Dependencies
/// To compile run this the following is also needed:
//
// mips_fs_tb.v The testbench. It is included in here for convenience.
// mipsmemmacros.v Macros needed for memory access.
//
// An "assembled" program, for example tthird.v. The name of the
// file is specified in the MIPS_PROG macro, the testbench uses the
// macro to include the file.
/// Limitations
//
// This code will probably never implement all of MIPS32. The intent
// is to demonstrate basic MIPS simulation techniques as a first step
// towards developing synthesizable and implementatble descriptions.
//
/// Specify Program to Load
//
// A quick-and-dirty method of loading a program is used. (For now.)
// Therefore the description must be re-compiled each time the program
// is changed. (The program is assembled by SPIM and some perl code.)
//
`define MIPS_PROG "tthird.v"
`include "mipsmemmacros.v"
module proc(exc,clk);
input clk;
output exc;
// add $2, $3, $4
reg [31:0] pc, npc, nnpc;
reg [31:0] ir;
reg [5:0] opcode, func;
reg [4:0] rs, rt, rd, sa;
reg [15:0] immed;
reg [25:0] ii;
reg [7:0] mem ['h400000:'h400200];
reg [31:0] gpr [0:31];
reg [31:0] simmed, uimmed;
reg [7:0] temp;
parameter F_add = 6'h20;
parameter F_sll = 6'h0;
parameter F_srl = 6'h2;
parameter F_sub = 6'h22;
parameter F_or = 6'h25;
parameter F_jr = 6'h8;
parameter O_tyr = 6'h0;
parameter O_addi = 6'h8;
parameter O_j = 6'h2;
parameter O_jal = 6'h3;
parameter O_beq = 6'h4;
parameter O_bne = 6'h5;
parameter O_slti = 6'ha;
parameter O_andi = 6'hc;
parameter O_ori = 6'hd;
parameter O_lui = 6'hf;
parameter O_lw = 6'h23;
parameter O_lbu = 6'h24;
parameter O_lb = 6'h20;
parameter O_sw = 6'h2b;
parameter O_sb = 6'h28;
always @( posedge clk ) begin
ir = {mem[pc],mem[pc+1],mem[pc+2],mem[pc+3]};
{opcode, rs, rt, rd, sa, func} = ir;
immed = ir[15:0];
ii = ir[25:0];
simmed = {immed[15] ? 16'hffff : 16'h0, immed};
uimmed = { 16'h0, immed };
nnpc = npc + 4; // Reassigned below.
case( opcode )
O_tyr:
case( func )
F_add: gpr[rd] = gpr[rs] + gpr[rt];
F_sub: gpr[rd] = gpr[rs] - gpr[rt];
F_sll: gpr[rd] = gpr[rt] << sa;
F_jr: nnpc = gpr[rs];
default: $stop;
endcase
O_addi: gpr[rt] = gpr[rs] + simmed;
O_andi: gpr[rt] = gpr[rs] & uimmed;
O_ori: gpr[rt] = gpr[rs] | uimmed;
O_lui: gpr[rt] = {immed,16'h0};
O_bne: if( gpr[rt] != gpr[rs] ) nnpc = npc + ( simmed << 2 );
O_j: nnpc = {npc[31:28],ii,2'd0};
O_jal: begin gpr[31] = nnpc; nnpc = {npc[31:28],ii,2'd0}; end
O_lbu: gpr[rt] = {24'b0, mem[`A(gpr[rs]+simmed)]};
O_lb:
begin
temp = mem[`A(gpr[rs]+simmed)];
gpr[rt] = {temp[7] ? 24'hffffff : 24'h0, temp};
end
O_sb: mem[`A(gpr[rs]+simmed)]= gpr[rt];
default: $stop;
endcase
gpr[0] = 0;
pc = npc;
npc = nnpc;
end
endmodule
`include "mips_fs_tb.v"