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

Subversion Repositories plasma_fpu

[/] [plasma_fpu/] [trunk/] [src/] [cores/] [div_core.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 __alexs__
-- --------------------------------------------------------------------------
2
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<<<<
3
-- --------------------------------------------------------------------------
4
-- TITLE:       Divider core
5
-- AUTHOR:      Steve Rhoads (rhoadss@yahoo.com)  
6
--              Alex Schoenberger (Alex.Schoenberger@ies.tu-darmstadt.de)
7
-- COMMENT:
8
--
9
-- www.ies.tu-darmstadt.de
10
-- TU Darmstadt
11
-- Institute for Integrated Systems
12
-- Merckstr. 25
13
-- 
14
-- 64283 Darmstadt - GERMANY
15
-- --------------------------------------------------------------------------
16
-- PROJECT:       Plasma CPU core with FPU
17
-- FILENAME:      mult_core.vhd
18
-- --------------------------------------------------------------------------
19
-- COPYRIGHT: 
20
--  This project is distributed by GPLv2.0
21
--  Software placed into the public domain by the author.
22
--  Software 'as is' without warranty.  Author liable for nothing.
23
-- --------------------------------------------------------------------------
24
-- DESCRIPTION:
25
--        long upper=a, lower=0;
26
--        a = b << 31;
27
--        for(i = 0; i < 32; ++i)
28
--        {
29
--          lower = lower << 1;
30
--          if(upper >= a && a && b < 2)
31
--          {
32
--            upper = upper - a;
33
--            lower |= 1;
34
--          }
35
--          a = ((b&2) << 30) | (a >> 1);
36
--          b = b >> 1;
37
--        }
38
--
39
--    SYNTHESIZABLE
40
--
41
----------------------------------------------------------------------------
42
-- Revision History
43
-- --------------------------------------------------------------------------
44
-- Revision   Date    Author     CHANGES
45
-- 1.0      7/2014    AS         initial
46
-- --------------------------------------------------------------------------
47
library IEEE;
48
  use IEEE.std_logic_1164.ALL;
49
  use IEEE.numeric_std.ALL;
50
 
51
entity div_core is
52
  port(
53
    clk               : in  std_logic;
54
    rst               : in  std_logic;
55
 
56
    start             : in  std_logic;
57
    busy              : out std_logic;
58
    rdy               : out std_logic;
59
 
60
    sign_flag         : in  std_logic;
61
 
62
    a                 : in  std_logic_vector(31 downto 0);
63
    b                 : in  std_logic_vector(31 downto 0);
64
 
65
    c                 : out std_logic_vector(31 downto 0);
66
    r                 : out std_logic_vector(31 downto 0)
67
  );
68
end entity div_core;
69
 
70
--           _____   _____ _    _ _____ _______ ______ _____ _______ _    _ _____  ______ 
71
--     /\   |  __ \ / ____| |  | |_   _|__   __|  ____/ ____|__   __| |  | |  __ \|  ____|
72
--    /  \  | |__) | |    | |__| | | |    | |  | |__ | |       | |  | |  | | |__) | |__   
73
--   / /\ \ |  _  /| |    |  __  | | |    | |  |  __|| |       | |  | |  | |  _  /|  __|  
74
--  / ____ \| | \ \| |____| |  | |_| |_   | |  | |___| |____   | |  | |__| | | \ \| |____ 
75
-- /_/    \_\_|  \_\\_____|_|  |_|_____|  |_|  |______\_____|  |_|   \____/|_|  \_\______|
76
architecture structure_div_core of div_core is
77
  -- _ _  _ ___  _  _ ___ 
78
  -- | |\ | |__] |  |  |  
79
  -- | | \| |    |__|  |  
80
  alias flag_a_neg              : std_logic is a(31);               -- operand A is negative
81
  alias flag_b_neg              : std_logic is b(31);               -- operand B is negative
82
 
83
  signal a_convert              : std_logic_vector(31 downto 0);    -- twoscomplement of operand A
84
  signal b_convert              : std_logic_vector(31 downto 0);    -- twoscomplement of operand B  
85
 
86
  signal a_input                : std_logic_vector(31 downto 0);
87
  signal b_input                : std_logic_vector(31 downto 0);
88
 
89
  -- ____ ____ ____ _ ____ ___ ____ ____ ____ 
90
  -- |__/ |___ | __ | [__   |  |___ |__/ [__  
91
  -- |  \ |___ |__] | ___]  |  |___ |  \ ___]
92
  signal i_rem, reg_rem         : std_logic_vector(31 downto 0);
93
  signal i_qot, reg_qot         : std_logic_vector(31 downto 0);
94
 
95
  signal reg_divisor            : std_logic_vector(31 downto 0);
96
 
97
  signal reg_sign_a             : std_logic;
98
  signal reg_xor_sign           : std_logic;
99
 
100
  -- ___  ____ ___ ____ ___  ____ ___ _  _ 
101
  -- |  \ |__|  |  |__| |__] |__|  |  |__| 
102
  -- |__/ |  |  |  |  | |    |  |  |  |  | 
103
  signal i_sub                  : std_logic_vector(32 downto 0);
104
  alias  flag_sub_neg           : std_logic is i_sub(32);
105
 
106
  -- ____ ____ _  _ ___ ____ ____ _    ___  ____ ___ _  _ 
107
  -- |    |  | |\ |  |  |__/ |  | |    |__] |__|  |  |__| 
108
  -- |___ |__| | \|  |  |  \ |__| |___ |    |  |  |  |  | 
109
  type t_div_state              is ( s_IDLE, s_INPUT, s_WORK );
110
 
111
  signal i_state, state         : t_div_state;
112
 
113
  type t_div_flags is
114
    record
115
      input_en                  : std_logic;
116
      work_en                   : std_logic;
117
      cnt_en                    : std_logic;
118
      cnt_done                  : std_logic;
119
    end record;
120
 
121
  signal flags                  : t_div_flags;                      -- internal flags
122
 
123
  -- ____ ____ _  _ _  _ ___ ____ ____ 
124
  -- |    |  | |  | |\ |  |  |___ |__/ 
125
  -- |___ |__| |__| | \|  |  |___ |  \   
126
  signal div_counter            : std_logic_vector(4 downto 0);     -- 2**5 = 32 clock cycles for division
127
 
128
  -- ____ _  _ ___ ___  _  _ ___ 
129
  -- |  | |  |  |  |__] |  |  |  
130
  -- |__| |__|  |  |    |__|  |  
131
  signal qot_convert            : std_logic_vector(31 downto 0);    -- twoscomplement of quotient
132
  signal rem_convert            : std_logic_vector(31 downto 0);    -- twoscomplement of remainder
133
 
134
begin
135
-- synthesis translate_off
136
  -- ____ ____ _  _ _ ___ _   _    ____ _  _ ____ ____ _  _ 
137
  -- [__  |__| |\ | |  |   \_/     |    |__| |___ |    |_/  
138
  -- ___] |  | | \| |  |    |      |___ |  | |___ |___ | \_ 
139
  sanity_process:process( a, b )
140
  begin
141
    assert (not((a = x"8000_0000") and (sign_flag = '1'))) report "WARNING: operand A of DIV-CORE is 0x8000_0000, result will be erroneous!" severity warning;
142
    assert (not((b = x"8000_0000") and (sign_flag = '1'))) report "WARNING: operand B of DIV-CORE is 0x8000_0000, result will be erroneous!" severity warning;
143
  end process;
144
-- synthesis translate_on
145
 
146
  -- _ _  _ ___  _  _ ___ 
147
  -- | |\ | |__] |  |  |  
148
  -- | | \| |    |__|  |  
149
  --
150
  -- calculate twoscomplement
151
  --
152
  a_convert <= std_logic_vector( unsigned(not a) + to_unsigned(1, 32) );
153
  b_convert <= std_logic_vector( unsigned(not b) + to_unsigned(1, 32) );
154
 
155
  --
156
  -- for signed multiplication and negative operand B take twoscomplements
157
  --
158
  a_input   <= a_convert when (flag_a_neg and sign_flag) = '1' else a;
159
  b_input   <= b_convert when (flag_b_neg and sign_flag) = '1' else b;
160
 
161
  -- ____ ____ ____ _ ____ ___ ____ ____ ____ 
162
  -- |__/ |___ | __ | [__   |  |___ |__/ [__  
163
  -- |  \ |___ |__] | ___]  |  |___ |  \ ___]
164
  --
165
  -- reg_qot : quotient register
166
  -- reg_rem : remainder register
167
  -- reg_divisor : divisor register
168
  --
169
  -- reg_sign_a : detect negative dividend -> remainder should have the same sign 
170
  -- reg_xor_sign : detect different signs of operands -> result should be negative
171
  --
172
  -- counter value and state variable
173
  --
174
  mul_registers:
175
  process( clk )
176
  begin
177
    if rising_edge( clk ) then
178
      if rst = '1' then                                   -- << RESET ACTIVE
179
        reg_qot         <= (others => '0');
180
        reg_rem         <= (others => '0');
181
        reg_divisor     <= (others => '0');
182
 
183
        reg_sign_a      <= '0';
184
        reg_xor_sign    <= '0';
185
 
186
        div_counter     <= (others => '0');
187
        state           <= s_IDLE;
188
      else                                                -- << RISING EDGE OF CLK
189
        -- ############ FIRST INPUT ################
190
        if flags.input_en = '1' then
191
 
192
          reg_qot       <= a_input;
193
          reg_rem       <= (others => '0');
194
          reg_divisor   <= b_input;
195
 
196
          reg_sign_a    <= flag_a_neg and sign_flag;
197
          reg_xor_sign  <= (flag_a_neg xor flag_b_neg) and sign_flag;
198
 
199
        else
200
          -- ########## CALCULATION ################
201
          if flags.work_en = '1' then
202
            reg_qot     <= i_qot;
203
            reg_rem     <= i_rem;
204
          end if;
205
        end if;
206
 
207
        if flags.cnt_en = '1' then
208
          div_counter <= std_logic_vector(unsigned(div_counter) + to_unsigned(1, 5));
209
        else
210
          div_counter <= (others => '0');
211
        end if;
212
 
213
        state         <= i_state;                       -- always active
214
      end if;
215
    end if;
216
  end process;
217
 
218
  -- ___  ____ ___ ____ ___  ____ ___ _  _ 
219
  -- |  \ |__|  |  |__| |__] |__|  |  |__| 
220
  -- |__/ |  |  |  |  | |    |  |  |  |  | 
221
 
222
  i_sub <= std_logic_vector(unsigned('0' & reg_rem(30 downto 0) & reg_qot(31))        -- '0' for sign and shift dividend
223
                            -
224
                            unsigned('0' & reg_divisor));                             -- substract divisor
225
 
226
  i_qot <= reg_qot(30 downto 0) & (not i_sub(32));
227
  i_rem <= reg_rem(30 downto 0) & reg_qot(31) when i_sub(32) = '1' else i_sub(31 downto 0);
228
 
229
  -- ____ ____ _  _ ___ ____ ____ _    ___  ____ ___ _  _ 
230
  -- |    |  | |\ |  |  |__/ |  | |    |__] |__|  |  |__| 
231
  -- |___ |__| | \|  |  |  \ |__| |___ |    |  |  |  |  | 
232
  div_control:
233
  process( start, state, flags.cnt_done )
234
  begin
235
    -- ######## DEFAULT VALUES
236
    --
237
    -- intern flags
238
    --
239
    flags.input_en          <= '0';           -- no input
240
    flags.work_en           <= '0';           -- no calculation
241
    flags.cnt_en            <= '0';           -- no counting
242
 
243
    --
244
    -- state variable
245
    --
246
    i_state                 <= s_IDLE;        -- waiting for commands
247
 
248
    --
249
    -- outputs
250
    --
251
    busy                    <= '0';           -- no calculation indication
252
    rdy                     <= '0';           -- no result indication
253
 
254
    -- ######### CONTROL LOGIC
255
    case state is
256
      when s_IDLE   =>
257
 
258
        if start = '1' then
259
          busy              <= '1';
260
          flags.input_en    <= '1';
261
 
262
          i_state           <= s_INPUT;
263
        end if;
264
 
265
      when s_INPUT  =>                        -- write initial values
266
 
267
        busy                <= '1';
268
 
269
        flags.work_en       <= '1';           -- and start calculation
270
        flags.cnt_en        <= '1';
271
 
272
        i_state             <= s_WORK;
273
 
274
      when s_WORK   =>
275
 
276
        busy                <= '1';
277
 
278
        if flags.cnt_done = '1' then          -- finish calculation
279
          rdy               <= '1';
280
        else
281
          flags.work_en     <= '1';
282
          flags.cnt_en      <= '1';
283
 
284
          i_state           <= s_WORK;
285
        end if;
286
 
287
      when others   =>
288
    end case;
289
  end process;
290
 
291
  -- ____ ____ _  _ _  _ ___ ____ ____ 
292
  -- |    |  | |  | |\ |  |  |___ |__/ 
293
  -- |___ |__| |__| | \|  |  |___ |  \ 
294
  --
295
  -- get counter flag
296
  --
297
  flags.cnt_done  <= '1' when div_counter = "00000" else '0';
298
 
299
  -- ____ _  _ ___ ___  _  _ ___ 
300
  -- |  | |  |  |  |__] |  |  |  
301
  -- |__| |__|  |  |    |__|  |  
302
  --
303
  -- calculate twoscomplement of results
304
  --
305
  qot_convert     <= std_logic_vector(unsigned(not reg_qot) + to_unsigned(1, 32) );
306
  rem_convert     <= std_logic_vector(unsigned(not reg_rem) + to_unsigned(1, 32) );
307
 
308
  --
309
  -- result is negative for signed division and different signs of operands 
310
  -- remainder has the same sign as dividend
311
  --
312
  c               <= qot_convert when reg_xor_sign = '1' else reg_qot;
313
  r               <= rem_convert when reg_sign_a   = '1' else reg_rem;
314
 
315
 
316
end architecture structure_div_core;

powered by: WebSVN 2.1.0

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