Search code examples
vhdlfpgaxilinxdivider

How to use the Xilinx Division IP Core


I am writing code in VHDL to be synthesised onto a XilinX FPGA. I typically use GHDL to simulate my testbenches. I need to make use of the XilinX division core in order to divide by a variable however I am not sure how to do this as there appear to be no examples in the XilinX documentation. Do I have to use the XilinX software to generate the VHDL component for the divider? Or does XilinX implicitly understand that divider means using the IP core? If my 2nd statement is true how would I go about simulating this with GHDL or would I have to use a XilinX simulation tool? I could really do with a minimal example of using the XilinX divider core to implement division by a variable e.g. something like this:

library ieee;      
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;

entity DividingExample is
  port (
    clk : in std_logic;
    reset : in std_logic;
    InputSignal : in std_logic_vector(15 downto 0);
    OutputSignal : out std_logic_vector(15 downto 0)
    );
end DividingExample;

architecture behaviour of DividingExample is
-- declarations
  signal numerator : integer;
begin
-- behaviour
  process(clk)
  begin
    if(rising_edge(clk)) then
      if(reset = '1') then
        -- reset values
        numerator <= 1000;  
      else
        -- calculate value to be output
        OutputSignal <= numerator/to_integer(signed(InputSignal))
    end if;
  end if;
end process;
end behaviour;

This example code obviously doesn't work as division (the '/' operator) is not defined for the integer datatype. How might I go about this?


Solution

  • I ended up writing my own division code, which was significantly quicker and easier to implement than using XilinX's IP Core. I used the binary division algorithm detailed here and wrote the following VHDL code for a signed 32 bit division:

      function Divide(N : signed(31 downto 0); D : signed(31 downto 0)) return signed is                                                                                                                    
        variable Q : signed(31 downto 0) := to_signed(0, 32);                                                      
        variable R : signed(31 downto 0) := to_signed(0, 32);                                                      
        variable l : line;                                                                                           
        constant N_Abs : signed(31 downto 0) := abs(N);                                                             
        constant D_Abs : signed(31 downto 0) := abs(D);                                                             
      begin                                                                                                          
        -- behaviour                                                                                                 
        for i in N_Abs'high downto 0 loop                                                                            
          R := shift_left(R, 1);                                                                                     
          R(0) := N_Abs(i);                                                                                          
          if R >= D_Abs then                                                                                         
            R := R - D;                                                                                              
            Q(i) := '1';                                                                                             
          end if;                                                                                                    
        end loop;                                                                                                    
    
        if ((N < 0 and D > 0) or (N > 0 and D < 0)) then                                                             
          return -Q;                                                                                                 
        else                                                                                                         
          return Q;                                                                                                  
        end if;                                                                                                      
      end function;