summaryrefslogtreecommitdiff
path: root/rtl/core/core_shifter.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-01-21 06:23:46 -0600
committerAlejandro Soto <alejandro@34project.org>2024-02-20 11:11:17 -0600
commitf3b18ead59ae02f95dabbf0a1dea40873a816975 (patch)
tree8979e50f2a37f66a4cd27e937b480efe60d72cf7 /rtl/core/core_shifter.sv
parenta8bc5a353ea997f73209b39377ee15a73e471237 (diff)
rtl: refactor filenames and directory hierarchy
Diffstat (limited to 'rtl/core/core_shifter.sv')
-rw-r--r--rtl/core/core_shifter.sv42
1 files changed, 42 insertions, 0 deletions
diff --git a/rtl/core/core_shifter.sv b/rtl/core/core_shifter.sv
new file mode 100644
index 0000000..96b8866
--- /dev/null
+++ b/rtl/core/core_shifter.sv
@@ -0,0 +1,42 @@
+`include "core/uarch.sv"
+
+module core_shifter
+#(parameter W=16)
+(
+ input shifter_control ctrl,
+ input logic[W - 1:0] base,
+ input logic[7:0] shift,
+ input logic c_in,
+
+ output logic[W - 1:0] q,
+ output logic c
+);
+
+ localparam LOG = $clog2(W);
+
+ logic[W - 1:0] q_no_c, q_shl, q_shr, q_ror;
+ logic[W:0] sign_mask;
+ logic c_shl, c_shr, c_ror;
+
+ assign sign_mask = {(W + 1){ctrl.sign_extend & base[W - 1]}};
+ assign {c_shl, q_shl} = {c_in, base} << shift;
+ assign {q_shr, c_shr} = {base, c_in} >> shift | (sign_mask & ~(sign_mask >> shift));
+
+ logic ror_cycle;
+ logic[LOG - 1:0] ror_shift;
+ logic[2 * W:0] ror_out;
+
+ assign ror_shift = shift[LOG - 1:0];
+ assign ror_cycle = |shift[7:LOG] & ~|ror_shift;
+ assign ror_out = {base, base, c_in} >> {ror_cycle, ror_shift};
+ assign {q_ror, c_ror} = ror_out[W:0];
+
+ always_comb
+ if(ctrl.ror)
+ {c, q} = {c_ror, q_ror};
+ else if(ctrl.shr)
+ {c, q} = {c_shr, q_shr[W - 1] | (ctrl.put_carry && c_in && shift != 0), q_shr[W - 2:0]};
+ else
+ {c, q} = {c_shl, q_shl};
+
+endmodule