library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

-- This file is a hack to quickly incorporate signed division into our design.
-- It divides the absolute values of the signals and determines the sign for the result.

entity signed_divide is
  port (
    X: in STD_LOGIC_VECTOR(31 downto 0);
    Y: in STD_LOGIC_VECTOR(31 downto 0);

    Z: out STD_LOGIC_VECTOR(31 downto 0);
    V: out STD_LOGIC);
end signed_divide;

-- X: 16.16
-- Y: 16.16
-- Z = X/Y: 16.16
-- V: Overflow Bit

architecture signed_divide_arch of signed_divide is
  constant ZERO31: SIGNED(30 downto 0) := "0000000000000000000000000000000";
  constant ONE31: SIGNED(30 downto 0) := "0000000000000000000000000000001";
  constant ZERO32: SIGNED(31 downto 0) := "00000000000000000000000000000000";

  component divide
    port (
      X: in STD_LOGIC_VECTOR(31 downto 0);
      Y: in STD_LOGIC_VECTOR(31 downto 0);

      Z: out STD_LOGIC_VECTOR(31 downto 0);
      V: out STD_LOGIC);
  end component;

  signal uX: STD_LOGIC_VECTOR(31 downto 0);
  signal uY: STD_LOGIC_VECTOR(31 downto 0);

  signal tZ: STD_LOGIC_VECTOR(31 downto 0);
  signal tV: STD_LOGIC;
  signal tS: STD_LOGIC;
begin
  -- Set Unsigned Values
  uX <= X when (X(31) = '0') else STD_LOGIC_VECTOR(ZERO32 - SIGNED(X));
  uY <= Y when (Y(31) = '0') else STD_LOGIC_VECTOR(ZERO32 - SIGNED(Y));

  -- Perform Division
  DIV: divide port map(uX, uY, tZ, tV);

  -- Drop out the last bit as overflow and calculate the sign
  V <= tV or tZ(31);
  tS <= X(31) xor Y(31);

  -- The result is the expected sign and the result of the division
  Z(31) <= tS;
  Z(30 downto 0) <= tZ(30 downto 0) when (tS = '0') else STD_LOGIC_VECTOR(ZERO31 - SIGNED(tZ(30 downto 0)));
end;
