summaryrefslogtreecommitdiff
path: root/rtl/core/core_alu_add.sv
blob: a15a6b62771aa13f914a160a19888978dc840f15 (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
module core_alu_add
#
(
	parameter W=16,
	parameter SUB=0
)
(
	input  logic[W - 1:0] a,
	                      b,
	input  logic          c_in,

	output logic[W - 1:0] q,
	output logic          c,
	                      v
);

	logic sgn_a, sgn_b, sgn_q, maybe_v;
	logic[W:0] out;

	/* Quartus infiere dos sumadores si se zero-extendea el cin
	 * para complacer a Verilator, lo cual es malo para Fmax.
	 */
`ifdef VERILATOR
	logic[W:0] ext_carry;
	assign ext_carry = {{W{1'b0}}, c_in};
`else
	logic ext_carry;
	assign ext_carry = c_in;
`endif

	assign v = maybe_v & (sgn_a ^ sgn_q);
	assign {c, q} = out;
	assign {sgn_a, sgn_b, sgn_q} = {a[W - 1], b[W - 1], q[W - 1]};

	generate
		if(SUB) begin
			assign out = {1'b1, a} - {1'b0, b} - ext_carry;
			assign maybe_v = sgn_a ^ sgn_b;
		end else begin
			assign out = {1'b0, a} + {1'b0, b} + ext_carry;
			assign maybe_v = sgn_a ~^ sgn_b;
		end
	endgenerate

endmodule