//----------------------------------------------------------------- // uRISC-V CPU // V0.5.0 // github.com/ultraembedded/core_uriscv // Copyright 2015-2021 // // admin@ultra-embedded.com // // License: Apache 2.0 //----------------------------------------------------------------- // Copyright 2015-2021 github.com/ultraembedded // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------- module uriscv_alu ( // ALU operation select input [3:0] op_i, // Operands input [31:0] a_i, input [31:0] b_i, // Result output [31:0] p_o ); //----------------------------------------------------------------- // Includes //----------------------------------------------------------------- `include "uriscv_defs.v" //----------------------------------------------------------------- // Registers //----------------------------------------------------------------- reg [31:0] result_r; reg [31:16] shift_right_fill_r; reg [31:0] shift_right_1_r; reg [31:0] shift_right_2_r; reg [31:0] shift_right_4_r; reg [31:0] shift_right_8_r; reg [31:0] shift_left_1_r; reg [31:0] shift_left_2_r; reg [31:0] shift_left_4_r; reg [31:0] shift_left_8_r; wire [31:0] sub_res_w = a_i - b_i; //----------------------------------------------------------------- // ALU //----------------------------------------------------------------- always @ * begin case (op_i) //---------------------------------------------- // Shift Left //---------------------------------------------- `RV_ALU_SHIFTL : begin if (b_i[0] == 1'b1) shift_left_1_r = {a_i[30:0],1'b0}; else shift_left_1_r = a_i; if (b_i[1] == 1'b1) shift_left_2_r = {shift_left_1_r[29:0],2'b00}; else shift_left_2_r = shift_left_1_r; if (b_i[2] == 1'b1) shift_left_4_r = {shift_left_2_r[27:0],4'b0000}; else shift_left_4_r = shift_left_2_r; if (b_i[3] == 1'b1) shift_left_8_r = {shift_left_4_r[23:0],8'b00000000}; else shift_left_8_r = shift_left_4_r; if (b_i[4] == 1'b1) result_r = {shift_left_8_r[15:0],16'b0000000000000000}; else result_r = shift_left_8_r; end //---------------------------------------------- // Shift Right //---------------------------------------------- `RV_ALU_SHIFTR, `RV_ALU_SHIFTR_ARITH: begin // Arithmetic shift? Fill with 1's if MSB set if (a_i[31] == 1'b1 && op_i == `RV_ALU_SHIFTR_ARITH) shift_right_fill_r = 16'b1111111111111111; else shift_right_fill_r = 16'b0000000000000000; if (b_i[0] == 1'b1) shift_right_1_r = {shift_right_fill_r[31], a_i[31:1]}; else shift_right_1_r = a_i; if (b_i[1] == 1'b1) shift_right_2_r = {shift_right_fill_r[31:30], shift_right_1_r[31:2]}; else shift_right_2_r = shift_right_1_r; if (b_i[2] == 1'b1) shift_right_4_r = {shift_right_fill_r[31:28], shift_right_2_r[31:4]}; else shift_right_4_r = shift_right_2_r; if (b_i[3] == 1'b1) shift_right_8_r = {shift_right_fill_r[31:24], shift_right_4_r[31:8]}; else shift_right_8_r = shift_right_4_r; if (b_i[4] == 1'b1) result_r = {shift_right_fill_r[31:16], shift_right_8_r[31:16]}; else result_r = shift_right_8_r; end //---------------------------------------------- // Arithmetic //---------------------------------------------- `RV_ALU_ADD : begin result_r = (a_i + b_i); end `RV_ALU_SUB : begin result_r = sub_res_w; end //---------------------------------------------- // Logical //---------------------------------------------- `RV_ALU_AND : begin result_r = (a_i & b_i); end `RV_ALU_OR : begin result_r = (a_i | b_i); end `RV_ALU_XOR : begin result_r = (a_i ^ b_i); end //---------------------------------------------- // Comparision //---------------------------------------------- `RV_ALU_LESS_THAN : begin result_r = (a_i < b_i) ? 32'h1 : 32'h0; end `RV_ALU_LESS_THAN_SIGNED : begin if (a_i[31] != b_i[31]) result_r = a_i[31] ? 32'h1 : 32'h0; else result_r = sub_res_w[31] ? 32'h1 : 32'h0; end default : begin result_r = a_i; end endcase end assign p_o = result_r; endmodule