2021-05-21 09:34:16 +08:00
|
|
|
/**********************************************************************
|
|
|
|
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
|
|
|
|
* Version 3, April 2008 *
|
|
|
|
* *
|
|
|
|
* Copyright (C) 2018 Luke Wren *
|
|
|
|
* *
|
|
|
|
* Everyone is permitted to copy and distribute verbatim or modified *
|
|
|
|
* copies of this license document and accompanying software, and *
|
|
|
|
* changing either is allowed. *
|
|
|
|
* *
|
|
|
|
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
|
|
|
|
* *
|
|
|
|
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
|
|
|
|
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
|
|
|
|
* *
|
|
|
|
*********************************************************************/
|
|
|
|
|
|
|
|
// Implement the three shifts (left logical, right logical, right arithmetic)
|
|
|
|
// using a single log-type barrel shifter. Around 240 LUTs for 32 bits.
|
|
|
|
// (7 layers of 32 2-input muxes, some extra LUTs and LUT inputs used for arith)
|
|
|
|
|
2021-11-24 06:10:39 +08:00
|
|
|
`default_nettype none
|
|
|
|
|
2021-05-21 10:46:29 +08:00
|
|
|
module hazard3_shift_barrel #(
|
2021-11-26 06:58:49 +08:00
|
|
|
`include "hazard3_config.vh"
|
|
|
|
,
|
|
|
|
`include "hazard3_width_const.vh"
|
2021-05-21 09:34:16 +08:00
|
|
|
) (
|
|
|
|
input wire [W_DATA-1:0] din,
|
|
|
|
input wire [W_SHAMT-1:0] shamt,
|
|
|
|
input wire right_nleft,
|
2021-11-26 06:58:49 +08:00
|
|
|
input wire rotate,
|
2021-05-21 09:34:16 +08:00
|
|
|
input wire arith,
|
|
|
|
output reg [W_DATA-1:0] dout
|
|
|
|
);
|
|
|
|
|
|
|
|
reg [W_DATA-1:0] din_rev;
|
|
|
|
reg [W_DATA-1:0] shift_accum;
|
2021-11-26 09:29:47 +08:00
|
|
|
reg sext; // haha
|
2021-05-21 09:34:16 +08:00
|
|
|
|
2021-11-26 06:58:49 +08:00
|
|
|
always @ (*) begin: shift
|
|
|
|
integer i;
|
|
|
|
|
2021-05-21 09:34:16 +08:00
|
|
|
for (i = 0; i < W_DATA; i = i + 1)
|
|
|
|
din_rev[i] = right_nleft ? din[W_DATA - 1 - i] : din[i];
|
|
|
|
|
2021-11-26 09:29:47 +08:00
|
|
|
sext = arith && din_rev[0];
|
|
|
|
|
2021-05-21 09:34:16 +08:00
|
|
|
shift_accum = din_rev;
|
|
|
|
for (i = 0; i < W_SHAMT; i = i + 1) begin
|
|
|
|
if (shamt[i]) begin
|
|
|
|
shift_accum = (shift_accum << (1 << i)) |
|
2021-11-26 06:58:49 +08:00
|
|
|
({W_DATA{sext}} & ~({W_DATA{1'b1}} << (1 << i))) |
|
|
|
|
({W_DATA{rotate && |EXTENSION_ZBB}} & (shift_accum >> (W_DATA - (1 << i))));
|
2021-05-21 09:34:16 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
for (i = 0; i < W_DATA; i = i + 1)
|
|
|
|
dout[i] = right_nleft ? shift_accum[W_DATA - 1 - i] : shift_accum[i];
|
|
|
|
end
|
|
|
|
|
|
|
|
`ifdef FORMAL
|
|
|
|
always @ (*) begin
|
2021-12-07 02:12:23 +08:00
|
|
|
if (right_nleft && arith && !rotate) begin: asr
|
2021-05-21 09:34:16 +08:00
|
|
|
assert($signed(dout) == $signed(din) >>> $signed(shamt));
|
2021-12-07 02:12:23 +08:00
|
|
|
end else if (right_nleft && !arith && !rotate) begin
|
2021-05-21 09:34:16 +08:00
|
|
|
assert(dout == din >> shamt);
|
2021-12-07 02:12:23 +08:00
|
|
|
end else if (!right_nleft && !arith && !rotate) begin
|
2021-05-21 09:34:16 +08:00
|
|
|
assert(dout == din << shamt);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
`endif
|
|
|
|
|
|
|
|
endmodule
|
2021-11-24 06:10:39 +08:00
|
|
|
|
|
|
|
`default_nettype wire
|