1 |
2 |
atypic |
-- ==============================================================================
|
2 |
|
|
-- Generic signed/unsigned restoring divider
|
3 |
|
|
--
|
4 |
|
|
-- This library is free software; you can redistribute it and/or modify it
|
5 |
|
|
-- under the terms of the GNU Lesser General Public License as published
|
6 |
|
|
-- by the Free Software Foundation; either version 2.1 of the License, or
|
7 |
|
|
-- (at your option) any later version.
|
8 |
|
|
--
|
9 |
|
|
-- This library is distributed in the hope that it will be useful, but WITHOUT
|
10 |
|
|
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
11 |
|
|
-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
12 |
|
|
-- License for more details. See http://www.gnu.org/copyleft/lesser.txt
|
13 |
|
|
--
|
14 |
|
|
-- ------------------------------------------------------------------------------
|
15 |
|
|
-- Version Author Date Changes
|
16 |
|
|
-- 0.1 Hans Tiggeler 07/18/02 Tested on Modelsim SE 5.6
|
17 |
|
|
-- ==============================================================================
|
18 |
|
|
library ieee;
|
19 |
|
|
use ieee.std_logic_1164.all;
|
20 |
|
|
use ieee.std_logic_unsigned.all;
|
21 |
|
|
|
22 |
|
|
entity divider is
|
23 |
|
|
GENERIC(WIDTH_DIVID : Integer := 32; -- Width Dividend
|
24 |
|
|
WIDTH_DIVIS : Integer := 16); -- Width Divisor
|
25 |
|
|
port(dividend : in std_logic_vector (WIDTH_DIVID-1 downto 0);
|
26 |
|
|
divisor : in std_logic_vector (WIDTH_DIVIS-1 downto 0);
|
27 |
|
|
quotient : out std_logic_vector (WIDTH_DIVID-1 downto 0);
|
28 |
|
|
remainder : out std_logic_vector (WIDTH_DIVIS-1 downto 0);
|
29 |
|
|
twocomp : in std_logic); -- '1' = 2's Complement,
|
30 |
|
|
end divider ; -- '0' = Unsigned
|
31 |
|
|
|
32 |
|
|
|
33 |
|
|
architecture rtl of divider is
|
34 |
|
|
type stdarray is array(WIDTH_DIVID downto 0) of std_logic_vector(WIDTH_DIVIS downto 0);
|
35 |
|
|
signal addsub_s : stdarray;
|
36 |
|
|
signal dividend_s : std_logic_vector(WIDTH_DIVID-1 downto 0);
|
37 |
|
|
signal didi_s : std_logic_vector(WIDTH_DIVID-1 downto 0);
|
38 |
|
|
signal divisor_s : std_logic_vector(WIDTH_DIVIS downto 0);
|
39 |
|
|
signal disi_s : std_logic_vector(WIDTH_DIVIS downto 0);
|
40 |
|
|
signal divn_s : std_logic_vector(WIDTH_DIVIS downto 0);
|
41 |
|
|
signal div_s : std_logic_vector(WIDTH_DIVIS downto 0);
|
42 |
|
|
signal signquot_s : std_logic;
|
43 |
|
|
signal signremain_s : std_logic;
|
44 |
|
|
signal remain_s : std_logic_vector(WIDTH_DIVIS+1 downto 0);
|
45 |
|
|
signal remainder_s : std_logic_vector(WIDTH_DIVIS+1 downto 0);
|
46 |
|
|
signal quot_s : std_logic_vector(WIDTH_DIVID-1 downto 0);
|
47 |
|
|
signal quotient_s : std_logic_vector(WIDTH_DIVID-1 downto 0);
|
48 |
|
|
begin
|
49 |
|
|
-- Sign Quotient
|
50 |
|
|
signquot_s <= (dividend(WIDTH_DIVID-1) xor divisor(WIDTH_DIVIS-1)) and twocomp;
|
51 |
|
|
|
52 |
|
|
-- Sign Remainder
|
53 |
|
|
signremain_s <= (signquot_s xor divisor(WIDTH_DIVIS-1)) and twocomp;
|
54 |
|
|
|
55 |
|
|
-- Rectify Dividend
|
56 |
|
|
didi_s <= not(dividend) when (dividend(WIDTH_DIVID-1) and twocomp)='1' else dividend;
|
57 |
|
|
dividend_s <= didi_s + (dividend(WIDTH_DIVID-1) and twocomp);
|
58 |
|
|
|
59 |
|
|
-- Rectify Divisor
|
60 |
|
|
disi_s <= not('1'&divisor) when (divisor(WIDTH_DIVIS-1) and twocomp)='1' else ('0'&divisor);
|
61 |
|
|
divisor_s <= disi_s + (divisor(WIDTH_DIVIS-1) and twocomp);
|
62 |
|
|
|
63 |
|
|
-- Create 2-Complement negative divisor
|
64 |
|
|
divn_s <= not(divisor_s) + '1';
|
65 |
|
|
|
66 |
|
|
-- Positive Divisor
|
67 |
|
|
div_s <= divisor_s;
|
68 |
|
|
|
69 |
|
|
-- Note first stage dividend_s(WIDTH_DIVID-1) is always '0'
|
70 |
|
|
addsub_s(WIDTH_DIVID) <= divn_s;
|
71 |
|
|
|
72 |
|
|
stages : for i in WIDTH_DIVID-1 downto 0 generate
|
73 |
|
|
addsub_s(i) <= ((addsub_s(i+1)(WIDTH_DIVIS-1 downto 0) & dividend_s(i)) + div_s) when addsub_s(i+1)(WIDTH_DIVIS)='1' else
|
74 |
|
|
((addsub_s(i+1)(WIDTH_DIVIS-1 downto 0) & dividend_s(i)) + divn_s);
|
75 |
|
|
end generate;
|
76 |
|
|
|
77 |
|
|
remain_s <= ((addsub_s(0)(WIDTH_DIVIS)&addsub_s(0)) + ('0'&div_s)) when addsub_s(0)(WIDTH_DIVIS)='1' else '0'&addsub_s(0);
|
78 |
|
|
|
79 |
|
|
-- Quotient
|
80 |
|
|
outstage : for i in WIDTH_DIVID-1 downto 0 generate
|
81 |
|
|
quot_s(i) <= not(addsub_s(i)(WIDTH_DIVIS));
|
82 |
|
|
end generate;
|
83 |
|
|
|
84 |
|
|
remainder_s <= ((not(remain_s)) + '1') when signremain_s='1' else remain_s; -- correct remainder sign
|
85 |
|
|
|
86 |
|
|
quotient_s <= ((not(quot_s)) + '1') when signquot_s='1' else quot_s; -- correct quotient sign
|
87 |
|
|
|
88 |
|
|
remainder <= remainder_s(WIDTH_DIVIS-1 downto 0) when twocomp='1' else
|
89 |
|
|
(remainder_s(WIDTH_DIVIS-1 downto 0)+remainder_s(WIDTH_DIVIS+1));
|
90 |
|
|
|
91 |
|
|
quotient <= quotient_s;
|
92 |
|
|
end rtl;
|