/// LSU EE 3755 -- Fall 2001 -- Computer Organization
//
/// Hardwired Control MIPS, As Seen in Class [tm]
//
// Time-stamp: <3 December 2001, 13:32:51 CST, koppel@sol>
//
// This file contains the Verilog code for the hardwired control MIPS
// implementation being written in class. It is probably not complete
// and might not be working, even considering its incomplete form.
// Completed code will also be posted.
//
// $Date: 2001/12/03 20:59:19 $
//
// $Log: mips3l.v,v $
// Revision 1.4 2001/12/03 20:59:19 koppel
// Completed combinational logic for setting memory inputs.
//
// Revision 1.3 2001/11/30 21:06:13 koppel
// Moved branch condition and target computation to ALU.
// Started on combinational logic code for setting memory inputs,
// this code currently incomplete and so it is ifdef'ed out.
//
// Revision 1.2 2001/11/30 16:14:02 koppel
// Completed separation of ALU, used for arithmetic & logic and for
// effective address computation. Not yet used for branches.
//
// Revision 1.1 2001/11/28 18:10:49 koppel
// Initial revision
//
//
// Hi-lock: (("st_[a-z_]+:" (0 (quote font-lock-note-face) t)))
`define MIPS_PROG "prog1.v"
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);
memory_3 m1(mem_data_out,mem_err_out,addr,size,we,cpu_data_out,clk);
endmodule
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;
reg [31:0] gpr [0:31];
reg [31:0] pc, npc, nnpc;
reg [31:0] ir;
reg [4:0] rs, rt, rd, sa;
reg [5:0] opcode, func;
integer i;
// 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_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;
// 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;
initial begin exc = 0; i = 0; end
reg [15:0] immed, highhalfofsignedimmed;
reg [31:0] simmed, uimmed;
reg [25:0] ii;
reg [2:0] state;
wire [31:0] alu_out;
reg [31:0] alu_a, alu_b;
reg [5:0] alu_op;
wire alu_zero;
alu our_alu(alu_zero, alu_out, alu_a, alu_b, alu_op);
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;
reg [31:0] rs_val, rt_val;
reg [4:0] wb_rd;
reg me_we;
reg [1:0] me_size;
reg ex_cond_take;
always @( state or pc or alu_out or me_we or me_size )
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 = alu_out; we =0; size = 0; end
endcase
always @( posedge clk )
if( reset ) begin
pc = 'h400000;
npc = pc + 4;
state = st_if;
end else
case ( state )
st_if:
begin
ir = data_in;
state = st_id;
end
st_id:
begin
{opcode,rs,rt,rd,sa,func} = ir;
immed = ir[15:0];
highhalfofsignedimmed = immed[15] ? 16'hffff : 16'h0;
simmed = { highhalfofsignedimmed, immed };
uimmed = { 16'h0, immed };
ii = ir[25:0];
nnpc = npc + 4;
rs_val = gpr[rs];
rt_val = gpr[rt];
case( opcode )
o_rfmt:
case ( func )
f_add:
begin
alu_a = rs_val;
alu_b = rt_val;
alu_op = op_add;
wb_rd = rd;
end
f_sub:
begin
alu_a = rs_val;
alu_b = rt_val;
alu_op = op_sub;
wb_rd = rd;
end
f_sll:
begin
alu_a = rt_val;
alu_b = sa;
alu_op = op_sll;
wb_rd = rd;
end
default: exc = 1;
endcase
o_lbu:
begin
alu_a = rs_val;
alu_b = simmed;
alu_op = op_add;
wb_rd = rt;
me_we = 0;
me_size = 1;
// addr = gpr[rs] + simmed; we = 0; size = 1;
end
o_sb: begin
alu_a = rs_val;
alu_b = simmed;
alu_op = op_add;
wb_rd = 0;
me_we = 1;
me_size = 1;
end
o_lui:
begin
alu_a = uimmed;
alu_b = 16;
alu_op = op_sll;
wb_rd = rt;
end
o_addi:
begin
alu_a = rs_val;
alu_b = simmed;
alu_op = op_add;
wb_rd = rt;
end
o_andi:
begin
alu_a = rs_val;
alu_b = uimmed;
alu_op = op_and;
wb_rd = rt;
end
o_bne:
begin
alu_a = rs_val;
alu_b = rt_val;
alu_op = op_sub;
wb_rd = 0;
ex_cond_take = 0;
end
o_beq:
begin
alu_a = rs_val;
alu_b = rt_val;
alu_op = op_sub;
wb_rd = 0;
ex_cond_take = 1;
end
o_j: nnpc = { pc[31:28], ii, 2'b0 };
default: exc = 1;
endcase
data_out = rt_val;
pc = npc;
npc = nnpc;
case( opcode )
o_bne, o_beq: state = st_ex_cond;
o_lbu, o_sb: state = st_ex_addr;
default: state = st_ex;
endcase
end
st_ex:
begin
if( wb_rd ) gpr[ wb_rd ] = alu_out;
state = st_if;
end
st_ex_addr:
begin
state = st_me;
end
st_ex_cond:
begin
if( ex_cond_take == alu_zero ) begin
// Taken
alu_a = pc;
alu_b = simmed << 2;
alu_op = op_add;
wb_rd = 0;
state = st_ex_targ;
end else begin
// Not Taken
state = st_if;
end
end
st_ex_targ:
begin
npc = alu_out;
state = st_if;
end
st_me:
begin
if( !we ) gpr[wb_rd] = data_in;
state = st_if;
end
default:
begin
$display("Unexpected state.");
$stop;
end
endcase
endmodule
module alu(zero,alu_out,alu_a,alu_b,alu_op);
output [31:0] alu_out;
output zero;
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;
assign zero = alu_out == 0;
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 < alu_b;
op_sll : alu_out = alu_a << alu_b;
op_srl : alu_out = alu_a >> alu_b;
op_nop : alu_out = 0;
default : begin alu_out = 0; $stop; end
endcase
endmodule
`include "mipsi3tb.v"