----------------------------------------------------------------------------------
-- Company:
-- Engineer: Rob David
--
-- Create Date: 10:00:00 07/30/2010
-- Design Name:
-- Module Name: fix_pt_div_nr - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description: Fixed point divider based on non-restoring algorithm for integer
-- inputs and optional fractional quotient output. QUO = NUM/DEN
-- The difference between the size of N and Q determines the number
-- of decimal points to the right of N bit positions.
-- Example: If N is 8 and Q is 10 then there will be 2 bits of binary
-- fraction to the right of N bits. 00000000.00
-- Fractional precision is 0.5, 0.25, 0.125, 0.0625 ...
-- Separate sign (SGN) output. Cycle synchronously starts when RST = '1'.
-- RDY output = '1' when done. If error ERR = '1'.
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
--
-- Additional Comments: Copyright ˆ 2009-2010 Robert David (rjdavid1@shaw.ca)
-- Provided WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
--use IEEE.NUMERIC_STD.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity fix_pt_div_nr is
Generic ( N : positive := 8; -- Size of numerator and denominator including the sign bit
Q : positive := 10); -- Number of bits in quotient including extra fractional precision
Port ( CLK : in STD_LOGIC; -- Input clock 50Mhz or ?
RST : in STD_LOGIC; -- Reset to start new cycle active high
NUM : in STD_LOGIC_VECTOR (N-1 downto 0); -- Numerator input
DEN : in STD_LOGIC_VECTOR (N-1 downto 0); -- Denominator input
QUO : out STD_LOGIC_VECTOR (Q-1 downto 0) := (others => '0'); -- Quotient output
SGN : out STD_LOGIC := '0'; -- Sign of quotient '1' = negative
ERR : out STD_LOGIC := '0'; -- Error if '1'
div : inout STD_LOGIC_VECTOR (7 downto 0);
reminder
ut STD_LOGIC_VECTOR (15 downto 0);
RDY : out STD_LOGIC := '0'); -- Data ready output active high
end fix_pt_div_nr;
architecture Behavioral of fix_pt_div_nr is
constant N_MSB : positive := N-1;
constant Q_MSB : positive := Q-1;
type STATE_TYPE is (Init, Sign, Error_Test, Sub_MSB, Append_D, Set_Q, Add_Sub_D, Bound_Test, Idle);
signal CS : STATE_TYPE := Idle; -- CS = Current State
signal Q_Bit : STD_LOGIC_VECTOR (Q_MSB downto 0):= (others => '0');
signal D_Bit : STD_LOGIC_VECTOR (N_MSB downto 0):= (others => '0');
signal Numer : STD_LOGIC_VECTOR (N_MSB downto 0);
signal Denom : STD_LOGIC_VECTOR (N_MSB downto 0);
signal Error : STD_LOGIC := '0';
begin
div_proc : process(CLK) --, RST )
variable i : integer range 0 to Q; -- Bit index
begin
-- if RST = '1' then -- Aynchronous reset
-- RDY <= '0'; -- Reset the Ready and Error outputs immediately
-- SGN <= '0';
-- Error <= '0';
-- CS <= S1;
if CLK'event AND CLK = '1' then -- State machine
if RST = '1' then -- Synchronous reset
RDY <= '0'; -- Reset the Ready and Error outputs immediately
SGN <= '0';
Error <= '0';
CS <= Init;
else
case CS is
when Init => -- Initialize all values
i := 1;
Q_Bit <= (others => '0');
CS <= Sign;
when Sign => -- Determine sign of quotient
if ((CONV_INTEGER(NUM) < 0 AND CONV_INTEGER(DEN) < 0) OR -- Both negative or
(CONV_INTEGER(NUM) >= 0 AND CONV_INTEGER(DEN) >= 0)) then -- both pos?
SGN <= '0'; -- Sign is positive
else
SGN <= '1'; -- Either numerator or denominator is negative so quotient will be also
end if;
Numer <= abs NUM; -- Convert to absolute values (positive numbers)
Denom <= abs DEN;
CS <= Error_Test;
when Error_Test =>
if CONV_INTEGER(Numer) = 0 then -- Numerator = 0 so output quick zero quotient
Error <= '0';
RDY <= '1'; -- Output Ready signal
CS <= Idle; -- Done and idle state
-- Error on divide by zero
elsif (CONV_INTEGER(Denom) = 0) then -- Divide by zero catch
Error <= '1';
RDY <= '1'; -- Output Ready signal
CS <= Idle; -- Error and idle state
else
Error <= '0';
RDY <= '0';
CS <= Sub_MSB; -- No error so continue
end if;
when Sub_MSB =>
D_Bit <= Numer(N_MSB) - Denom; -- Subtract denominator from MSB of numerator
CS <= Append_D;
when Append_D =>
if i > N_MSB then -- Quotient is larger than numerator denominator so do fractional part
D_Bit <= D_Bit(N_MSB - 1 downto 0) & "0";
else
D_Bit <= D_Bit(N_MSB - 1 downto 0) & Numer(N_MSB - i); -- Bring down next MSB and append to D_Bit
end if;
CS <= Set_Q;
when Set_Q =>
if D_Bit >= 0 then -- Is positive ?
Q_Bit(Q - i) <= '1'; -- Set bit to '1'
CS <= Add_Sub_D;
else -- Is negative
Q_Bit(Q - i) <= '0'; -- Set bit to '0'
CS <= Add_Sub_D;
end if;
when Add_Sub_D =>
if D_Bit >= 0 then -- Is positive ?
D_Bit <= D_Bit - Denom;
CS <= Bound_Test;
else -- Is negative
D_Bit <= D_Bit + Denom;
CS <= Bound_Test;
end if;
when Bound_Test => -- Increment bit index check for bounds
i := i + 1;
if i = Q + 1 then -- Done all bits?
RDY <= '1'; -- Output Ready signal
CS <= Idle;
elsif i < Q then
CS <= Append_D; -- Iterate through algorithm
else -- Do last bit and remainder
CS <= Set_Q;
end if;
when Idle => -- Idle state
CS <= Idle;
when others => -- Default reset and restart
RDY <= '0';
Error <= '0';
CS <= Init;
end case;
end if;
end if; -- End clk event
end process div_proc;
QUO <= Q_Bit;
ERR <= Error;
div<=Q_Bit(Q-1 downto 2);
reminder<=NUM-(DEN*div);
end Behavioral;
here "div " output may consider as signal also[/b]