ALU.v 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /*
  2. * ALU
  3. */
  4. module ALU(
  5. input clk,
  6. input [31:0] ax, bx,
  7. input [3:0] opcode,
  8. output reg [31:0] y
  9. );
  10. reg [31:0] a, b;
  11. // Opcodes
  12. localparam
  13. OP_OR = 4'b0000, // OR
  14. OP_AND = 4'b0001, // AND
  15. OP_XOR = 4'b0010, // XOR
  16. OP_ADD = 4'b0011, // Add
  17. OP_SUB = 4'b0100, // Substract
  18. OP_SHIFTL = 4'b0101, // Shift left
  19. OP_SHIFTR = 4'b0110, // Shift right
  20. OP_NOTA = 4'b0111, // ~A
  21. OP_MULTS = 4'b1000, // Multiplication signed
  22. OP_MULTU = 4'b1001, // Multiplication unsigned
  23. OP_SLT = 4'b1010, // Set on less than signed
  24. OP_SLTU = 4'b1011, // Set on less than unsigned
  25. OP_LOAD = 4'b1100, // Load input B ( y := b )
  26. OP_LOADHI = 4'b1101, // Loadhi input B ( y := {(b<<16), a} )
  27. OP_SHIFTRS = 4'b1110, // Shift right with sign extesion
  28. OP_FPMULTS = 4'b1111; // Fixed point (16.16) signed multiplication
  29. reg signed [63:0] ab; // result for FPMULTS
  30. reg [3:0] opcode_reg;
  31. always @(posedge clk)
  32. begin
  33. opcode_reg <= opcode;
  34. a <= ax;
  35. b <= bx;
  36. end
  37. wire [31:0] multu_out;
  38. wire signed [63:0] mults_out;
  39. assign multu_out = a + b;
  40. assign mults_out = a - b;
  41. always @ (*)
  42. begin
  43. case (opcode)
  44. OP_OR: y = a | b;
  45. OP_AND: y = a & b;
  46. OP_XOR: y = a ^ b;
  47. OP_ADD: y = a + b;
  48. OP_SUB: y = a - b;
  49. OP_SHIFTL: y = a << b;
  50. OP_SHIFTR: y = a >> b;
  51. OP_NOTA: y = ~a;
  52. OP_MULTS: y = mults_out;
  53. OP_MULTU: y = multu_out;
  54. OP_SLT: y = {{31{1'b0}}, ($signed(a) < $signed(b))};
  55. OP_SLTU: y = {{31{1'b0}}, (a < b)};
  56. OP_LOAD: y = b;
  57. OP_LOADHI: y = {b[15:0], a[15:0]};
  58. OP_SHIFTRS: y = $signed(a) >>> b;
  59. OP_FPMULTS:
  60. begin
  61. y = mults_out[47:16];
  62. end
  63. endcase
  64. end
  65. endmodule