/* Copyright 2006 Suraj N. Kurapati This file is part of Ruby-VPI. Ruby-VPI is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Ruby-VPI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Ruby-VPI; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ `define WIDTH 32 `define DATABITS 7 `define OP_NOP 0 `define OP_ADD 1 `define OP_SUB 2 `define OP_MULT 3 module hw5_unit( input clk , input reset // inputs , input [`DATABITS-1:0] in_databits , input [`WIDTH-1:0] a , input [`WIDTH-1:0] b , input [1:0] in_op // outputs , output reg [`WIDTH-1:0] res , output reg [`DATABITS-1:0] out_databits , output reg [1:0] out_op ); /* PHASE 0: perform the ALU operations */ // operation ID reg [`DATABITS-1:0] in_databits_phase0; reg [1:0] in_op_phase0; always @(*) begin in_databits_phase0 = in_databits; in_op_phase0 = in_op; end // addition reg [`WIDTH-1:0] add_result_phase0; always @(*) begin add_result_phase0 = a + b; end // subtraction reg [`WIDTH-1:0] sub_result_phase0; always @(*) begin sub_result_phase0 = a - b; end // multiplication reg [`WIDTH-1:0] mul_result_phase0; always @(*) begin mul_result_phase0 = a * b; end // always @(posedge clk) begin // $display("in_databits_phase0 => %d", in_databits_phase0); // $display("in_op_phase0 => %d", in_op_phase0); // $display("add_result_phase0 => %d", add_result_phase0); // $display("sub_result_phase0 => %d", sub_result_phase0); // $display("mul_result_phase0 => %d", mul_result_phase0); // end /* PHASE 1: delay the ALU results */ reg [`DATABITS-1:0] in_databits_phase1; reg [1:0] in_op_phase1; reg [`WIDTH-1:0] add_result_phase1; reg [`WIDTH-1:0] sub_result_phase1; reg [`WIDTH-1:0] mul_result_phase1; always @(posedge clk) begin in_databits_phase1 <= in_databits_phase0; in_op_phase1 <= in_op_phase0; add_result_phase1 <= add_result_phase0; sub_result_phase1 <= sub_result_phase0; mul_result_phase1 <= mul_result_phase0; end // always @(posedge clk) begin // $display("in_databits_phase1 => %d", in_databits_phase1); // $display("in_op_phase1 => %d", in_op_phase1); // $display("add_result_phase1 => %d", add_result_phase1); // $display("sub_result_phase1 => %d", sub_result_phase1); // $display("mul_result_phase1 => %d", mul_result_phase1); // end /* PHASE 2: delay the ALU results */ reg [`DATABITS-1:0] in_databits_phase2; reg [1:0] in_op_phase2; reg [`WIDTH-1:0] add_result_phase2; reg [`WIDTH-1:0] sub_result_phase2; reg [`WIDTH-1:0] mul_result_phase2; always @(posedge clk) begin in_databits_phase2 <= in_databits_phase1; in_op_phase2 <= in_op_phase1; add_result_phase2 <= add_result_phase1; sub_result_phase2 <= sub_result_phase1; mul_result_phase2 <= mul_result_phase1; end // always @(posedge clk) begin // $display("in_databits_phase2 => %d", in_databits_phase2); // $display("in_op_phase2 => %d", in_op_phase2); // $display("add_result_phase2 => %d", add_result_phase2); // $display("sub_result_phase2 => %d", sub_result_phase2); // $display("mul_result_phase2 => %d", mul_result_phase2); // end /* PHASE 3: produce the outputs */ reg [`DATABITS-1:0] out_databits_next; reg [1:0] out_op_next; reg [`WIDTH-1:0] res_next; always @(*) begin if (reset) begin out_op_next = `OP_NOP; end else begin out_op_next = in_op_phase2; end out_databits_next = in_databits_phase2; case (in_op_phase2) `OP_NOP: res_next = 0; `OP_ADD: res_next = add_result_phase2; `OP_SUB: res_next = sub_result_phase2; `OP_MULT: res_next = mul_result_phase2; endcase end always @(posedge clk) begin res <= res_next; out_op <= out_op_next; out_databits <= out_databits_next; end endmodule