URL
https://opencores.org/ocsvn/System09/System09/trunk
Subversion Repositories System09
[/] [System09/] [trunk/] [rtl/] [VHDL/] [muls32_s2.vhd] - Rev 209
Go to most recent revision | Compare with Previous | Blame | View Log
--===========================================================================-- -- -- -- umul32.vhd - Synthesizable 32 bit unsigned integer multiplier -- -- For FPGAs without hardware multiplier blocks -- -- -- --===========================================================================-- -- -- File name : muls32_S2.vhd -- -- Entity name : smul32 -- -- Purpose : Implements a 32 bit x 32 bit signed integer multiplier -- Produces 64 bit result. -- Consists of 16 x 8 bit registers. -- 4 x 8bit read/write registers for 32 bit multiplicand. -- 4 x 8bit read/write registers for 32 bit multiplier. -- 8 x 8bit read only register for 64 bit result. -- There is no control or status register. -- Must wait 32 clock cycles for result after writing LSByte of multiplier -- Designed for FPGAs which don't have hardware multiplier blocks -- such as Spartan 2/2E (which are no longer supported by current Xilinx software) -- -- Dependencies : ieee.std_logic_1164 -- ieee.std_logic_unsigned -- unisim.vcomponents -- -- Author : John E. Kent -- -- Email : dilbert57@opencores.org -- -- Web : http://opencores.org/project,system09 -- -- Registers : -- -- 0 R/W multiplicand input Most Significant Byte -- 1 R/W multiplicand input -- 2 R/W multiplicand input -- 3 R/W multiplicand input Least Significant Byte -- 4 R/W multiplier input Most Significant Byte -- 5 R/W multiplier input -- 6 R/W multiplier input -- 7 R/W multiplier input Least Significant Byte -- 8 R/O result output Most Significant Byte -- 9 R/O result output -- 10 R/O result output -- 11 R/O result output -- 12 R/O result output -- 13 R/O result output -- 14 R/O result output -- 15 R/O result output Least Significant Byte -- -- Copyright (C) 2010 - 2012 John Kent -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- --===========================================================================-- -- -- -- Revision History -- -- -- --===========================================================================-- -- -- Version Author Date Description -- -- 0.1 John Kent 2008-09-07 Initial version -- 0.2 John Kent 2010-06-17 Header & GPL added -- 0.3 John Kent 2012-04-06 converted into umul32 -- 0.4 John Kent 2016-02-04 Version without hardware multiply -- 0.5 John Kent 2018-03-21 converted into smul32 -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; --library unisim; -- use unisim.vcomponents.all; entity smul32 is port ( clk : in std_logic; rst : in std_logic; cs : in std_logic; rw : in std_logic; addr : in std_logic_vector(3 downto 0); data_in : in std_logic_vector(7 downto 0); data_out : out std_logic_vector(7 downto 0); hold : out std_logic ); end entity; architecture rtl of smul32 is -- -- registers -- signal multiplicand : std_logic_vector(31 downto 0) := (others=>'0'); signal multiplier : std_logic_vector(31 downto 0) := (others=>'0'); signal result : std_logic_vector(64 downto 0) := (others=>'0'); signal multiplier_temp : std_logic_vector(31 downto 0) := (others=>'0'); signal count : std_logic_vector(4 downto 0); -- bit counter signal req_flag : std_logic := '0'; signal act_flag : std_logic := '0'; begin --------------------------------- -- -- Write Multiplier Registers -- --------------------------------- smul32_write : process( clk, rst, cs, rw, addr, data_in, req_flag, act_flag ) begin if rst = '1' then multiplicand <= (others => '0'); multiplier <= (others => '0'); req_flag <= '0'; elsif falling_edge( clk ) then if (cs = '1') and (rw = '0') then case addr is when "0000" => multiplicand(31 downto 24) <= data_in; when "0001" => multiplicand(23 downto 16) <= data_in; when "0010" => multiplicand(15 downto 8) <= data_in; when "0011" => multiplicand( 7 downto 0) <= data_in; when "0100" => multiplier(31 downto 24) <= data_in; when "0101" => multiplier(23 downto 16) <= data_in; when "0110" => multiplier(15 downto 8) <= data_in; when "0111" => multiplier( 7 downto 0) <= data_in; if (req_flag = '0') and (act_flag = '0') then req_flag <= '1'; end if; when others => null; end case; end if; -- clk if (req_flag = '1') and (act_flag = '1') then req_flag <= '0'; end if; hold <= cs and rw and addr(3) and act_flag; end if; -- rst end process; --------------------------------- -- -- Read Multiplier Registers -- --------------------------------- smul32_read : process( addr, multiplicand, multiplier, result ) begin case addr is when "0000" => data_out <= multiplicand(31 downto 24); when "0001" => data_out <= multiplicand(23 downto 16); when "0010" => data_out <= multiplicand(15 downto 8); when "0011" => data_out <= multiplicand( 7 downto 0); when "0100" => data_out <= multiplier(31 downto 24); when "0101" => data_out <= multiplier(23 downto 16); when "0110" => data_out <= multiplier(15 downto 8); when "0111" => data_out <= multiplier( 7 downto 0); when "1000" => data_out <= result(63 downto 56); when "1001" => data_out <= result(55 downto 48); when "1010" => data_out <= result(47 downto 40); when "1011" => data_out <= result(39 downto 32); when "1100" => data_out <= result(31 downto 24); when "1101" => data_out <= result(23 downto 16); when "1110" => data_out <= result(15 downto 8); when "1111" => data_out <= result( 7 downto 0); when others => null; end case; end process; --------------------------------- -- -- Perform 32 x 32 multiply -- --------------------------------- -- -- When the active flag is clear and the request flag goes high, -- start the multiplication by setting the active flag -- When the active flag is high and the count reaches 31 -- reset the active flag -- smul32_multiply : process( rst, clk, req_flag, act_flag ) variable result_temp : std_logic_vector(32 downto 0); begin if (rst = '1') then multiplier_temp <= (others=>'0'); result <= (others=>'0'); count <= (others=>'0'); act_flag <= '0'; -- default state is inactive elsif falling_edge( clk ) then -- -- start the division if the last division was complete -- i.e. the active flag was clear -- and the last byte of the divisor was just written -- i.e. the request flag was pulsed high for one clock cycle -- if (req_flag = '1') and (act_flag = '0') then if multiplier(31) = '0' then multiplier_temp(31 downto 0) <= multiplier(31 downto 0); -- Get Multiplier into temp else multiplier_temp(31 downto 0) <= "00000000000000000000000000000000" - multiplier(31 downto 0); end if; result <= (others => '0'); -- Clear the result count <= (others => '0'); -- Zero the bit counter act_flag <= '1'; -- Flag that the multiplication is in progress elsif (req_flag = '0') and ( act_flag = '1' ) then -- if active flag is set the multiplication must be in progress result_temp := (result(63) & result(63 downto 32)); if multiplier_temp(0) = '1' then if multiplier(31) = '0' then -- if most significant bit of multiplicand is clear result_temp := (result(63) & result(63 downto 32)) + (multiplicand(31) & multiplicand); -- add the multiplicand to the msbits of the result else result_temp := (result(63) & result(63 downto 32)) - (multiplicand(31) & multiplicand); -- otherwise subtract the multiplicand from the msbits of the result end if; end if; -- -- shift the result down one bit -- leave sign bit of result -- result(30 downto 0) <= result(31 downto 1); result(63 downto 31) <= result_temp(32 downto 0); -- -- shift multiplier temp down one bit -- extend sign bit of multiplier temp -- multiplier_temp(30 downto 0) <= multiplier_temp(31 downto 1); -- -- 32 bit multiplication should take 32 clock cycles -- count <= count + "00001"; -- -- When the count reaches the 31st cycle of the division -- flag that the multiplication is complete by setting the finish flag. -- if count = "11111" then act_flag <= '0'; -- flag Multiplication complete end if; end if; -- start/finish end if; -- rst/clk end process; end rtl;
Go to most recent revision | Compare with Previous | Blame | View Log