`define MIPS_PROG "uc.v"
`define MEMBASE 'h400000
`define DATABASE 'h10010000
`define TEXTSIZE 'h100
`define MEMSIZE 'h200
`define MEMRANGE `MEMBASE:`MEMBASE+`MEMSIZE-1
`define A(addr) ((addr)-`DATABASE+`MEMBASE+`TEXTSIZE)
`define MEM(addr) mem[((addr)-`DATABASE+`MEMBASE+`TEXTSIZE)]
module proc(exc,clk);
input clk;
output exc;
reg exc;
reg [7:0] mem [`MEMRANGE];
reg [31:0] pc, npc, nnpc, ir;
reg [31:0] gpr [0:31];
reg [5:0] opcode, funct;
reg [4:0] rs, rt, rd, sa;
reg [15:0] immed;
reg [25:0] ii;
reg [31:0] uimm16, simm16;
reg [31:0] branch_target;
// Values for funct field.
parameter f_sll = 6'h0;
parameter f_srl = 6'h2;
parameter f_add = 6'h20;
parameter f_sub = 6'h22;
parameter f_or = 6'h25;
// Values for opcode field.
parameter o_j = 6'h2;
parameter o_beq = 6'h4;
parameter o_bne = 6'h5;
parameter o_addi = 6'h8;
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_sw = 6'h2b;
parameter o_sb = 6'h28;
initial begin
exc = 0;
pc = 0;
npc = 4;
end
always @( posedge clk ) begin
ir = {mem[pc],mem[pc+1],mem[pc+2],mem[pc+3]};
// R Format
{opcode,rs,rt,rd,sa,funct} = ir;
nnpc = npc + 4; // May be reassigned below.
if( !opcode ) begin
//
// R-Format Instructions
case( funct )
f_sll : gpr[rd] = gpr[rt] << sa;
f_srl : gpr[rd] = gpr[rt] >> sa;
f_add : gpr[rd] = gpr[rs] + gpr[rt];
f_or : gpr[rd] = gpr[rs] | gpr[rt];
f_sub : gpr[rd] = gpr[rs] - gpr[rt];
default : exc = 1;
endcase
end else begin
//
// I- and J-Format Instructions
// I Format (Also uses opcode, rs, and rt.)
immed = ir[15:0];
// J Format (Also uses opcode.)
ii = ir[25:0];
uimm16 = { 16'b0, immed };
simm16 = immed[15] ? { 16'hffff, immed } : uimm16;
branch_target = npc + ( simm16 << 2 );
case( opcode )
o_j : nnpc = {npc[31:28],ii,2'b0};
o_beq : if( gpr[rs] == gpr[rt] ) nnpc = branch_target;
o_bne : if( gpr[rs] != gpr[rt] ) nnpc = branch_target;
o_andi : gpr[rt] = gpr[rs] & uimm16;
o_slti : gpr[rt] = gpr[rs] < simm16;
o_addi : gpr[rt] = gpr[rs] + simm16;
o_ori : gpr[rt] = gpr[rs] | uimm16;
o_lui : gpr[rt] = { immed, 16'b0 };
o_lbu : gpr[rt] = { 24'b0, `MEM( gpr[rs] + simm16 ) };
o_sb : `MEM( gpr[rs] + simm16 ) = gpr[rt];
default : exc = 1;
endcase
end
gpr[0] = 0;
pc = npc;
npc = nnpc;
end
endmodule
`include "mipsi1tb.v"