1 |
2 |
zpekic |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company: @Home
|
3 |
|
|
-- Engineer: zpekic@hotmail.com
|
4 |
|
|
--
|
5 |
|
|
-- Create Date: 15:37:39 02/04/2018
|
6 |
|
|
-- Design Name:
|
7 |
|
|
-- Module Name: signedmultiplier - Behavioral
|
8 |
|
|
-- Project Name:
|
9 |
|
|
-- Target Devices:
|
10 |
|
|
-- Tool versions:
|
11 |
|
|
-- Description: Mostly bsed on Chapter 7-3 from "Computer Organization and Architecture" by William Stallings
|
12 |
|
|
--
|
13 |
|
|
-- Dependencies:
|
14 |
|
|
--
|
15 |
|
|
-- Revision:
|
16 |
|
|
-- Revision 0.01 - File Created
|
17 |
|
|
-- Additional Comments:
|
18 |
|
|
--
|
19 |
|
|
----------------------------------------------------------------------------------
|
20 |
|
|
library IEEE;
|
21 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
22 |
|
|
|
23 |
|
|
-- Uncomment the following library declaration if using
|
24 |
|
|
-- arithmetic functions with Signed or Unsigned values
|
25 |
|
|
use IEEE.NUMERIC_STD.ALL;
|
26 |
|
|
|
27 |
|
|
-- Uncomment the following library declaration if instantiating
|
28 |
|
|
-- any Xilinx primitives in this code.
|
29 |
|
|
--library UNISIM;
|
30 |
|
|
--use UNISIM.VComponents.all;
|
31 |
|
|
|
32 |
|
|
entity signedmultiplier is
|
33 |
|
|
Port ( reset : in STD_LOGIC; -- Active high to initialize. Note that ready will be low as long as it remains high
|
34 |
|
|
clk : in STD_LOGIC; -- Clock to drive the FSM
|
35 |
|
|
start : in STD_LOGIC; -- Apply high for at least 1 clock cycle to start computation
|
36 |
|
|
mode: in STD_LOGIC_VECTOR(1 downto 0); -- 00: unsigned multiply, 01: signed multiply, 10: unsigned divide, 11: signed divide
|
37 |
|
|
dividend32: in STD_LOGIC; -- 0: 16/16 divide, 1: 32/16 divide
|
38 |
|
|
arg0h : in STD_LOGIC_VECTOR (15 downto 0); -- used as MSW for 32/16 divide
|
39 |
|
|
arg0l : in STD_LOGIC_VECTOR (15 downto 0); -- LSW for 32/16 divide, factor0 for 16*16 multiplication
|
40 |
|
|
arg1 : in STD_LOGIC_VECTOR (15 downto 0); -- factor1 for 16*16 multiplication
|
41 |
|
|
result : buffer STD_LOGIC_VECTOR (31 downto 0); -- 32 bit result when multiplying, when dividing quotient is MSW, remainder is LSW
|
42 |
|
|
ready : out STD_LOGIC; -- goes high when done
|
43 |
|
|
error : out STD_LOGIC; -- goes high when dividing by 0
|
44 |
|
|
zero : out STD_LOGIC; -- quotient is zero (divide) or whole product is zero (multiplication)
|
45 |
|
|
sign : out STD_LOGIC; -- same result checked like for zero, only meaningful for signed operation
|
46 |
|
|
debug : out STD_LOGIC_VECTOR(3 downto 0)); -- debug output (leave open)
|
47 |
|
|
end signedmultiplier;
|
48 |
|
|
|
49 |
|
|
architecture Behavioral of signedmultiplier is
|
50 |
|
|
|
51 |
|
|
constant min_value: std_logic_vector(15 downto 0):= X"8000";
|
52 |
|
|
constant zero_value: std_logic_vector(15 downto 0):= X"0000";
|
53 |
|
|
constant minusone_value: std_logic_vector(15 downto 0):= X"FFFF";
|
54 |
|
|
constant min_value32: std_logic_vector(31 downto 0):= X"80000000";
|
55 |
|
|
constant zero_value32: std_logic_vector(31 downto 0):= X"00000000";
|
56 |
|
|
constant minusone_value32: std_logic_vector(31 downto 0):= X"FFFFFFFF";
|
57 |
|
|
|
58 |
|
|
type state is (st_reset, st_readytostart,
|
59 |
|
|
-- Multiply
|
60 |
|
|
st_mul_checkzero, st_mul_setzero, st_mul_setprod,
|
61 |
|
|
st_ms_checkq, st_ms_aplusm, st_ms_aminusm, st_ms_shiftanddecrement, st_ms_checkcounter,
|
62 |
|
|
st_mu_checkq, st_mu_aplusm, st_mu_shiftanddecrement, st_mu_checkcounter,
|
63 |
|
|
-- Divide
|
64 |
|
|
st_div_checkzero, st_div_setresult, st_div_setzero,
|
65 |
|
|
st_dq_posdivneg, st_dq_negdivpos, st_dq_negdivneg, st_dq_checkquadrant,
|
66 |
|
|
st_du_checkfit, st_du_shiftleft, st_du_aminusm, st_du_checka, st_du_setq0decrement, st_du_clearq0decrementaplusm, st_du_checkcounter,
|
67 |
|
|
-- Common
|
68 |
|
|
st_done_ok, st_done_error);
|
69 |
|
|
|
70 |
|
|
signal state_current, state_next: state;
|
71 |
|
|
|
72 |
|
|
signal m32: std_logic_vector(31 downto 0);
|
73 |
|
|
signal caqx32: std_logic_vector(65 downto 0);
|
74 |
|
|
alias c32: std_logic is caqx32(65);
|
75 |
|
|
alias a32: std_logic_vector(31 downto 0) is caqx32(64 downto 33);
|
76 |
|
|
alias q32: std_logic_vector(31 downto 0) is caqx32(32 downto 1);
|
77 |
|
|
alias aq32: std_logic_vector(63 downto 0) is caqx32(64 downto 1);
|
78 |
|
|
alias ca32: std_logic_vector(32 downto 0) is caqx32(65 downto 33);
|
79 |
|
|
|
80 |
|
|
signal m: std_logic_vector(15 downto 0);
|
81 |
|
|
signal caqx: std_logic_vector(33 downto 0);
|
82 |
|
|
alias c: std_logic is caqx(33);
|
83 |
|
|
alias a: std_logic_vector(15 downto 0) is caqx(32 downto 17);
|
84 |
|
|
alias q: std_logic_vector(15 downto 0) is caqx(16 downto 1);
|
85 |
|
|
alias x: std_logic is caqx(0);
|
86 |
|
|
alias caq: std_logic_vector(32 downto 0) is caqx(33 downto 1);
|
87 |
|
|
alias aq: std_logic_vector(31 downto 0) is caqx(32 downto 1);
|
88 |
|
|
alias aqx: std_logic_vector(32 downto 0) is caqx(32 downto 0);
|
89 |
|
|
alias ca: std_logic_vector(16 downto 0) is caqx(33 downto 17);
|
90 |
|
|
alias prod: std_logic_vector(31 downto 0) is result;
|
91 |
|
|
alias quotient: std_logic_vector(15 downto 0) is result(31 downto 16);
|
92 |
|
|
alias remainder: std_logic_vector(15 downto 0) is result(15 downto 0);
|
93 |
|
|
signal m_is_zero, q_is_zero, m_is_minusone, q_is_min: std_logic;
|
94 |
|
|
|
95 |
|
|
signal q_is_negative, m_is_negative, carry: std_logic;
|
96 |
|
|
signal counter: integer range 0 to 32;
|
97 |
|
|
signal a_padded, m_padded, m_2compl, a_minus_m, a_plus_m: std_logic_vector(17 downto 0); -- these include carry in and out!
|
98 |
|
|
signal a_complement, q_complement, m_complement: std_logic_vector(15 downto 0);
|
99 |
|
|
signal a32_padded, m32_padded, m32_2compl, a32_minus_m32, a32_plus_m32: std_logic_vector(33 downto 0); -- these include carry in and out!
|
100 |
|
|
signal a32_complement, q32_complement, m32_complement: std_logic_vector(31 downto 0);
|
101 |
|
|
signal changesign_quotient, changesign_remainder: std_logic;
|
102 |
|
|
signal mode32, quotient_will_fit: std_logic;
|
103 |
|
|
|
104 |
|
|
begin
|
105 |
|
|
|
106 |
|
|
debug(3) <= q_is_negative;
|
107 |
|
|
debug(2) <= m_is_negative;
|
108 |
|
|
debug(1) <= changesign_quotient;
|
109 |
|
|
debug(0) <= changesign_remainder;
|
110 |
|
|
|
111 |
|
|
-- 32 bit mode only for division!
|
112 |
|
|
mode32 <= mode(1) and dividend32;
|
113 |
|
|
|
114 |
|
|
-- combinatorial output flags
|
115 |
|
|
zero <= '1' when ((prod = zero_value32 and mode(1) = '0') or (quotient = zero_value and mode(1) = '1')) else '0';
|
116 |
|
|
sign <= prod(31) when mode(1) = '0' else quotient(15);
|
117 |
|
|
|
118 |
|
|
-- combinatorial signals to help drive the FSM
|
119 |
|
|
m_is_zero <= '1' when ((m = zero_value and mode32 = '0') or (m32 = zero_value32 and mode32 = '1')) else '0';
|
120 |
|
|
q_is_zero <= '1' when ((q = zero_value and mode32 = '0') or (q32 = zero_value32 and mode32 = '1')) else '0';
|
121 |
|
|
m_is_minusone <= '1' when ((m = minusone_value and mode32 = '0') or (m32 = minusone_value32 and mode32 = '1')) else '0';
|
122 |
|
|
q_is_min <= '1' when ((q = min_value and mode32 = '0') or (q32 = min_value32 and mode32 = '1')) else '0';
|
123 |
|
|
|
124 |
|
|
--q_is_negative <= q(15) when mode32 = '0' else q32(31);
|
125 |
|
|
--m_is_negative <= m(15) when mode32 = '0' else m32(31);
|
126 |
|
|
|
127 |
|
|
carry <= c when mode32 = '0' else c32;
|
128 |
|
|
quotient_will_fit <= '1' when (unsigned(m32(15 downto 0)) > unsigned(q32(31 downto 16))) else '0';
|
129 |
|
|
|
130 |
|
|
-- 2's complement add and substract
|
131 |
|
|
a_padded <= '0' & a & '1';
|
132 |
|
|
m_padded <= '0' & m & '0';
|
133 |
|
|
m_2compl <= "011111111111111111" xor m_padded;
|
134 |
|
|
a_minus_m <= std_logic_vector(unsigned(a_padded) + unsigned(m_2compl));
|
135 |
|
|
a_plus_m <= std_logic_vector(unsigned(a_padded) + unsigned(m_padded));
|
136 |
|
|
q_complement <= std_logic_vector(unsigned(q xor minusone_value) + 1);
|
137 |
|
|
a_complement <= std_logic_vector(unsigned(a xor minusone_value) + 1);
|
138 |
|
|
m_complement <= std_logic_vector(unsigned(m xor minusone_value) + 1);
|
139 |
|
|
|
140 |
|
|
a32_padded <= '0' & a32 & '1';
|
141 |
|
|
m32_padded <= '0' & m32 & '0';
|
142 |
|
|
m32_2compl <= "0111111111111111111111111111111111" xor m32_padded;
|
143 |
|
|
a32_minus_m32 <= std_logic_vector(unsigned(a32_padded) + unsigned(m32_2compl));
|
144 |
|
|
a32_plus_m32 <= std_logic_vector(unsigned(a32_padded) + unsigned(m32_padded));
|
145 |
|
|
q32_complement <= std_logic_vector(unsigned(q32 xor minusone_value32) + 1);
|
146 |
|
|
a32_complement <= std_logic_vector(unsigned(a32 xor minusone_value32) + 1);
|
147 |
|
|
m32_complement <= std_logic_vector(unsigned(m32 xor minusone_value32) + 1);
|
148 |
|
|
|
149 |
|
|
-- FSM
|
150 |
|
|
drive: process(reset, clk, state_next)
|
151 |
|
|
begin
|
152 |
|
|
if (reset = '1') then
|
153 |
|
|
state_current <= st_reset;
|
154 |
|
|
else
|
155 |
|
|
if (rising_edge(clk)) then
|
156 |
|
|
state_current <= state_next;
|
157 |
|
|
end if;
|
158 |
|
|
end if;
|
159 |
|
|
end process;
|
160 |
|
|
|
161 |
|
|
execute: process(clk, state_current)
|
162 |
|
|
begin
|
163 |
|
|
if (rising_edge(clk)) then
|
164 |
|
|
case state_current is
|
165 |
|
|
when st_reset =>
|
166 |
|
|
ready <= '0';
|
167 |
|
|
error <= '0';
|
168 |
|
|
|
169 |
|
|
when st_readytostart =>
|
170 |
|
|
ready <= '1';
|
171 |
|
|
m_is_negative <= mode(0) and arg1(15);
|
172 |
|
|
if (mode32 = '0') then
|
173 |
|
|
counter <= 16;
|
174 |
|
|
q_is_negative <= mode(0) and arg0l(15);
|
175 |
|
|
else
|
176 |
|
|
counter <= 32;
|
177 |
|
|
q_is_negative <= mode(0) and arg0h(15);
|
178 |
|
|
end if;
|
179 |
|
|
-- for 16*16 bit multiplication and 16/16 bit divisions
|
180 |
|
|
m <= arg1;
|
181 |
|
|
caqx <= '0' & X"0000" & arg0l & '0';
|
182 |
|
|
-- for 32/16 bit divisions
|
183 |
|
|
if (mode(0) = '1' and arg1(15) = '1') then
|
184 |
|
|
m32 <= X"FFFF" & arg1;
|
185 |
|
|
else
|
186 |
|
|
m32 <= X"0000" & arg1;
|
187 |
|
|
end if;
|
188 |
|
|
caqx32 <= '0' & X"00000000" & arg0h & arg0l & '0';
|
189 |
|
|
|
190 |
|
|
when st_mul_checkzero => -- clear ready and error when entering computation
|
191 |
|
|
ready <= '0';
|
192 |
|
|
error <= '0';
|
193 |
|
|
|
194 |
|
|
when st_ms_aminusm =>
|
195 |
|
|
ca <= a_minus_m(17 downto 1);
|
196 |
|
|
|
197 |
|
|
when st_ms_aplusm | st_mu_aplusm =>
|
198 |
|
|
ca <= a_plus_m(17 downto 1);
|
199 |
|
|
|
200 |
|
|
when st_ms_shiftanddecrement =>
|
201 |
|
|
aqx <= aqx(32) & aqx(32 downto 1);
|
202 |
|
|
counter <= counter - 1;
|
203 |
|
|
|
204 |
|
|
when st_mu_shiftanddecrement =>
|
205 |
|
|
caq <= '0' & caq(32 downto 1);
|
206 |
|
|
counter <= counter - 1;
|
207 |
|
|
|
208 |
|
|
when st_mul_setzero =>
|
209 |
|
|
prod <= X"00000000";
|
210 |
|
|
|
211 |
|
|
when st_mul_setprod =>
|
212 |
|
|
prod <= aq;
|
213 |
|
|
|
214 |
|
|
when st_done_ok =>
|
215 |
|
|
error <= '0';
|
216 |
|
|
|
217 |
|
|
when st_done_error =>
|
218 |
|
|
error <= '1';
|
219 |
|
|
|
220 |
|
|
when st_div_checkzero =>
|
221 |
|
|
ready <= '0'; -- clear ready when entering computation
|
222 |
|
|
error <= '0';
|
223 |
|
|
changesign_quotient <= '0';
|
224 |
|
|
changesign_remainder <= '0';
|
225 |
|
|
--- for debugging ---
|
226 |
|
|
--result <= aq;
|
227 |
|
|
|
228 |
|
|
when st_div_setzero =>
|
229 |
|
|
quotient <= q; -- q = 0
|
230 |
|
|
remainder <= m; -- remainder = dividend
|
231 |
|
|
|
232 |
|
|
when st_div_setresult =>
|
233 |
|
|
if (mode32 = '0') then
|
234 |
|
|
if (changesign_quotient = '0') then
|
235 |
|
|
quotient <= q;
|
236 |
|
|
else
|
237 |
|
|
quotient <= q_complement;
|
238 |
|
|
end if;
|
239 |
|
|
if (changesign_remainder = '0') then
|
240 |
|
|
remainder <= a;
|
241 |
|
|
else
|
242 |
|
|
remainder <= a_complement;
|
243 |
|
|
end if;
|
244 |
|
|
else
|
245 |
|
|
if (changesign_quotient = '0') then
|
246 |
|
|
quotient <= q32(15 downto 0);
|
247 |
|
|
else
|
248 |
|
|
quotient <= q32_complement(15 downto 0);
|
249 |
|
|
end if;
|
250 |
|
|
if (changesign_remainder = '0') then
|
251 |
|
|
remainder <= a32(15 downto 0);
|
252 |
|
|
else
|
253 |
|
|
remainder <= a32_complement(15 downto 0);
|
254 |
|
|
end if;
|
255 |
|
|
end if;
|
256 |
|
|
|
257 |
|
|
when st_du_shiftleft =>
|
258 |
|
|
aq <= aq(30 downto 0) & '0';
|
259 |
|
|
aq32 <= aq32(62 downto 0) & '0';
|
260 |
|
|
--- for debugging ---
|
261 |
|
|
result <= aq32(31 downto 0);
|
262 |
|
|
|
263 |
|
|
when st_du_aminusm =>
|
264 |
|
|
ca <= a_minus_m(17 downto 1);
|
265 |
|
|
ca32 <= a32_minus_m32(33 downto 1);
|
266 |
|
|
--- for debugging ---
|
267 |
|
|
result <= aq32(31 downto 0);
|
268 |
|
|
|
269 |
|
|
when st_du_setq0decrement => --| st_ds_setq0decrement =>
|
270 |
|
|
q <= q or X"0001";
|
271 |
|
|
q32 <= q32 or X"00000001";
|
272 |
|
|
counter <= counter - 1;
|
273 |
|
|
--- for debugging ---
|
274 |
|
|
result <= aq32(31 downto 0);
|
275 |
|
|
|
276 |
|
|
when st_du_clearq0decrementaplusm =>
|
277 |
|
|
ca <= a_plus_m(17 downto 1);
|
278 |
|
|
ca32 <= a32_plus_m32(33 downto 1);
|
279 |
|
|
counter <= counter - 1;
|
280 |
|
|
--- for debugging ---
|
281 |
|
|
result <= aq32(31 downto 0);
|
282 |
|
|
|
283 |
|
|
when st_du_checkcounter =>
|
284 |
|
|
--- for debugging ---
|
285 |
|
|
result <= m32; --std_logic_vector(to_unsigned(counter, 32));
|
286 |
|
|
|
287 |
|
|
when st_dq_posdivneg =>
|
288 |
|
|
m <= m_complement;
|
289 |
|
|
m32 <= m32_complement;
|
290 |
|
|
changesign_quotient <= '1';
|
291 |
|
|
--- for debugging ---
|
292 |
|
|
result <= aq32(31 downto 0);
|
293 |
|
|
|
294 |
|
|
when st_dq_negdivpos =>
|
295 |
|
|
q <= q_complement;
|
296 |
|
|
q32 <= q32_complement;
|
297 |
|
|
changesign_quotient <= '1';
|
298 |
|
|
changesign_remainder <= '1';
|
299 |
|
|
--- for debugging ---
|
300 |
|
|
result <= aq32(31 downto 0);
|
301 |
|
|
|
302 |
|
|
when st_dq_negdivneg =>
|
303 |
|
|
q <= q_complement;
|
304 |
|
|
q32 <= q32_complement;
|
305 |
|
|
m <= m_complement;
|
306 |
|
|
m32 <= m32_complement;
|
307 |
|
|
changesign_remainder <= '1';
|
308 |
|
|
--- for debugging ---
|
309 |
|
|
result <= aq32(31 downto 0);
|
310 |
|
|
|
311 |
|
|
when others =>
|
312 |
|
|
null;
|
313 |
|
|
|
314 |
|
|
end case;
|
315 |
|
|
end if;
|
316 |
|
|
end process;
|
317 |
|
|
|
318 |
|
|
sequence: process(state_current, aq, m, counter, start)
|
319 |
|
|
begin
|
320 |
|
|
case state_current is
|
321 |
|
|
when st_reset =>
|
322 |
|
|
state_next <= st_readytostart;
|
323 |
|
|
|
324 |
|
|
-- COMMON START --
|
325 |
|
|
when st_readytostart =>
|
326 |
|
|
if (start = '1') then
|
327 |
|
|
if (mode(1) = '0') then
|
328 |
|
|
state_next <= st_mul_checkzero; -- * starting point
|
329 |
|
|
else
|
330 |
|
|
state_next <= st_div_checkzero; -- / starting point
|
331 |
|
|
end if;
|
332 |
|
|
else
|
333 |
|
|
state_next <= st_readytostart;
|
334 |
|
|
end if;
|
335 |
|
|
|
336 |
|
|
-- DIVISION
|
337 |
|
|
when st_div_checkzero =>
|
338 |
|
|
if (m_is_zero = '1') then
|
339 |
|
|
state_next <= st_done_error; -- all divide by zero results in error!
|
340 |
|
|
else
|
341 |
|
|
if (q_is_zero = '1') then
|
342 |
|
|
state_next <= st_div_setzero; -- divide zero by something other then 0 is 0 with remainder
|
343 |
|
|
else
|
344 |
|
|
if (mode(0) = '1') then
|
345 |
|
|
if (q_is_min = '1' and m_is_minusone = '1' ) then -- -32768 / -1 = overflow!
|
346 |
|
|
state_next <= st_done_error;
|
347 |
|
|
else
|
348 |
|
|
state_next <= st_dq_checkquadrant; -- signed divide
|
349 |
|
|
end if;
|
350 |
|
|
else
|
351 |
|
|
state_next <= st_du_checkfit; -- unsigned divide
|
352 |
|
|
end if;
|
353 |
|
|
end if;
|
354 |
|
|
end if;
|
355 |
|
|
|
356 |
|
|
when st_div_setzero =>
|
357 |
|
|
state_next <= st_done_ok;
|
358 |
|
|
|
359 |
|
|
when st_div_setresult =>
|
360 |
|
|
state_next <= st_readytostart; -- set result may have set error flag to 1!
|
361 |
|
|
|
362 |
|
|
-- signed, 4 quadrant approach --
|
363 |
|
|
when st_dq_checkquadrant =>
|
364 |
|
|
if (q_is_negative = '0') then
|
365 |
|
|
if (m_is_negative = '0') then
|
366 |
|
|
state_next <= st_du_checkfit; -- +/+ = unsigned divide
|
367 |
|
|
else
|
368 |
|
|
state_next <= st_dq_posdivneg; -- +/-
|
369 |
|
|
end if;
|
370 |
|
|
else
|
371 |
|
|
if (m_is_negative = '0') then
|
372 |
|
|
state_next <= st_dq_negdivpos; -- -/+
|
373 |
|
|
else
|
374 |
|
|
state_next <= st_dq_negdivneg; -- -/-
|
375 |
|
|
end if;
|
376 |
|
|
end if;
|
377 |
|
|
|
378 |
|
|
when st_dq_posdivneg | st_dq_negdivpos | st_dq_negdivneg =>
|
379 |
|
|
state_next <= st_du_checkfit;
|
380 |
|
|
|
381 |
|
|
-- unsigned --
|
382 |
|
|
when st_du_checkfit =>
|
383 |
|
|
if (mode32 = '0') then
|
384 |
|
|
state_next <= st_du_shiftleft;
|
385 |
|
|
else
|
386 |
|
|
if (quotient_will_fit = '1') then
|
387 |
|
|
state_next <= st_du_shiftleft;
|
388 |
|
|
else
|
389 |
|
|
state_next <= st_done_error;
|
390 |
|
|
end if;
|
391 |
|
|
end if;
|
392 |
|
|
|
393 |
|
|
when st_du_shiftleft =>
|
394 |
|
|
state_next <= st_du_aminusm;
|
395 |
|
|
|
396 |
|
|
when st_du_aminusm =>
|
397 |
|
|
state_next <= st_du_checka;
|
398 |
|
|
|
399 |
|
|
when st_du_checka =>
|
400 |
|
|
if (carry = '1') then -- A >= M
|
401 |
|
|
state_next <= st_du_setq0decrement;
|
402 |
|
|
else
|
403 |
|
|
state_next <= st_du_clearq0decrementaplusm;
|
404 |
|
|
end if;
|
405 |
|
|
|
406 |
|
|
when st_du_setq0decrement =>
|
407 |
|
|
state_next <= st_du_checkcounter;
|
408 |
|
|
|
409 |
|
|
when st_du_clearq0decrementaplusm =>
|
410 |
|
|
state_next <= st_du_checkcounter;
|
411 |
|
|
|
412 |
|
|
when st_du_checkcounter =>
|
413 |
|
|
if (counter = 0) then
|
414 |
|
|
state_next <= st_div_setresult;
|
415 |
|
|
else
|
416 |
|
|
state_next <= st_du_shiftleft;
|
417 |
|
|
end if;
|
418 |
|
|
|
419 |
|
|
-- MULTIPLICATION --
|
420 |
|
|
when st_mul_checkzero =>
|
421 |
|
|
if (q_is_zero = '1' or m_is_zero = '1') then
|
422 |
|
|
state_next <= st_mul_setzero;
|
423 |
|
|
else
|
424 |
|
|
if (mode(0) = '0') then
|
425 |
|
|
state_next <= st_mu_checkq;
|
426 |
|
|
else
|
427 |
|
|
state_next <= st_ms_checkq;
|
428 |
|
|
end if;
|
429 |
|
|
end if;
|
430 |
|
|
|
431 |
|
|
when st_mul_setzero =>
|
432 |
|
|
state_next <= st_done_ok;
|
433 |
|
|
|
434 |
|
|
when st_mul_setprod =>
|
435 |
|
|
state_next <= st_done_ok;
|
436 |
|
|
|
437 |
|
|
-- Unsigned --
|
438 |
|
|
when st_mu_checkq =>
|
439 |
|
|
if q(0) = '1' then
|
440 |
|
|
state_next <= st_mu_aplusm;
|
441 |
|
|
else
|
442 |
|
|
state_next <= st_mu_shiftanddecrement;
|
443 |
|
|
end if;
|
444 |
|
|
|
445 |
|
|
when st_mu_aplusm =>
|
446 |
|
|
state_next <= st_mu_shiftanddecrement;
|
447 |
|
|
|
448 |
|
|
when st_mu_shiftanddecrement =>
|
449 |
|
|
state_next <= st_mu_checkcounter;
|
450 |
|
|
|
451 |
|
|
when st_mu_checkcounter =>
|
452 |
|
|
if (counter = 0) then
|
453 |
|
|
state_next <= st_mul_setprod;
|
454 |
|
|
else
|
455 |
|
|
state_next <= st_mu_checkq;
|
456 |
|
|
end if;
|
457 |
|
|
|
458 |
|
|
-- Signed --
|
459 |
|
|
when st_ms_checkq =>
|
460 |
|
|
case aqx(1 downto 0) is
|
461 |
|
|
when "10" =>
|
462 |
|
|
state_next <= st_ms_aminusm;
|
463 |
|
|
when "01" =>
|
464 |
|
|
state_next <= st_ms_aplusm;
|
465 |
|
|
when others =>
|
466 |
|
|
state_next <= st_ms_shiftanddecrement;
|
467 |
|
|
end case;
|
468 |
|
|
|
469 |
|
|
when st_ms_aminusm =>
|
470 |
|
|
state_next <= st_ms_shiftanddecrement;
|
471 |
|
|
|
472 |
|
|
when st_ms_aplusm =>
|
473 |
|
|
state_next <= st_ms_shiftanddecrement;
|
474 |
|
|
|
475 |
|
|
when st_ms_shiftanddecrement =>
|
476 |
|
|
state_next <= st_ms_checkcounter;
|
477 |
|
|
|
478 |
|
|
when st_ms_checkcounter =>
|
479 |
|
|
if (counter = 0) then
|
480 |
|
|
state_next <= st_mul_setprod;
|
481 |
|
|
else
|
482 |
|
|
state_next <= st_ms_checkq;
|
483 |
|
|
end if;
|
484 |
|
|
|
485 |
|
|
-- COMMON END --
|
486 |
|
|
when st_done_ok =>
|
487 |
|
|
state_next <= st_readytostart;
|
488 |
|
|
|
489 |
|
|
when st_done_error =>
|
490 |
|
|
state_next <= st_readytostart;
|
491 |
|
|
|
492 |
|
|
when others =>
|
493 |
|
|
null;
|
494 |
|
|
end case;
|
495 |
|
|
end process;
|
496 |
|
|
|
497 |
|
|
end Behavioral;
|
498 |
|
|
|