-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathArithmetic_Predicates_Binary.v
100 lines (80 loc) · 3.35 KB
/
Arithmetic_Predicates_Binary.v
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//# Arithmetic Predicates (Binary)
// Given two integers, `A` and `B`, derives all the possible arithmetic
// predictates (equal, greater-than, less-than-equal, etc...) as both signed
// and unsigned comparisons.
// This code implements "*How the Computer Sets the Comparison Predicates*" in
// Section 2-12 of Henry S. Warren, Jr.'s [Hacker's
// Delight](./reading.html#Warren2013), which describes how to compute all the
// integer comparisons, based on the condition flags generated after
// a (2's-complement) subtraction `A-B`.
`default_nettype none
module Arithmetic_Predicates_Binary
#(
parameter WORD_WIDTH = 0
)
(
input wire [WORD_WIDTH-1:0] A,
input wire [WORD_WIDTH-1:0] B,
output reg A_eq_B,
output reg A_lt_B_unsigned,
output reg A_lte_B_unsigned,
output reg A_gt_B_unsigned,
output reg A_gte_B_unsigned,
output reg A_lt_B_signed,
output reg A_lte_B_signed,
output reg A_gt_B_signed,
output reg A_gte_B_signed
);
localparam ZERO = {WORD_WIDTH{1'b0}};
initial begin
A_eq_B = 1'b0;
A_lt_B_unsigned = 1'b0;
A_lte_B_unsigned = 1'b0;
A_gt_B_unsigned = 1'b0;
A_gte_B_unsigned = 1'b0;
A_lt_B_signed = 1'b0;
A_lte_B_signed = 1'b0;
A_gt_B_signed = 1'b0;
A_gte_B_signed = 1'b0;
end
// First, let's subtract B from A, and get the the carry-out and overflow bits.
wire [WORD_WIDTH-1:0] difference;
wire carry_out;
wire overflow_signed;
Adder_Subtractor_Binary
#(
.WORD_WIDTH (WORD_WIDTH)
)
subtraction
(
.add_sub (1'b1), // 0/1 -> A+B/A-B
.carry_in (1'b0),
.A (A),
.B (B),
.sum (difference),
.carry_out (carry_out),
// verilator lint_off PINCONNECTEMPTY
.carries (),
// verilator lint_on PINCONNECTEMPTY
.overflow (overflow_signed)
);
// We now have enough information to compute all the arithmetic predicates.
// Note that in 2's-complement subtraction, the meaning of the carry-out bit
// is reversed, and that special care must be taken for signed comparisons to
// distinguish the carry-out from an overflow. This code takes advantage of
// the sequential evaluation of blocking assignments in a Verilog procedural
// block to re-use and optimize the logic expressions.
reg negative = 1'b0;
always @(*) begin
negative = (difference[WORD_WIDTH-1] == 1'b1);
A_eq_B = (difference == ZERO);
A_lt_B_unsigned = (carry_out == 1'b0);
A_lte_B_unsigned = (A_lt_B_unsigned == 1'b1) || (A_eq_B == 1'b1);
A_gte_B_unsigned = (carry_out == 1'b1);
A_gt_B_unsigned = (A_gte_B_unsigned == 1'b1) && (A_eq_B == 1'b0);
A_lt_B_signed = (negative != overflow_signed);
A_lte_B_signed = (A_lt_B_signed == 1'b1) || (A_eq_B == 1'b1);
A_gte_B_signed = (negative == overflow_signed);
A_gt_B_signed = (A_gte_B_signed == 1'b1) && (A_eq_B == 1'b0);
end
endmodule