如何使用Xilinx Division IP Core

How to use the Xilinx Division IP Core

我正在用 VHDL 编写要合成到 XilinX FPGA 上的代码。我通常使用 GHDL 来模拟我的测试平台。我需要使用 XilinX 除法核心来除以变量,但我不确定如何执行此操作,因为 XilinX 文档中似乎没有示例。我必须使用 XilinX 软件为分频器生成 VHDL 组件吗?还是 XilinX 隐含地理解分频器意味着使用 IP 核?如果我的第二个陈述是正确的,我将如何使用 GHDL 对此进行仿真,或者我是否必须使用 XilinX 仿真工具?我真的可以用一个使用 XilinX 分频器内核来实现按变量除法的最小示例来做,例如像这样:

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;

此示例代码显然不起作用,因为没有为整数数据类型定义除法(“/”运算符)。我该怎么办?

我最终编写了自己的除法代码,这比使用 XilinX 的 IP 核实现起来要快得多,也容易得多。我使用了详细的二进制除法算法 here 并为有符号的 32 位除法编写了以下 VHDL 代码:

  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;