diff options
Diffstat (limited to 'shifter.v')
-rw-r--r-- | shifter.v | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/shifter.v b/shifter.v new file mode 100644 index 0000000..46360fe --- /dev/null +++ b/shifter.v @@ -0,0 +1,68 @@ +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 [47:0] x; + + assign x = { + extend == 2'b00 ? 16'h0 : + extend == 2'b01 ? 16'hFFFF : + extend == 2'b10 ? {16{v[15]}} : v, + + v, + + extend == 2'b00 ? 16'h0 : + extend == 2'b01 ? 16'hFFFF : + extend == 2'b10 ? {16{v[0]}} : v + }; + + wire [15:0] barrelResult; + wire [15:0] otherResult; + + wire [4:0] dirAndAmount; + assign dirAndAmount = {dir, by[3:0]}; + + assign barrelResult = + |(by[15:4]) ? (dir == 1'b1 ? x[47:32] : x[15:0]) : + dirAndAmount == 5'h1F ? x[46:31] : + dirAndAmount == 5'h1E ? x[45:30] : + dirAndAmount == 5'h1D ? x[44:29] : + dirAndAmount == 5'h1C ? x[43:28] : + dirAndAmount == 5'h1B ? x[42:27] : + dirAndAmount == 5'h1A ? x[41:26] : + dirAndAmount == 5'h19 ? x[40:25] : + dirAndAmount == 5'h18 ? x[39:24] : + dirAndAmount == 5'h17 ? x[38:23] : + dirAndAmount == 5'h16 ? x[37:22] : + dirAndAmount == 5'h15 ? x[36:21] : + dirAndAmount == 5'h14 ? x[35:20] : + dirAndAmount == 5'h13 ? x[34:19] : + dirAndAmount == 5'h12 ? x[33:18] : + dirAndAmount == 5'h11 ? x[32: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]) ? (dir == 1'b1 ? x[47:32] : x[15:0]) : barrelResult; + + assign result = extend == 2'b11 ? barrelResult : otherResult; +endmodule |