summaryrefslogtreecommitdiff
path: root/rtl/core/alu
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-09-26 09:26:35 -0600
committerAlejandro Soto <alejandro@34project.org>2022-09-26 09:26:35 -0600
commitaf2f49f863deaeb6dc905bbb15701b50bc139873 (patch)
treee86dfc675f18ce49b91f4034788d1aaea4cbf2d3 /rtl/core/alu
parent14d06f0bc047ad79830890807bfe6195ba3de8ff (diff)
Implement ALU shifter
Diffstat (limited to 'rtl/core/alu')
-rw-r--r--rtl/core/alu/alu.sv14
-rw-r--r--rtl/core/alu/shifter.sv33
2 files changed, 40 insertions, 7 deletions
diff --git a/rtl/core/alu/alu.sv b/rtl/core/alu/alu.sv
index 914b40e..f5a0487 100644
--- a/rtl/core/alu/alu.sv
+++ b/rtl/core/alu/alu.sv
@@ -5,7 +5,8 @@ module core_alu
(
input alu_control ctrl,
input logic[W - 1:0] a,
- b,
+ base,
+ input logic[7:0] shift,
input logic c_in,
output logic[W - 1:0] q,
@@ -14,12 +15,21 @@ module core_alu
);
logic c, v, swap, sub, and_not, c_shifter, c_add, v_add;
- logic[W - 1:0] swap_a, swap_b, neg_b, c_in_add, q_add, q_and, q_orr, q_xor;
+ logic[W - 1:0] b, swap_a, swap_b, neg_b, c_in_add, q_add, q_and, q_orr, q_xor;
assign swap_a = swap ? b : a;
assign swap_b = swap ? a : b;
assign neg_b = -swap_b;
+ core_alu_shifter #(.W(W)) shifter
+ (
+ .base(base),
+ .shift(shift),
+ .b(b),
+ .c(c_shifter),
+ .*
+ );
+
core_alu_add #(.W(W)) op_add
(
.a(swap_a),
diff --git a/rtl/core/alu/shifter.sv b/rtl/core/alu/shifter.sv
index 3effb2c..4385b41 100644
--- a/rtl/core/alu/shifter.sv
+++ b/rtl/core/alu/shifter.sv
@@ -1,12 +1,35 @@
-module alu_shl
+`include "core/uarch.sv"
+
+module core_alu_shifter
#(parameter W=16)
(
- input logic[W - 1:0] a,
- b,
- output logic[W - 1:0] q,
+ input alu_control ctrl,
+ input logic[W - 1:0] base,
+ input logic[7:0] shift,
+ input logic c_in,
+
+ output logic[W - 1:0] b,
output logic c
);
- assign {c, q} = {1'b0, a} << b;
+ logic [W - 1:0] b_no_c, b_shl, b_shr, b_ror;
+ logic [W:0] sign_mask;
+ logic c_shl, c_shr;
+
+ assign sign_mask = {(W + 1){ctrl.sign_extend & base[W - 1]}};
+ assign {c_shl, b_shl} = {c_in, base} << shift;
+ assign {b_shr, c_shr} = {base, c_in} >> shift | ~(sign_mask >> shift);
+ assign b_ror = b_shr | base << (W - shift);
+
+ assign b = {b_no_c[W - 1] | (ctrl.put_carry & c_in), b_no_c[W - 2:0]};
+ assign c = ctrl.shr | ctrl.ror ? c_shr : c_shl;
+
+ always_comb
+ if(ctrl.ror)
+ b = b_ror;
+ else if(ctrl.shr)
+ b = {b_shr[W - 1] | (ctrl.put_carry & c_in), b_shr[W - 2:0]};
+ else
+ b = b_shl;
endmodule