aboutsummaryrefslogtreecommitdiff
path: root/rtl/alu.sv
blob: f5dde1932deb8b88c53a70d90314989050ac8f56 (plain) (blame)
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
module alu
  import montreal_pkg::*;
#(
  parameter int unsigned XLEN        = config_pkg::XLEN,
  parameter int unsigned SLICE_WIDTH = config_pkg::SLICE_WIDTH,

  localparam int unsigned SLICE_ADDR_WIDTH = $clog2(XLEN / SLICE_WIDTH)
) (
  input logic   clk_i,
  input logic   rst_ni,
  input fu_op_t alu_op_i,

  input logic [SLICE_ADDR_WIDTH-1:0] count_i,

  input slice_t a_i,
  input slice_t b_i,

  output slice_t result_o,
  output logic   carry_o
);

  logic negate_b;

  /* We used Karnaugh maps here. If the encoding for fu_op_t changes, this has to be updated. */
  assign negate_b = alu_op_i[3] || (!alu_op_i[2] && alu_op_i[1]);

  /* Adder width is SLICE_WIDTH + 1 to account for carry-out. */
  logic [SLICE_WIDTH:0] adder_a, adder_b, adder_result;

  assign adder_a = {1'b0, a_i};
  assign adder_b = {1'b0, (b_i ^ {SLICE_WIDTH{negate_b}})};

  /* Carry signals. */
  logic carry, carry_d, carry_q;

  assign carry = (count_i == '0) ? negate_b : carry_q;

  /* Combinational arithmetic/logic core. */
  always_comb begin : alu_core
    unique casez (alu_op_i[2:0])
      /* ADD, SUB, SLT, SLTU. */
      3'b0??: begin end
      /* XOR. */
      3'b100: begin end
      /* OR. */
      3'b110: begin end
      /* AND. */
      3'b111: begin end
      default: begin end
    endcase
  end : alu_core

  always_ff @(posedge clk_i) begin : carry_ff
    if (!rst_ni) begin
      carry_q <= '0;
    end else begin
      carry_q <= carry_d;
    end
  end : carry_ff

endmodule : alu