183 lines
5.7 KiB
Verilog
183 lines
5.7 KiB
Verilog
//-----------------------------------------------------------------
|
|
// 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
|