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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [muls32_s2.vhd] - Rev 138

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

powered by: WebSVN 2.1.0

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