Radix2div

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in November 2011

I want to come back and revisit this actually verify the design properly - only verified in simulation for a small set of numbers.

VHDL source for non-pipelined Radix2 division

Performance as around 29MHz on Xilinx XC6SLX9-3 (latency of 34ns), with a constraint on "clk" of 28MHz.

----------------------------------------------------------------------------------
-- Engineer:       Mike Field (hamster@snap.net.nz)
-- 
-- Create Date:    20:59:(Width-1) 11/28/2011 
-- Module Name:    DivRadix2 - Behavioral 
-- Description:     A Radix2 divider
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity DivRadix2 is
   GENERIC(width : Natural := 16);
    Port ( clk      : in  STD_LOGIC;
           Dividend : in  STD_LOGIC_VECTOR ((Width-1) downto 0);
           Divisor  : in  STD_LOGIC_VECTOR ((Width-1) downto 0);
           Quotient : out STD_LOGIC_VECTOR ((Width-1) downto 0);
           Remainder: out STD_LOGIC_VECTOR ((Width-1) downto 0));
end DivRadix2;

architecture Behavioral of DivRadix2 is
  type test_arr    is array(0 to (Width-1)) of std_logic_vector((Width-1) downto 0);
  type partial_arr is array(0 to Width) of std_logic_vector((Width-1) downto 0);
  type divisor_arr is array(0 to Width) of std_logic_vector((Width-1) downto 0);
  type q_arr       is array(0 to Width) of std_logic_vector((Width-1) downto 0);
  
  signal test : test_arr;
  signal p    : partial_arr;
  signal d    : divisor_arr;
  signal q    : q_arr;

  constant zeros     : STD_LOGIC_VECTOR ((Width-2) downto 0) := (others => '0');

begin
  q(Width)       <= (others => '0');
  p(Width)       <= dividend;
  d(Width)       <= divisor;
  remainder   <= p(0);
  quotient    <= q(0);

  testgen: for I in 0 to (Width-1) generate
    test(I) <= zeros(I-1 downto 0) & p(I+1)((Width-1) downto I);
  end generate testgen;
  
  procgen: for I in 0 to (Width-1) generate
    process (clk, p(I+1),test(I), d(I+1), q(I+1))
    begin
      q(I) <= q(I+1)((Width-2) downto 0) & "0";
      d(I) <= d(I+1);
      p(I) <= p(I+1);
      if test(I) >= d(I+1) then
        q(I) <= q(I+1)((Width-2) downto 0) & '1';
        p(I) <= (p(I+1)((Width-1) downto I)-test(I)((Width-1)-I downto 0)) & p(I+1)(I-1 downto 0);
      end if;
    end process;
  end generate procgen;
end Behavioral;

VHDL source for pipelined Radix2 division

Performance is around 330MHz on Xilinx XC6SLX9-3, latency is 16 cycles (48.0ns), with a constraint on "clk" of 320MHz.

----------------------------------------------------------------------------------
-- Engineer:       Mike Field (hamster@snap.net.nz)
-- 
-- Create Date:    20:59:(Width-1) 11/28/2011 
-- Module Name:    DivRadix2 - Behavioral 
-- Description:     A Radix2 divider
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity DivRadix2 is
   GENERIC(width : Natural := 16);
    Port ( clk      : in  STD_LOGIC;
           Dividend : in  STD_LOGIC_VECTOR ((Width-1) downto 0);
           Divisor  : in  STD_LOGIC_VECTOR ((Width-1) downto 0);
           Quotient : out STD_LOGIC_VECTOR ((Width-1) downto 0);
           Remainder: out STD_LOGIC_VECTOR ((Width-1) downto 0));
end DivRadix2;

architecture Behavioral of DivRadix2 is
  type test_arr    is array(0 to (Width-1)) of std_logic_vector((Width-1) downto 0);
  type partial_arr is array(0 to Width) of std_logic_vector((Width-1) downto 0);
  type divisor_arr is array(0 to Width) of std_logic_vector((Width-1) downto 0);
  type q_arr       is array(0 to Width) of std_logic_vector((Width-1) downto 0);
  
  signal test : test_arr;
  signal p    : partial_arr;
  signal d    : divisor_arr;
  signal q    : q_arr;

  constant zeros     : STD_LOGIC_VECTOR ((Width-2) downto 0) := (others => '0');

begin
  q(Width)       <= (others => '0');
  p(Width)       <= dividend;
  d(Width)       <= divisor;
  remainder   <= p(0);
  quotient    <= q(0);

  testgen: for I in 0 to (Width-1) generate
    test(I) <= zeros(I-1 downto 0) & p(I+1)((Width-1) downto I);
  end generate testgen;
  
  procgen: for I in 0 to (Width-1) generate
    process (clk, p(I+1),test(I), d(I+1), q(I+1))
    begin
      if rising_edge(clk) then 
        q(I) <= q(I+1)((Width-2) downto 0) & "0";
        d(I) <= d(I+1);
        p(I) <= p(I+1);
        if test(I) >= d(I+1) then
          q(I) <= q(I+1)((Width-2) downto 0) & '1';
          p(I) <= (p(I+1)((Width-1) downto I)-test(I)((Width-1)-I downto 0)) & p(I+1)(I-1 downto 0);
        end if;
      end if;
    end process;
  end generate procgen;
end Behavioral;
Personal tools