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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [muls32_s2.vhd] - Blame information for rev 130

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 130 dilbert57
--===========================================================================--
2
--                                                                           --
3
--  umul32.vhd - Synthesizable 32 bit unsigned integer multiplier            --
4
--               For FPGAs without hardware multiplier blocks                --
5
--                                                                           --
6
--===========================================================================--
7
--
8
--  File name      : muls32_S2.vhd
9
--
10
--  Entity name    : smul32
11
--
12
--  Purpose        : Implements a 32 bit x 32 bit signed integer multiplier
13
--                   Produces 64 bit result. 
14
--                   Consists of 16 x 8 bit registers.
15
--                   4 x 8bit read/write registers for 32 bit multiplicand.
16
--                   4 x 8bit read/write registers for 32 bit multiplier.
17
--                   8 x 8bit read only register for 64 bit result.
18
--                   There is no control or status register.
19
--                   Must wait 32 clock cycles for result after writing LSByte of multiplier
20
--                   Designed for FPGAs which don't have hardware multiplier blocks 
21
--                   such as Spartan 2/2E (which are no longer supported by current Xilinx software)
22
--
23
--  Dependencies   : ieee.std_logic_1164
24
--                   ieee.std_logic_unsigned
25
--                   unisim.vcomponents
26
--
27
--  Author         : John E. Kent
28
--
29
--  Email          : dilbert57@opencores.org      
30
--
31
--  Web            : http://opencores.org/project,system09
32
--
33
--  Registers      :
34
-- 
35
--   0 R/W multiplicand input  Most Significant Byte
36
--   1 R/W multiplicand input
37
--   2 R/W multiplicand input
38
--   3 R/W multiplicand input  Least Significant Byte
39
--   4 R/W multiplier   input  Most Significant Byte
40
--   5 R/W multiplier   input
41
--   6 R/W multiplier   input
42
--   7 R/W multiplier   input  Least Significant Byte
43
--   8 R/O result       output Most Significant Byte
44
--   9 R/O result       output 
45
--  10 R/O result       output 
46
--  11 R/O result       output 
47
--  12 R/O result       output 
48
--  13 R/O result       output 
49
--  14 R/O result       output 
50
--  15 R/O result       output Least Significant Byte
51
--
52
--  Copyright (C) 2010 - 2012 John Kent
53
--
54
--  This program is free software: you can redistribute it and/or modify
55
--  it under the terms of the GNU General Public License as published by
56
--  the Free Software Foundation, either version 3 of the License, or
57
--  (at your option) any later version.
58
--
59
--  This program is distributed in the hope that it will be useful,
60
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
61
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
62
--  GNU General Public License for more details.
63
--
64
--  You should have received a copy of the GNU General Public License
65
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
66
--
67
--===========================================================================--
68
--                                                                           --
69
--                              Revision  History                            --
70
--                                                                           --
71
--===========================================================================--
72
--
73
-- Version  Author        Date         Description
74
--
75
-- 0.1      John Kent     2008-09-07   Initial version
76
-- 0.2      John Kent     2010-06-17   Header & GPL added
77
-- 0.3      John Kent     2012-04-06   converted into umul32
78
-- 0.4      John Kent     2016-02-04   Version without hardware multiply
79
-- 0.5      John Kent     2018-03-21   converted into smul32
80
--
81
 
82
library ieee;
83
  use ieee.std_logic_1164.all;
84
  use ieee.std_logic_unsigned.all;
85
--library unisim;
86
--  use unisim.vcomponents.all;
87
 
88
entity smul32 is
89
        port (
90
         clk       : in  std_logic;
91
    rst       : in  std_logic;
92
    cs        : in  std_logic;
93
    rw        : in  std_logic;
94
    addr      : in  std_logic_vector(3 downto 0);
95
    data_in   : in  std_logic_vector(7 downto 0);
96
         data_out  : out std_logic_vector(7 downto 0);
97
         hold      : out std_logic
98
         );
99
end entity;
100
 
101
architecture rtl of smul32 is
102
 
103
--
104
-- registers
105
--
106
signal multiplicand : std_logic_vector(31 downto 0) := (others=>'0');
107
signal multiplier   : std_logic_vector(31 downto 0) := (others=>'0');
108
signal result       : std_logic_vector(64 downto 0) := (others=>'0');
109
 
110
signal multiplier_temp : std_logic_vector(31 downto 0) := (others=>'0');
111
 
112
signal count        : std_logic_vector(4 downto 0); -- bit counter
113
signal req_flag     : std_logic := '0';
114
signal act_flag     : std_logic := '0';
115
 
116
begin
117
 
118
---------------------------------
119
--
120
-- Write Multiplier Registers
121
--
122
---------------------------------
123
 
124
smul32_write : process( clk, rst, cs, rw, addr, data_in, req_flag, act_flag )
125
begin
126
  if rst = '1' then
127
    multiplicand <= (others => '0');
128
    multiplier   <= (others => '0');
129
    req_flag     <= '0';
130
  elsif falling_edge( clk ) then
131
    if (cs = '1') and (rw = '0') then
132
      case addr is
133
           when "0000" =>
134
                  multiplicand(31 downto 24) <= data_in;
135
           when "0001" =>
136
                  multiplicand(23 downto 16) <= data_in;
137
           when "0010" =>
138
                  multiplicand(15 downto  8) <= data_in;
139
           when "0011" =>
140
                  multiplicand( 7 downto  0) <= data_in;
141
           when "0100" =>
142
                  multiplier(31 downto 24) <= data_in;
143
           when "0101" =>
144
                  multiplier(23 downto 16) <= data_in;
145
           when "0110" =>
146
                  multiplier(15 downto  8) <= data_in;
147
           when "0111" =>
148
        multiplier( 7 downto  0) <= data_in;
149
                  if (req_flag = '0') and (act_flag = '0') then
150
                    req_flag <= '1';
151
                  end if;
152
      when others =>
153
        null;
154
                end case;
155
         end if; -- clk
156
    if (req_flag = '1') and (act_flag = '1') then
157
      req_flag <= '0';
158
    end if;
159
    hold <= cs and rw and addr(3) and act_flag;
160
  end if; -- rst
161
end process;
162
 
163
---------------------------------
164
--
165
-- Read Multiplier Registers
166
--
167
---------------------------------
168
 
169
smul32_read : process( addr, multiplicand, multiplier, result )
170
begin
171
  case addr is
172
  when "0000" =>
173
         data_out <= multiplicand(31 downto 24);
174
  when "0001" =>
175
    data_out <= multiplicand(23 downto 16);
176
  when "0010" =>
177
    data_out <= multiplicand(15 downto  8);
178
  when "0011" =>
179
    data_out <= multiplicand( 7 downto  0);
180
  when "0100" =>
181
    data_out <= multiplier(31 downto 24);
182
  when "0101" =>
183
    data_out <= multiplier(23 downto 16);
184
  when "0110" =>
185
    data_out <= multiplier(15 downto  8);
186
  when "0111" =>
187
    data_out <= multiplier( 7 downto  0);
188
  when "1000" =>
189
    data_out <= result(63 downto 56);
190
  when "1001" =>
191
    data_out <= result(55 downto 48);
192
  when "1010" =>
193
    data_out <= result(47 downto 40);
194
  when "1011" =>
195
    data_out <= result(39 downto 32);
196
  when "1100" =>
197
    data_out <= result(31 downto 24);
198
  when "1101" =>
199
    data_out <= result(23 downto 16);
200
  when "1110" =>
201
    data_out <= result(15 downto  8);
202
  when "1111" =>
203
    data_out <= result( 7 downto  0);
204
  when others =>
205
    null;
206
  end case;
207
 
208
end process;
209
 
210
---------------------------------
211
--
212
-- Perform 32 x 32 multiply
213
--
214
---------------------------------
215
--
216
-- When the active flag is clear and the request flag goes high, 
217
-- start the multiplication by setting the active flag
218
-- When the active flag is high and the count reaches 31
219
-- reset the active flag
220
-- 
221
smul32_multiply : process( rst, clk, req_flag, act_flag )
222
variable result_temp  : std_logic_vector(32 downto 0);
223
begin
224
  if (rst = '1') then
225
    multiplier_temp <= (others=>'0');
226
    result          <= (others=>'0');
227
    count           <= (others=>'0');
228
    act_flag        <= '0';             -- default state is inactive
229
  elsif falling_edge( clk ) then
230
      --
231
      -- start the division if the last division was complete
232
                -- i.e. the active flag was clear
233
      -- and the last byte of the divisor was just written
234
      -- i.e. the request flag was pulsed high for one clock cycle
235
                --
236
      if (req_flag = '1') and (act_flag = '0') then
237
        if multiplier(31) = '0' then
238
           multiplier_temp(31 downto 0) <= multiplier(31 downto 0);    -- Get Multiplier into temp
239
        else
240
           multiplier_temp(31 downto 0) <= "00000000000000000000000000000000" - multiplier(31 downto 0);
241
        end if;
242
        result                       <= (others => '0');            -- Clear the result
243
        count                        <= (others => '0');            -- Zero the bit counter
244
        act_flag                     <= '1';                        -- Flag that the multiplication is in progress
245
 
246
      elsif (req_flag = '0') and ( act_flag = '1' ) then                                 -- if active flag is set the multiplication must be in progress
247
 
248
        result_temp := (result(63) & result(63 downto 32));
249
        if multiplier_temp(0) = '1' then
250
          if multiplier(31) = '0' then                                      -- if most significant bit of multiplicand is clear
251
            result_temp := (result(63) & result(63 downto 32)) + (multiplicand(31) & multiplicand); -- add the multiplicand to the msbits of the result
252
          else
253
            result_temp := (result(63) & result(63 downto 32)) - (multiplicand(31) & multiplicand); -- otherwise subtract the multiplicand from the msbits of the result
254
          end if;
255
        end if;
256
 
257
        --
258
        -- shift the result down one bit
259
        -- leave sign bit of result
260
                  --
261
                  result(30 downto  0) <= result(31 downto 1);
262
        result(63 downto 31) <= result_temp(32 downto 0);
263
 
264
                  --
265
        -- shift multiplier temp down one bit
266
        -- extend sign bit of multiplier temp
267
        --
268
        multiplier_temp(30 downto 0) <= multiplier_temp(31 downto 1);
269
 
270
        --
271
        -- 32 bit multiplication should take 32 clock cycles
272
        --
273
        count               <= count + "00001";
274
        --
275
                  -- When the count reaches the 31st cycle of the division 
276
        -- flag that the multiplication is complete by setting the finish flag.
277
        -- 
278
        if count = "11111" then
279
          act_flag <= '0';  -- flag Multiplication complete
280
        end if;
281
 
282
      end if; -- start/finish
283
  end if; -- rst/clk
284
end process;
285
 
286
end rtl;
287
 

powered by: WebSVN 2.1.0

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