//////////////////////////////////////////////////////////////////////////////// /// /// LSU EE 3755 -- Fall 2012 /// /// Homework 6 /// Name: /// Instructions: // // Copy this to a file named hw06.v to directory ~/hw06 in your // class account. (~ is your home directory.) Use this // file for your solution. Your entire solution should be in // this file. // // Do not rename the modules in this file and be sure to use the // directory and filename given above. // // Modify the same cpu module for Problems 1 and 2. // Assignment: http://www.ece.lsu.edu/ee3755/2012f/hw06.pdf //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// Problems 1 and 2 /// General Instructions // // For clickable links visit an html version of this file: // http://www.ece.lsu.edu/ee3755/2012f/hw06.v.html // // Put the solutions to Problems 1 and 2 in the cpu module below. // Don't duplicate or rename it. // // The testbench for both problems is "test_proc". // // It should issue PASS and FAIL messages for each problem, // and finish by displaying "End of testbench run." // // By default it runs test program: // Web: http://www.ece.lsu.edu/ee3755/2012f/hw06-bm.s.html // Local: /home/faculty/koppel/pub/ee3755/s/2012_Fall/hw06/hw06-bm.s // // To use a different test program put its name in the macro below // (end it with a .v even though the assembler code is in a file // with a .s extension) and "assemble" the program by pressing // [S-f9] while in an Emacs buffer containing the program. // `define MIPS_PROG "/home/faculty/koppel/pub/ee3755/s/2012_Fall/hw06/hw06-bm.v" // // The testbench will not pass Problem 1 unless the test program // above is used. // // Additional states (st_if, st_id, etc.) can be added but st_id must // be used for decode and its value must remain 2. // // Solutions must be reasonably efficient, fast, and synthesizable. // // Do not use delays or do anything on the negative edge of the clock. // // See: http://www.ece.lsu.edu/ee4720/mips32v2.pdf for instruction info. /// Modify The Module Below // 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; reg [31:0] data_out, addr; reg [1:0] size; reg we; reg [7:0] exc; // MIPS Registers // reg [31:0] gpr [0:31]; reg [31:0] pc, npc; reg [31:0] ir; // Instruction Fields // reg [4:0] rs, rt, rd, sa; reg [5:0] opcode, func; reg [25:0] ii; reg [15:0] immed; // Values Derived From Immediates and Read From Register File // reg [31:0] simmed, uimmed, limmed; reg [31:0] rs_val, rt_val, sa_val; reg [75:0] bndl; // ALU Connections // wire [31:0] alu_out; reg [31:0] alu_a, alu_b; reg [5:0] alu_op; // Processor Control Logic State // reg [2:0] state; reg [4:0] wb_rd; // Register number to write. reg me_we; // we value to use in state st_me reg [1:0] me_size; // size value to use in state st_me alu our_alu(alu_out, alu_a, alu_b, alu_op); // Values for the MIPS 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 the MIPS opcode field. // parameter O_rfmt = 6'h0; 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; // Processor Control Logic States // parameter ST_if = 1; parameter ST_id = 2; parameter ST_ex = 3; parameter ST_ex_addr = 5; parameter ST_ex_cond = 6; parameter ST_ex_targ = 7; parameter ST_me = 4; // ALU Operations // 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; // Handy Constant // parameter R0 = 5'd0; /// Set Memory Connection Values: addr, we, and size. // always @( state or pc or alu_out or me_size or me_we ) case ( state ) ST_if : begin addr = pc; we = 0; size = 3; end ST_me : begin addr = alu_out; we = me_we; size = me_size; end default : begin addr = pc; we = 0; size = 0; end // Note: addr is set for default case to simplify synthesized hardware. endcase always @( posedge clk ) if ( reset ) begin state = ST_if; exc = 0; pc = 32'h400000; npc = pc + 4; end else case ( state ) /// Instruction Fetch ST_if: begin ir = data_in; state = ST_id; end /// Instruction Decode (and Register Read) ST_id: begin {opcode,rs,rt,rd,sa,func} = ir; ii = ir[25:0]; immed = ir[15:0]; simmed = { immed[15] ? 16'hffff : 16'h0, immed }; uimmed = { 16'h0, immed }; limmed = { immed, 16'h0 }; rs_val = gpr[rs]; rt_val = gpr[rt]; sa_val = {26'd0,sa}; // Set alu_a, alu_b, alu_op, and wb_rd. // case ( opcode ) O_rfmt: // R-Format Instructions 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}; default: begin bndl = {rd, sa_val, OP_sll, rt_val}; exc = 1; end endcase // I- and J-Format Instructions O_lbu: bndl = {rt, rs_val, OP_add, simmed }; O_sb: bndl = {R0, rs_val, OP_add, simmed }; O_lui: bndl = {rt, rs_val, OP_or, limmed }; 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_slti: bndl = {rt, rs_val, OP_slt, simmed }; O_j: bndl = {R0, rs_val, OP_nop, simmed }; O_bne, O_beq: bndl = {R0, rs_val, OP_seq, rt_val }; default: begin bndl = {R0, rs_val, OP_seq, rt_val }; exc = 1; end endcase { wb_rd, alu_a, alu_op, alu_b } = bndl; // Needed for a store instruction, doesn't hurt others. data_out = rt_val; // Set me_size and me_wb // case ( opcode ) O_lbu : begin me_size = 1; me_we = 0; end O_sb : begin me_size = 1; me_we = 1; end default : begin me_size = 0; me_we = 0; end endcase pc = npc; // Set npc, branch instruction may change npc. // case ( opcode ) O_j : npc = { pc[31:28], ii, 2'b0 }; default : npc = pc + 4; endcase case ( opcode ) O_lbu, O_sb : state = ST_ex_addr; O_bne, O_beq : state = ST_ex_cond; O_j : state = ST_if; default : state = ST_ex; endcase end /// Execute -- ALU instructions ST_ex: begin if ( wb_rd ) gpr[wb_rd] = alu_out; state = ST_if; end /// Execute -- Compute Effective Address for Loads and Stores ST_ex_addr: begin state = ST_me; end /// Execute -- Compute Branch Condition ST_ex_cond: begin if ( opcode == O_beq && alu_out || opcode == O_bne && !alu_out ) begin alu_a = pc; alu_b = simmed << 2; alu_op = OP_add; state = ST_ex_targ; end else begin state = ST_if; end end /// Execute -- Compute Branch Target ST_ex_targ: begin npc = alu_out; state = ST_if; end /// Memory ST_me: begin if ( wb_rd ) gpr[wb_rd] = data_in; state = ST_if; end default: begin $display("Unexpected state."); $stop; 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 = 0; parameter OP_sll = 1; parameter OP_srl = 2; parameter OP_add = 3; parameter OP_sub = 4; parameter OP_or = 5; parameter OP_and = 6; parameter OP_slt = 7; parameter OP_seq = 8; 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_nop : alu_out = 0; default : begin alu_out = 0; $stop; end endcase endmodule // cadence translate_off 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 // cadence translate_on `include "/home/faculty/koppel/pub/ee3755/s/2012_Fall/hw06/mips_hc_tb.v"