summaryrefslogtreecommitdiff
path: root/shifter.v
blob: 4d7b6b6e74f9ea23de1a6a5e3d0d510008409c11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
module shifter (
	input [15:0] v,      // number to shift
	input [15:0] by,     // bits to shift by
	input dir,           // 0 = left shift, 1 = right shift
	input [1:0] extend,  // 0 = zero extend, 1 = one extend, 2 = sign extend (or last bit), 3 = barrel shift
	output [15:0] result
);

	wire [31:0] x;

	assign x = {
		v,

		extend == 2'b00 ? 16'h0 :
		extend == 2'b01 ? 16'hFFFF :
		extend == 2'b10 ? {16{v[dir == 1'b0 ? 0 : 15]}} : v
	};

	wire [15:0] barrelResult;
	wire [15:0] otherResult;

	wire [4:0] dirAndAmount;
	assign dirAndAmount = {dir, by[3:0]};

	assign barrelResult =
		|(by[15:4]) ? x[15:0] :
		dirAndAmount == 5'h1F ? {x[14:0], x[31   ]} :
		dirAndAmount == 5'h1E ? {x[13:0], x[31:30]} :
		dirAndAmount == 5'h1D ? {x[12:0], x[31:29]} :
		dirAndAmount == 5'h1C ? {x[11:0], x[31:28]} :
		dirAndAmount == 5'h1B ? {x[10:0], x[31:27]} :
		dirAndAmount == 5'h1A ? {x[ 9:0], x[31:26]} :
		dirAndAmount == 5'h19 ? {x[ 8:0], x[31:25]} :
		dirAndAmount == 5'h18 ? {x[ 7:0], x[31:24]} :
		dirAndAmount == 5'h17 ? {x[ 6:0], x[31:23]} :
		dirAndAmount == 5'h16 ? {x[ 5:0], x[31:22]} :
		dirAndAmount == 5'h15 ? {x[ 4:0], x[31:21]} :
		dirAndAmount == 5'h14 ? {x[ 3:0], x[31:20]} :
		dirAndAmount == 5'h13 ? {x[ 2:0], x[31:19]} :
		dirAndAmount == 5'h12 ? {x[ 1:0], x[31:18]} :
		dirAndAmount == 5'h11 ? {x[   0], x[31:17]} :
		// zero shift is handled at the bottom
		dirAndAmount == 5'h01 ? x[30:15] :
		dirAndAmount == 5'h02 ? x[29:14] :
		dirAndAmount == 5'h03 ? x[28:13] :
		dirAndAmount == 5'h04 ? x[27:12] :
		dirAndAmount == 5'h05 ? x[26:11] :
		dirAndAmount == 5'h06 ? x[25:10] :
		dirAndAmount == 5'h07 ? x[24: 9] :
		dirAndAmount == 5'h08 ? x[23: 8] :
		dirAndAmount == 5'h09 ? x[22: 7] :
		dirAndAmount == 5'h0A ? x[21: 6] :
		dirAndAmount == 5'h0B ? x[20: 5] :
		dirAndAmount == 5'h0C ? x[19: 4] :
		dirAndAmount == 5'h0D ? x[18: 3] :
		dirAndAmount == 5'h0E ? x[17: 2] :
		dirAndAmount == 5'h0F ? x[16: 1] :
		x[31:16];

	assign otherResult =
		|(by[15:4]) ? x[15:0] : barrelResult;

	assign result = extend == 2'b11 ? barrelResult : otherResult;
endmodule