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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [mulu32_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      : mulu32_S2.vhd
9
--
10
--  Entity name    : umul32
11
--
12
--  Purpose        : Implements a 32 bit x 32 bit unsigned 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
--
80
 
81
library ieee;
82
  use ieee.std_logic_1164.all;
83
  use ieee.std_logic_unsigned.all;
84
--library unisim;
85
--  use unisim.vcomponents.all;
86
 
87
entity umul32 is
88
        port (
89
         clk       : in  std_logic;
90
    rst       : in  std_logic;
91
    cs        : in  std_logic;
92
    rw        : in  std_logic;
93
    addr      : in  std_logic_vector(3 downto 0);
94
    data_in   : in  std_logic_vector(7 downto 0);
95
         data_out  : out std_logic_vector(7 downto 0);
96
         hold      : out std_logic
97
         );
98
end entity;
99
 
100
architecture rtl of umul32 is
101
 
102
--
103
-- registers
104
--
105
signal multiplicand : std_logic_vector(31 downto 0) := (others=>'0');
106
signal multiplier   : std_logic_vector(31 downto 0) := (others=>'0');
107
signal result       : std_logic_vector(64 downto 0) := (others=>'0');
108
 
109
signal multiplier_temp  : std_logic_vector(31 downto 0) := (others=>'0');
110
 
111
signal count        : std_logic_vector(4 downto 0); -- bit counter
112
signal req_flag     : std_logic := '0';
113
signal act_flag     : std_logic := '0';
114
 
115
begin
116
 
117
---------------------------------
118
--
119
-- Write Multiplier Registers
120
--
121
---------------------------------
122
 
123
umul32_write : process( clk, rst, cs, rw, addr, data_in, act_flag, req_flag )
124
begin
125
  if rst = '1' then
126
    multiplicand <= (others => '0');
127
    multiplier   <= (others => '0');
128
    req_flag   <= '0';
129
  elsif falling_edge( clk ) then
130
    if (cs = '1') and (rw = '0') then
131
      case addr is
132
           when "0000" =>
133
                  multiplicand(31 downto 24) <= data_in;
134
           when "0001" =>
135
                  multiplicand(23 downto 16) <= data_in;
136
           when "0010" =>
137
                  multiplicand(15 downto  8) <= data_in;
138
           when "0011" =>
139
                  multiplicand( 7 downto  0) <= data_in;
140
           when "0100" =>
141
                  multiplier(31 downto 24) <= data_in;
142
           when "0101" =>
143
                  multiplier(23 downto 16) <= data_in;
144
           when "0110" =>
145
                  multiplier(15 downto  8) <= data_in;
146
           when "0111" =>
147
        multiplier( 7 downto  0) <= data_in;
148
                  if (act_flag = '0') and (req_flag <= '0') then
149
                    req_flag <= '1';
150
                  end if;
151
      when others =>
152
        null;
153
                end case;
154
         end if; -- cs
155
         if (act_flag = '1') and (req_flag = '1') then
156
           req_flag <= '0';
157
    end if;
158
    hold <= cs and rw and addr(3) and act_flag;
159
  end if; -- rst/clk
160
end process;
161
 
162
---------------------------------
163
--
164
-- Read Multiplier Registers
165
--
166
---------------------------------
167
 
168
umul32_read : process( addr, multiplicand, multiplier, result )
169
begin
170
  case addr is
171
  when "0000" =>
172
         data_out <= multiplicand(31 downto 24);
173
  when "0001" =>
174
    data_out <= multiplicand(23 downto 16);
175
  when "0010" =>
176
    data_out <= multiplicand(15 downto  8);
177
  when "0011" =>
178
    data_out <= multiplicand( 7 downto  0);
179
  when "0100" =>
180
    data_out <= multiplier(31 downto 24);
181
  when "0101" =>
182
    data_out <= multiplier(23 downto 16);
183
  when "0110" =>
184
    data_out <= multiplier(15 downto  8);
185
  when "0111" =>
186
    data_out <= multiplier( 7 downto  0);
187
  when "1000" =>
188
    data_out <= result(63 downto 56);
189
  when "1001" =>
190
    data_out <= result(55 downto 48);
191
  when "1010" =>
192
    data_out <= result(47 downto 40);
193
  when "1011" =>
194
    data_out <= result(39 downto 32);
195
  when "1100" =>
196
    data_out <= result(31 downto 24);
197
  when "1101" =>
198
    data_out <= result(23 downto 16);
199
  when "1110" =>
200
    data_out <= result(15 downto  8);
201
  when "1111" =>
202
    data_out <= result( 7 downto  0);
203
  when others =>
204
    null;
205
  end case;
206
 
207
end process;
208
 
209
---------------------------------
210
--
211
-- Perform 32 x 32 multiply
212
--
213
---------------------------------
214
--
215
-- When the active flag is clear and the request flag goes high, 
216
-- start the multiplication by setting the active flag
217
-- When the active flag is high and the count reaches 31
218
-- reset the active flag
219
-- 
220
umul32_multiply : process( rst, clk, req_flag, act_flag )
221
variable result_temp : std_logic_vector(32 downto 0);
222
begin
223
  if (rst = '1') then
224
    multiplier_temp <= (others=>'0');
225
    result          <= (others=>'0');
226
    count           <= (others=>'0');
227
    act_flag        <= '0';             -- default state is inactive
228
  elsif falling_edge( clk ) then
229
      --
230
      -- start the division if the last division was complete
231
                -- i.e. the active flag was clear
232
      -- and the last byte of the divisor was just written
233
      -- i.e. the request flag was pulsed high for one clock cycle
234
                --
235
      if (req_flag = '1') and (act_flag = '0') then
236
        multiplier_temp <= multiplier;       -- Get Multiplier into temp
237
        result          <= (others => '0');  -- Clear the result
238
        count           <= (others => '0');  -- Zero the bit counter
239
        act_flag        <= '1';              -- Flag multiplication in progress
240
 
241
      elsif ( req_flag = '0' ) and (act_flag = '1') then  -- if active flag is set the multiplication must be in progress
242
 
243
        result_temp(32 downto 0) := "0" & result(63 downto 32);
244
        if multiplier_temp(0) = '1' then                            -- if least significant bit of multiplier is set
245
          result_temp(32 downto 0) := ("0" & result(63 downto 32)) + ("0" & multiplicand);    -- add the multiplicand to the msbits of the result
246
        end if;
247
 
248
        --
249
        -- shift the result down one bit
250
        --
251
                  result(30 downto  0) <= result(31 downto 1);
252
        result(63 downto 31) <= result_temp(32 downto 0);
253
 
254
                  --
255
        -- shift multiplier temp down one bit
256
        --
257
        multiplier_temp(30 downto 0) <= multiplier_temp(31 downto 1);
258
                  multiplier_temp(31) <= '0';
259
        --
260
        -- 32 bit multiplication should take 32 clock cycles
261
        --
262
        count               <= count + "00001";
263
        --
264
                  -- When the count reaches the 31st cycle of the division 
265
        -- flag that the multiplication is complete by setting the finish flag.
266
        -- 
267
        if count = "11111" then
268
          act_flag <= '0';  -- flag Multiplication complete
269
        end if;
270
 
271
      end if; -- start/finish
272
  end if; -- rst/clk
273
end process;
274
 
275
end rtl;
276
 

powered by: WebSVN 2.1.0

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