OpenCores
URL https://opencores.org/ocsvn/signed_unsigned_multiplier_and_divider/signed_unsigned_multiplier_and_divider/trunk

Subversion Repositories signed_unsigned_multiplier_and_divider

[/] [signed_unsigned_multiplier_and_divider/] [trunk/] [signedmultiplier.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.