1 |
25 |
mikel262 |
--------------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- V H D L F I L E --
|
4 |
|
|
-- COPYRIGHT (C) 2006-2009 --
|
5 |
|
|
-- --
|
6 |
|
|
--------------------------------------------------------------------------------
|
7 |
|
|
-- --
|
8 |
|
|
-- Title : DIVIDER --
|
9 |
|
|
-- Design : Signed Pipelined Divider core --
|
10 |
|
|
-- Author : Michal Krepa --
|
11 |
|
|
-- --
|
12 |
|
|
--------------------------------------------------------------------------------
|
13 |
|
|
-- --
|
14 |
|
|
-- File : S_DIVIDER.VHD --
|
15 |
|
|
-- Created : Sat Aug 26 2006 --
|
16 |
|
|
-- Modified : Thu Mar 12 2009 --
|
17 |
|
|
-- --
|
18 |
|
|
--------------------------------------------------------------------------------
|
19 |
|
|
-- --
|
20 |
|
|
-- Description : Signed Pipelined Divider --
|
21 |
|
|
-- --
|
22 |
|
|
-- dividend allowable range of -2**SIZE_C to 2**SIZE_C-1 [SIGNED number] --
|
23 |
|
|
-- divisor allowable range of 1 to (2**SIZE_C)/2-1 [UNSIGNED number] --
|
24 |
|
|
-- pipeline latency is 2*SIZE_C+2 (time from latching input to result ready) --
|
25 |
|
|
-- when pipeline is full new result is generated every clock cycle --
|
26 |
|
|
-- Non-Restoring division algorithm --
|
27 |
|
|
-- Use SIZE_C constant in divider entity to adjust bit width --
|
28 |
|
|
--------------------------------------------------------------------------------
|
29 |
|
|
|
30 |
|
|
--------------------------------------------------------------------------------
|
31 |
|
|
-- MAIN DIVIDER top level
|
32 |
|
|
--------------------------------------------------------------------------------
|
33 |
|
|
library IEEE;
|
34 |
|
|
use IEEE.STD_LOGIC_1164.All;
|
35 |
|
|
use IEEE.NUMERIC_STD.all;
|
36 |
|
|
|
37 |
|
|
entity s_divider is
|
38 |
|
|
generic
|
39 |
|
|
(
|
40 |
|
|
SIZE_C : INTEGER := 32
|
41 |
|
|
) ; -- SIZE_C: Number of bits
|
42 |
|
|
port
|
43 |
|
|
(
|
44 |
|
|
rst : in STD_LOGIC;
|
45 |
|
|
clk : in STD_LOGIC;
|
46 |
|
|
a : in STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;
|
47 |
|
|
d : in STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;
|
48 |
|
|
|
49 |
|
|
q : out STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;
|
50 |
|
|
r : out STD_LOGIC_VECTOR(SIZE_C-1 downto 0) ;
|
51 |
|
|
round : out STD_LOGIC
|
52 |
|
|
) ;
|
53 |
|
|
end s_divider ;
|
54 |
|
|
|
55 |
|
|
architecture str of s_divider is
|
56 |
|
|
|
57 |
|
|
type S_ARRAY is array(0 to SIZE_C+3) of unsigned(SIZE_C-1 downto 0);
|
58 |
|
|
type S2_ARRAY is array(0 to SIZE_C+1) of unsigned(2*SIZE_C-1 downto 0);
|
59 |
|
|
|
60 |
|
|
signal d_s : S_ARRAY;
|
61 |
|
|
signal q_s : S_ARRAY;
|
62 |
|
|
signal r_s : S2_ARRAY;
|
63 |
|
|
signal diff : S_ARRAY;
|
64 |
|
|
signal qu_s : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
|
65 |
|
|
signal ru_s : unsigned(SIZE_C-1 downto 0);
|
66 |
|
|
signal qu_s2 : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
|
67 |
|
|
signal ru_s2 : unsigned(SIZE_C-1 downto 0);
|
68 |
|
|
signal d_reg : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
|
69 |
|
|
signal pipeline_reg : STD_LOGIC_VECTOR(SIZE_C+3-1 downto 0);
|
70 |
|
|
signal r_reg : STD_LOGIC_VECTOR(SIZE_C-1 downto 0);
|
71 |
|
|
|
72 |
|
|
begin
|
73 |
|
|
|
74 |
|
|
pipeline : process(clk,rst)
|
75 |
|
|
begin
|
76 |
|
|
if rst = '1' then
|
77 |
|
|
for k in 0 to SIZE_C loop
|
78 |
|
|
r_s(k) <= (others => '0');
|
79 |
|
|
q_s(k) <= (others => '0');
|
80 |
|
|
d_s(k) <= (others => '0');
|
81 |
|
|
end loop;
|
82 |
|
|
pipeline_reg <= (others => '0');
|
83 |
|
|
elsif clk = '1' and clk'event then
|
84 |
|
|
|
85 |
|
|
-- negative number
|
86 |
|
|
if a(SIZE_C-1) = '1' then
|
87 |
|
|
-- negate negative number to create positive
|
88 |
|
|
r_s(0) <= unsigned(resize(unsigned(not(SIGNED(a)) + TO_SIGNED(1,SIZE_C)),2*SIZE_C));
|
89 |
|
|
-- left shift
|
90 |
|
|
pipeline_reg <= pipeline_reg(pipeline_reg'high-1 downto 0) & '1';
|
91 |
|
|
else
|
92 |
|
|
r_s(0) <= resize(unsigned(a),2*SIZE_C);
|
93 |
|
|
-- left shift
|
94 |
|
|
pipeline_reg <= pipeline_reg(pipeline_reg'high-1 downto 0) & '0';
|
95 |
|
|
end if;
|
96 |
|
|
d_s(0) <= unsigned(d);
|
97 |
|
|
q_s(0) <= (others => '0');
|
98 |
|
|
|
99 |
|
|
-- pipeline
|
100 |
|
|
for k in 0 to SIZE_C loop
|
101 |
|
|
-- test remainder if positive/negative
|
102 |
|
|
if r_s(k)(2*SIZE_C-1) = '0' then
|
103 |
|
|
-- shift r_tmp one bit left and subtract d_tmp from upper part of r_tmp
|
104 |
|
|
r_s(k+1)(2*SIZE_C-1 downto SIZE_C) <= r_s(k)(2*SIZE_C-2 downto SIZE_C-1) - d_s(k);
|
105 |
|
|
else
|
106 |
|
|
r_s(k+1)(2*SIZE_C-1 downto SIZE_C) <= r_s(k)(2*SIZE_C-2 downto SIZE_C-1) + d_s(k);
|
107 |
|
|
end if;
|
108 |
|
|
-- shift r_tmp one bit left (lower part)
|
109 |
|
|
r_s(k+1)(SIZE_C-1 downto 0) <= r_s(k)(SIZE_C-2 downto 0) & '0';
|
110 |
|
|
|
111 |
|
|
if diff(k)(SIZE_C-1) = '0' then
|
112 |
|
|
q_s(k+1) <= q_s(k)(SIZE_C-2 downto 0) & '1';
|
113 |
|
|
else
|
114 |
|
|
q_s(k+1) <= q_s(k)(SIZE_C-2 downto 0) & '0';
|
115 |
|
|
end if;
|
116 |
|
|
|
117 |
|
|
d_s(k+1) <= d_s(k);
|
118 |
|
|
end loop;
|
119 |
|
|
end if;
|
120 |
|
|
end process;
|
121 |
|
|
|
122 |
|
|
G_DIFF: for x in 0 to SIZE_C generate
|
123 |
|
|
diff(x) <= r_s(x)(2*SIZE_C-2 downto SIZE_C-1) - d_s(x) when r_s(x)(2*SIZE_C-1) = '0'
|
124 |
|
|
else r_s(x)(2*SIZE_C-2 downto SIZE_C-1) + d_s(x);
|
125 |
|
|
end generate G_DIFF;
|
126 |
|
|
|
127 |
|
|
qu_s <= STD_LOGIC_VECTOR( q_s(SIZE_C) );
|
128 |
|
|
ru_s <= r_s(SIZE_C)(2*SIZE_C-1 downto SIZE_C);
|
129 |
|
|
|
130 |
|
|
process(clk,rst)
|
131 |
|
|
begin
|
132 |
|
|
if rst = '1' then
|
133 |
|
|
q <= (others => '0');
|
134 |
|
|
r_reg <= (others => '0');
|
135 |
|
|
round <= '0';
|
136 |
|
|
elsif clk = '1' and clk'event then
|
137 |
|
|
|
138 |
|
|
|
139 |
|
|
if ru_s(SIZE_C-1) = '0' then
|
140 |
|
|
ru_s2 <= (ru_s);
|
141 |
|
|
else
|
142 |
|
|
ru_s2 <= (unsigned(ru_s) + d_s(SIZE_C));
|
143 |
|
|
end if;
|
144 |
|
|
qu_s2 <= qu_s;
|
145 |
|
|
|
146 |
|
|
-- negative number
|
147 |
|
|
if pipeline_reg(SIZE_C+1) = '1' then
|
148 |
|
|
-- negate positive number to create negative
|
149 |
|
|
q <= STD_LOGIC_VECTOR(not(SIGNED(qu_s2)) + TO_SIGNED(1,SIZE_C));
|
150 |
|
|
r_reg <= STD_LOGIC_VECTOR(not(SIGNED(ru_s2)) + TO_SIGNED(1,SIZE_C));
|
151 |
|
|
else
|
152 |
|
|
q <= STD_LOGIC_VECTOR(qu_s2);
|
153 |
|
|
r_reg <= STD_LOGIC_VECTOR(ru_s2);
|
154 |
|
|
end if;
|
155 |
|
|
|
156 |
|
|
-- if 2*remainder >= divisor then add 1 to round to nearest integer
|
157 |
|
|
if (ru_s2(SIZE_C-2 downto 0) & '0') >= d_s(SIZE_C+1) then
|
158 |
|
|
round <= '1';
|
159 |
|
|
else
|
160 |
|
|
round <= '0';
|
161 |
|
|
end if;
|
162 |
|
|
end if;
|
163 |
|
|
end process;
|
164 |
|
|
|
165 |
|
|
-- remainder
|
166 |
|
|
r <= r_reg;
|
167 |
|
|
|
168 |
|
|
end str;
|
169 |
|
|
|
170 |
|
|
|