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

Subversion Repositories plasma_fpu

[/] [plasma_fpu/] [trunk/] [src/] [cores/] [mul_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:       Multiplier core
5
-- AUTHOR:      Steve Rhoads (rhoadss@yahoo.com)
6
--              Alex Schoenberger (Alex.Schoenberger@ies.tu-darmstadt.de)
7
-- COMMENT:     bit-pair algorithm for multiplication
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:      mul_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
--        long64 answer = 0;
26
--        for(i = 0; i < 32; ++i)
27
--        {
28
--          answer = (answer >> 1) + (((b&1)?a:0) << 31);
29
--          b = b >> 1;
30
--        }
31
--
32
--    SYNTHESIZABLE
33
--
34
----------------------------------------------------------------------------
35
-- Revision History
36
-- --------------------------------------------------------------------------
37
-- Revision   Date    Author     CHANGES
38
-- 1.0      7/2014    AS         initial
39
-- --------------------------------------------------------------------------
40
library IEEE;
41
  use IEEE.std_logic_1164.ALL;
42
  use IEEE.numeric_std.ALL;
43
 
44
entity mul_core is
45
  port(
46
    clk               : in  std_logic;
47
    rst               : in  std_logic;
48
 
49
    start             : in  std_logic;
50
    busy              : out std_logic;
51
    rdy               : out std_logic;
52
 
53
    sign_flag         : in  std_logic;
54
 
55
    a                 : in  std_logic_vector(31 downto 0);
56
    b                 : in  std_logic_vector(31 downto 0);
57
 
58
    c                 : out std_logic_vector(63 downto 0)
59
  );
60
end entity mul_core;
61
 
62
 
63
--           _____   _____ _    _ _____ _______ ______ _____ _______ _    _ _____  ______ 
64
--     /\   |  __ \ / ____| |  | |_   _|__   __|  ____/ ____|__   __| |  | |  __ \|  ____|
65
--    /  \  | |__) | |    | |__| | | |    | |  | |__ | |       | |  | |  | | |__) | |__   
66
--   / /\ \ |  _  /| |    |  __  | | |    | |  |  __|| |       | |  | |  | |  _  /|  __|  
67
--  / ____ \| | \ \| |____| |  | |_| |_   | |  | |___| |____   | |  | |__| | | \ \| |____ 
68
-- /_/    \_\_|  \_\\_____|_|  |_|_____|  |_|  |______\_____|  |_|   \____/|_|  \_\______|
69
architecture mul_core_structure of mul_core is
70
  -- _ _  _ ___  _  _ ___ 
71
  -- | |\ | |__] |  |  |  
72
  -- | | \| |    |__|  |  
73
  alias flag_b_neg              : std_logic is b(31);              -- operand B is negative
74
 
75
  signal a_convert              : std_logic_vector(31 downto 0);   -- twoscomplement of operand A
76
  signal b_convert              : std_logic_vector(31 downto 0);   -- twoscomplement of operand B  
77
 
78
  signal a_input                : std_logic_vector(31 downto 0);   -- final input of operand A
79
  signal b_input                : std_logic_vector(31 downto 0);   -- final input of operand B
80
  signal i_input                : std_logic_vector(31 downto 0);   -- first intermediate result
81
 
82
  -- ____ ____ ____ _ ____ ___ ____ ____ ____ 
83
  -- |__/ |___ | __ | [__   |  |___ |__/ [__  
84
  -- |  \ |___ |__] | ___]  |  |___ |  \ ___]
85
  signal i_lower, reg_lower     : std_logic_vector(31 downto 0);
86
  signal i_upper, reg_upper     : std_logic_vector(31 downto 0);
87
  signal reg_adder              : std_logic_vector(31 downto 0);
88
 
89
  signal reg_sign               : std_logic;
90
 
91
  -- ___  ____ ___ ____ ___  ____ ___ _  _ 
92
  -- |  \ |__|  |  |__| |__] |__|  |  |__| 
93
  -- |__/ |  |  |  |  | |    |  |  |  |  | 
94
  signal i_sum_in               : std_logic_vector(31 downto 0);   -- input of summary
95
  signal i_sum                  : std_logic_vector(32 downto 0);   -- intermediate sum, extended with carry
96
 
97
  alias  sum_en                 : std_logic is reg_lower(0);       -- enable summary if current LSB is '1'
98
  alias  a_msb                  : std_logic is reg_upper(31);      -- for signed multiplication detect leading ones
99
  alias  b_msb                  : std_logic is i_sum_in(31);       -- for signed multiplication
100
 
101
  -- ____ ____ _  _ ___ ____ ____ _    ___  ____ ___ _  _ 
102
  -- |    |  | |\ |  |  |__/ |  | |    |__] |__|  |  |__| 
103
  -- |___ |__| | \|  |  |  \ |__| |___ |    |  |  |  |  | 
104
  type t_mul_state               is ( s_IDLE, s_WORK );
105
 
106
  signal i_state, state         : t_mul_state;                     -- state variable
107
 
108
  type t_mul_flags is
109
    record
110
      input_en                  : std_logic;
111
      work_en                   : std_logic;
112
      cnt_en                    : std_logic;
113
      cnt_done                  : std_logic;
114
    end record;
115
 
116
  signal flags                  : t_mul_flags;                     -- internal flags
117
 
118
  -- ____ ____ _  _ _  _ ___ ____ ____ 
119
  -- |    |  | |  | |\ |  |  |___ |__/ 
120
  -- |___ |__| |__| | \|  |  |___ |  \   
121
  signal mul_counter            : std_logic_vector(4 downto 0);      -- 2**5 = 32 clock cycles for multiplication
122
 
123
begin
124
-- synthesis translate_off
125
  -- ____ ____ _  _ _ ___ _   _    ____ _  _ ____ ____ _  _ 
126
  -- [__  |__| |\ | |  |   \_/     |    |__| |___ |    |_/  
127
  -- ___] |  | | \| |  |    |      |___ |  | |___ |___ | \_ 
128
  sanity_process:process( a, b )
129
  begin
130
    assert (not((a = x"8000_0000") and (sign_flag = '1'))) report "WARNING: operand A of MUL-CORE is 0x8000_0000, result will be erroneous!" severity warning;
131
    assert (not((b = x"8000_0000") and (sign_flag = '1'))) report "WARNING: operand B of MUL-CORE is 0x8000_0000, result will be erroneous!" severity warning;
132
  end process;
133
-- synthesis translate_on
134
 
135
  -- _ _  _ ___  _  _ ___ 
136
  -- | |\ | |__] |  |  |  
137
  -- | | \| |    |__|  |  
138
  --
139
  -- calculate twoscomplement
140
  --
141
  a_convert <= std_logic_vector( unsigned(not a) + to_unsigned(1, 32) );
142
  b_convert <= std_logic_vector( unsigned(not b) + to_unsigned(1, 32) );
143
 
144
  --
145
  -- for signed multiplication and negative operand B take twoscomplements
146
  --
147
  a_input   <= a_convert when (flag_b_neg and sign_flag) = '1' else a;
148
  b_input   <= b_convert when (flag_b_neg and sign_flag) = '1' else b;
149
 
150
  --
151
  -- if LSB of operand B is '1' the first intermediate result is operand A
152
  --
153
  i_input <= a_input      when b_input(0) = '1' else (others => '0');
154
 
155
  -- ____ ____ ____ _ ____ ___ ____ ____ ____ 
156
  -- |__/ |___ | __ | [__   |  |___ |__/ [__  
157
  -- |  \ |___ |__] | ___]  |  |___ |  \ ___]
158
  --
159
  -- reg_upper & reg_lower compose result
160
  -- reg_adder contain (to shift) adder constant
161
  -- reg_sign indicates signed multiplication
162
  --
163
  -- counter value and state variable
164
  --
165
  mul_registers:
166
  process( clk )
167
  begin
168
    if rising_edge( clk ) then
169
      if rst = '1' then                                   -- << RESET ACTIVE
170
        reg_lower     <= (others => '0');
171
        reg_upper     <= (others => '0');
172
        reg_adder     <= (others => '0');
173
 
174
        reg_sign      <= '0';
175
 
176
        mul_counter   <= (others => '0');
177
        state         <= s_IDLE;
178
      else                                                -- << RISING EDGE OF CLK
179
        -- ############ FIRST INPUT ################
180
        if flags.input_en = '1' then
181
          reg_sign    <= sign_flag;
182
 
183
          reg_adder   <= a_input;
184
          reg_lower   <= i_input(0) & b_input(31 downto 1);                   -- shift first intermediate result
185
          reg_upper   <= (sign_flag and i_input(31)) & i_input(31 downto 1);
186
 
187
        else
188
          -- ########## CALCULATION ################
189
          if flags.work_en = '1' then
190
            reg_lower <= i_lower;
191
            reg_upper <= i_upper;
192
          end if;
193
        end if;
194
 
195
        if flags.cnt_en = '1' then
196
          mul_counter <= std_logic_vector(unsigned(mul_counter) + to_unsigned(1, 5));
197
        else
198
          mul_counter <= (others => '0');
199
        end if;
200
 
201
        state         <= i_state;                       -- always active
202
      end if;
203
    end if;
204
  end process;
205
 
206
  -- ___  ____ ___ ____ ___  ____ ___ _  _ 
207
  -- |  \ |__|  |  |__| |__] |__|  |  |__| 
208
  -- |__/ |  |  |  |  | |    |  |  |  |  | 
209
  --
210
  -- get intermediate summand
211
  --
212
  i_sum_in <= reg_adder when sum_en = '1' else (others => '0');
213
 
214
  --
215
  --  calculate intermediate sum
216
  --
217
  i_sum <= std_logic_vector( unsigned((reg_sign and a_msb) & reg_upper)      -- for signed multiplication extend with MSB of reg upper
218
                              +
219
                             unsigned((reg_sign and b_msb) & i_sum_in) );    -- for signed multiplication extend with MSB of i_sum_in
220
 
221
  --
222
  -- shift intermediate result
223
  --
224
  i_upper <= i_sum(32 downto 1);                                              -- get upper bits
225
  i_lower <= i_sum(0) & reg_lower(31 downto 1);                               -- get LSB and shift lower bits
226
 
227
  -- ____ ____ _  _ ___ ____ ____ _    ___  ____ ___ _  _ 
228
  -- |    |  | |\ |  |  |__/ |  | |    |__] |__|  |  |__| 
229
  -- |___ |__| | \|  |  |  \ |__| |___ |    |  |  |  |  | 
230
  mul_control:
231
  process( start, state, flags.cnt_done )
232
  begin
233
    -- ######## DEFAULT VALUES
234
    --
235
    -- intern flags
236
    --
237
    flags.input_en          <= '0';           -- no input
238
    flags.work_en           <= '0';           -- no calculation
239
    flags.cnt_en            <= '0';           -- no counting
240
 
241
    --
242
    -- state variable
243
    --
244
    i_state                 <= s_IDLE;        -- waiting for commands
245
 
246
    --
247
    -- outputs
248
    --
249
    busy                    <= '0';           -- no calculation indication
250
    rdy                     <= '0';           -- no result indication
251
 
252
    -- ######### CONTROL LOGIC
253
    case state is
254
      when s_IDLE   =>
255
 
256
        if start = '1' then
257
          busy              <= '1';
258
          flags.input_en    <= '1';
259
          flags.cnt_en      <= '1';
260
 
261
          i_state           <= s_WORK;
262
        end if;
263
 
264
      when s_WORK   =>
265
 
266
        busy                <= '1';
267
 
268
        if flags.cnt_done = '1' then          -- finish calculation
269
          rdy               <= '1';
270
        else
271
          flags.work_en     <= '1';
272
          flags.cnt_en      <= '1';
273
 
274
          i_state           <= s_WORK;
275
        end if;
276
 
277
      when others   =>
278
    end case;
279
  end process;
280
 
281
  -- ____ ____ _  _ _  _ ___ ____ ____ 
282
  -- |    |  | |  | |\ |  |  |___ |__/ 
283
  -- |___ |__| |__| | \|  |  |___ |  \ 
284
  --
285
  -- get counter flag
286
  --
287
  flags.cnt_done  <= '1' when mul_counter = "00000" else '0';
288
 
289
  -- ____ _  _ ___ ___  _  _ ___ 
290
  -- |  | |  |  |  |__] |  |  |  
291
  -- |__| |__|  |  |    |__|  |  
292
  c               <= reg_upper & reg_lower;
293
 
294
end architecture mul_core_structure;

powered by: WebSVN 2.1.0

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