-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathposit16_adder.vhd
208 lines (175 loc) · 6.47 KB
/
posit16_adder.vhd
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
entity posit16_adder is
port (
x : in std_logic_vector(15 downto 0);
y : in std_logic_vector(15 downto 0);
r : out std_logic_vector(15 downto 0)
);
end posit16_adder;
architecture behaviour of posit16_adder is
component posit16_decoder is
port (
x : in std_logic_vector(15 downto 0);
sign : out std_logic;
regime : out signed(4 downto 0);
exp : out std_logic_vector(1 downto 0);
frac : out std_logic_vector(11 downto 0);
x_abs : out std_logic_vector(14 downto 0);
zero : out std_logic;
inf : out std_logic
);
end component;
component right_shifter_extender is
port (
-- Input vector
x : in std_logic_vector(11 downto 0);
-- Number of bits to shift
count : in std_logic_vector(3 downto 0);
-- Output vector right-shifted count bits which keeps sticky bits to the right
y : out std_logic_vector(14 downto 0)
);
end component;
component LZcountshift is
port (
-- Input vector
x : in std_logic_vector(13 downto 0);
-- Number of leading zeros
nlzeros : out unsigned(3 downto 0);
-- Output vector left-shifted nlzeros bits
y : out std_logic_vector(13 downto 0)
);
end component;
component posit16_encoder is
port (
sign : in std_logic;
sf : in std_logic_vector(7 downto 0);
frac : in std_logic_vector(14 downto 0);
inf : in std_logic;
x : out std_logic_vector(15 downto 0)
);
end component;
signal sign_x : std_logic;
signal sign_y : std_logic;
signal sign_l : std_logic;
signal sign_r : std_logic;
signal regime_x : signed(4 downto 0);
signal regime_y : signed(4 downto 0);
signal exp_x : std_logic_vector(1 downto 0);
signal exp_y : std_logic_vector(1 downto 0);
signal frac_x : std_logic_vector(11 downto 0);
signal frac_y : std_logic_vector(11 downto 0);
signal frac_l : std_logic_vector(11 downto 0);
signal frac_s : std_logic_vector(11 downto 0);
signal frac_s_shift : std_logic_vector(14 downto 0);
signal frac_add : std_logic_vector(15 downto 0);
signal frac_r : std_logic_vector(14 downto 0);
signal frac_r_shift : std_logic_vector(13 downto 0);
signal frac_r_shift_sticky : std_logic_vector(14 downto 0);
signal frac_tmp : std_logic_vector(15 downto 0);
signal abs_x : std_logic_vector(14 downto 0);
signal abs_y : std_logic_vector(14 downto 0);
signal inf_x : std_logic;
signal inf_y : std_logic;
signal inf_r : std_logic;
signal sf_x : std_logic_vector(6 downto 0);
signal sf_y : std_logic_vector(6 downto 0);
signal sf_l : std_logic_vector(6 downto 0);
signal sf_s : std_logic_vector(6 downto 0);
signal sf_r : std_logic_vector(7 downto 0);
signal offset_tmp : unsigned(6 downto 0);
signal offset : std_logic_vector(3 downto 0);
signal ovf_r : std_logic_vector(0 downto 0);
signal nzeros : unsigned(3 downto 0);
signal ovf_tmp : std_logic_vector (7 downto 0);
signal nzeros_tmp : std_logic_vector (7 downto 0);
begin
inst_decoder_x : posit16_decoder
port map(
x => x,
sign => sign_x,
regime => regime_x,
exp => exp_x,
frac => frac_x,
x_abs => abs_x,
zero => open,
inf => inf_x
);
inst_decoder_y : posit16_decoder
port map(
x => y,
sign => sign_y,
regime => regime_y,
exp => exp_y,
frac => frac_y,
x_abs => abs_y,
zero => open,
inf => inf_y
);
-- Define the scaling factor
sf_x <= std_logic_vector(regime_x) & exp_x;
sf_y <= std_logic_vector(regime_y) & exp_y;
-- Check the larger and smaller input
process (abs_x, abs_y, sign_x, sign_y, sf_x, sf_y, frac_x, frac_y)
begin
if abs_x > abs_y then
sign_l <= sign_x;
sf_l <= sf_x;
frac_l <= frac_x;
sf_s <= sf_y;
frac_s <= frac_y;
else
sign_l <= sign_y;
sf_l <= sf_y;
frac_l <= frac_y;
sf_s <= sf_x;
frac_s <= frac_x;
end if;
end process;
-- Align the significands
offset_tmp <= unsigned(signed(sf_l) - signed(sf_s));
offset <= std_logic_vector(offset_tmp(3 downto 0)) when offset_tmp < 16 else
(others => '1'); -- The offset of the right shifter must be at most 15
inst_rshifter : right_shifter_extender
port map (
x => frac_s,
count => offset,
y => frac_s_shift
);
-- Add the fractions
frac_tmp <= std_logic_vector(unsigned(not('0' & frac_s_shift)) + 1) when (sign_x xor sign_y) = '1' else
'0' & frac_s_shift;
frac_add <= std_logic_vector(unsigned('0' & frac_l & "000") + unsigned(frac_tmp));
-- Check for overflow when adding
ovf_r <= frac_add(15 downto 15);
frac_r <= frac_add(15 downto 2) & (frac_add(1) or frac_add(0)) when ovf_r = "1" else
frac_add(14 downto 0);
-- Normalize the fraction without the sticky bit
inst_LZcountshift : LZcountshift
port map (
x => frac_r(14 downto 1),
nlzeros => nzeros,
y => frac_r_shift
);
-- Add back the sticky bit
frac_r_shift_sticky <= frac_r_shift & frac_r(0);
-- Update the final scaling factor
ovf_tmp <= (7 downto 1 => '0') & ovf_r;
nzeros_tmp <= (7 downto 4 => '0') & std_logic_vector(nzeros);
sf_r <= "10110100" when nzeros = "1110" else
(std_logic_vector(signed(sf_l) + signed(ovf_tmp) - signed(nzeros_tmp)));
sign_r <= '0' when nzeros = "1110" else
sign_l;
-- Check for infinity
inf_r <= inf_x or inf_y;
inst_encoder : posit16_encoder
port map (
sign => sign_r,
sf => sf_r,
frac => frac_r_shift_sticky,
inf => inf_r,
x => r
);
end behaviour;