/// LSU EE 3755 – Fall 2009 -- Computer Organization.

 

//

/// MIPS Processor Functional Unit.

//

// Implements a small subset of MIPS32 instructions and features.

/

 

// The intent   is to demonstrate basic MIPS CPU functionality,

//  to clarify the concept of data path we just covered.

 

module proc(exc,clk);

   input clk;

   output exc;

 

   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 = {pc[31:28],ii,2'd0};

        O_jal:  begin gpr[31] = nnpc;  nnpc = {pc[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