/// EE 3755 -- Spring 2002 -- Computer Organization // /// Example used in class 8 May 2002 // /// Hardwired Control, Multicycle MIPS, Day 5 // // // Will be added to each day. // /// Day 1: 29 April 2002 // // Started moving memory out of the processor by adding ports for an // external memory. The module system (at the end of this file) // connects cpu to the memory. Not in a working state. // // Copied functional simulator code. // Added system module that instantiates cpu and memory. // Added new ports. // /// Day 2: 1 May 2002 // // Removed old mem code. // Added states for instruction fetch, decode, and execute. // Was working during class, but by the end of class was in a // non-working state. // /// Day 3: 3 May 2002 // // Got states working. // Re-wrote ID to take advantage of separate ALU for arithmetic and log. inst. // Re-wrote ID to take advantage of separate ALU for branches. // /// Day 4: 6 May 2002 // // Added load instruction. // Started store instruction. // /// Day 5: 8 May 2002 // // Got lb working. // Finished store instruction. // This file does not include changes to overlap IF and ID. `define MIPS_PROG "tthird.v" module cpu(exc,data_out,addr,size,we,data_in,mem_error_in,reset,clk); input [31:0] data_in; input [2:0] mem_error_in; input reset,clk; output [7:0] exc; output [31:0] data_out, addr; output [1:0] size; output we; wire [31:0] data_out; reg [31:0] addr; reg [1:0] size; reg we; reg [7:0] exc; reg [31:0] pc, npc, nnpc; reg [31:0] ir; wire [5:0] opcode, func; wire [4:0] rs, rt, rd, sa; wire [15:0] immed; wire [25:0] ii; reg [31:0] gpr [0:31]; wire [31:0] simmed, uimmed; reg [7:0] temp; reg [2:0] state; reg [4:0] dst; reg [74:0] bndl; wire [31:0]limmed; reg [31:0] bimmed; reg [31:0] rs_val, rt_val, sa_val; 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; // Control Signal Value Names parameter OP_nop = 6'd0; parameter OP_sll = 6'd1; parameter OP_srl = 6'd2; parameter OP_add = 6'd3; parameter OP_sub = 6'd4; parameter OP_or = 6'd5; parameter OP_and = 6'd6; parameter OP_slt = 6'd7; parameter OP_seq = 6'd8; parameter OP_sne = 6'd9; parameter ST_if = 1; // Instruction Fetch parameter ST_id = 2; // Instruction Decode parameter ST_ex = 3; // Executing Arithmetic or Logical Instruction parameter ST_eb = 4; // Executing Branch (Computing condition.) parameter ST_ea = 5; // Executing Memory (Computing address.) parameter ST_me = 6; // Performing load or store. wire [31:0] alu_out; reg [31:0] alu_a, alu_b; reg [5:0] alu_op; alu our_alu(alu_out, alu_a, alu_b, alu_op); reg [1:0] me_size; reg me_we, me_se; assign data_out = rt_val; always @( state or pc or alu_out ) case( state ) ST_if: begin addr = pc; size = 3; we = 0; end ST_me: begin addr = alu_out; size = me_size; we = me_we; end default: begin size = 0; addr = pc; we = 0; end endcase assign immed = ir[15:0]; assign {opcode, rs, rt, rd, sa, func} = ir; assign ii = ir[25:0]; assign simmed = {immed[15] ? 16'hffff : 16'h0, immed}; assign uimmed = { 16'h0, immed }; assign limmed = { immed, 16'h0 }; always @( posedge clk ) if( reset ) begin state = ST_if; pc = 'h400000; npc = pc + 4; exc = 0; end else case( state ) /// IF: Instruction Fetch ST_if: begin ir = data_in; state = ST_id; end /// Instruction Decode ST_id: begin nnpc = npc + 4; // Reassigned below. rs_val = gpr[rs]; rt_val = gpr[rt]; sa_val = { 27'd0, sa }; bndl = 75'bx; case( opcode ) O_tyr: case( func ) F_add: bndl = {rd, rs_val, OP_add, rt_val }; F_sub: bndl = {rd, rs_val, OP_sub, rt_val }; F_sll: bndl = {rd, sa_val, OP_sll, rt_val }; F_jr: nnpc = rs_val; default: exc = 1; endcase O_addi: bndl = {rt, rs_val, OP_add, simmed }; O_andi: bndl = {rt, rs_val, OP_and, uimmed }; O_ori: bndl = {rt, rs_val, OP_or, uimmed }; O_lui: bndl = {rt, rs_val, OP_or, limmed }; O_bne: bndl = {5'd0, rs_val, OP_sne, rt_val }; O_beq: bndl = {5'd0, rs_val, OP_seq, rt_val }; O_j: nnpc = {npc[31:28],ii,2'd0}; O_jal: begin gpr[31] = nnpc; nnpc = {npc[31:28],ii,2'd0}; end O_lb,O_lbu: bndl = {rt, rs_val, OP_add, simmed }; O_sb: bndl = {5'd0, rs_val, OP_add, simmed }; // O_lbu: gpr[rt] = {24'b0, mem[`A(gpr[rs]+simmed)]}; // O_sb: mem[`A(gpr[rs]+simmed)]= gpr[rt]; default: exc = 1; endcase if( bndl !== 75'bx ) {dst, alu_a, alu_op, alu_b } = bndl; case( opcode ) O_lb: begin me_size = 1; me_se = 1; me_we = 0; end O_lbu: begin me_size = 1; me_se = 0; me_we = 0; end O_sb: begin me_size = 1; me_se = 0; me_we = 1; end default: begin me_size = 0; me_se = 0; me_we = 0; end endcase case( opcode ) O_beq,O_bne: state = ST_eb; O_sb,O_lb,O_lbu: state = ST_ea; O_j: state = ST_if; default: state = bndl === 75'bx ? ST_if : ST_ex; endcase bimmed = npc + ( simmed << 2 ); pc = npc; npc = nnpc; end /// EX: Execute ST_ex: begin if( dst ) gpr[dst] = alu_out; state = ST_if; end /// EXB: Execute Branch ST_eb: begin if( alu_out[0] ) npc = bimmed; state = ST_if; end /// EA: Effective Address ST_ea: begin state = ST_me; end /// ME: Memory ST_me: begin if( dst != 0 ) case( size ) 1: gpr[dst] = { me_se & data_in[7] ? 24'hffffff : 24'h0, data_in[7:0] }; 2: gpr[dst] = { me_se & data_in[15] ? 16'hffff : 16'h0, data_in[15:0] }; endcase state = ST_if; end endcase endmodule module alu(alu_out, alu_a, alu_b, alu_op); output [31:0] alu_out; input [31:0] alu_a, alu_b; input [5:0] alu_op; reg [31:0] alu_out; // Control Signal Value Names parameter OP_nop = 6'd0; parameter OP_sll = 6'd1; parameter OP_srl = 6'd2; parameter OP_add = 6'd3; parameter OP_sub = 6'd4; parameter OP_or = 6'd5; parameter OP_and = 6'd6; parameter OP_slt = 6'd7; parameter OP_seq = 6'd8; parameter OP_sne = 6'd9; always @( alu_a or alu_b or alu_op ) case( alu_op ) OP_add : alu_out = alu_a + alu_b; OP_and : alu_out = alu_a & alu_b; OP_or : alu_out = alu_a | alu_b; OP_sub : alu_out = alu_a - alu_b; OP_slt : alu_out = {alu_a[31],alu_a} < {alu_b[31],alu_b}; OP_sll : alu_out = alu_b << alu_a; OP_srl : alu_out = alu_b >> alu_a; OP_seq : alu_out = alu_a == alu_b; OP_sne : alu_out = alu_a != alu_b; OP_nop : alu_out = 0; default : begin alu_out = 0; $stop; end endcase endmodule module system(exc,reset,clk); input reset, clk; output [7:0] exc; wire [31:0] cpu_data_out, addr, mem_data_out; wire [2:0] mem_err_out; wire [1:0] size; wire we; cpu cpu1(exc,cpu_data_out,addr,size,we,mem_data_out,mem_err_out,reset,clk); mips_memory_1p m1(mem_data_out,mem_err_out,addr,size,we,cpu_data_out,clk); endmodule `include "mips_hc_tb.v"