---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 12:53:25 11/19/2008 -- Design Name: -- Module Name: divider - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- W is width of binary divisor and dividend. ITER_REG_WIDTH is register width constant -- of register used in multiple iterations carried out by state machine. It needs to be -- wide enough to hold the value W+1. start is an input triggering the start of the -- division operation. dvsr, dvnd are W bits wide for divisor and dividend. ready is -- output signal indicating another division operation can be carried out. done_tick is -- one clock cycle wide pulse indicating division is complete. quo and rmd are quotient -- and remainder of division entity div is generic( W: integer:= 8; ITER_REG_WIDTH: integer:= 4 ); port( clk, reset: in std_logic; start: in std_logic; dvsr, dvnd: in std_logic_vector(W-1 downto 0); ready, done_tick: out std_logic; quo, rmd: out std_logic_vector(W-1 downto 0) ); end div; architecture arch of div is type state_type is (idle, op, last, done); signal state_reg, state_next: state_type; -- dividend register + left extended 0's signal rh_reg, rh_next: unsigned(W-1 downto 0); signal rl_reg, rl_next: std_logic_vector(W-1 downto 0); -- signal to represent output of data path operation that passes or subtracts signal rh_tmp: unsigned(W-1 downto 0); -- divisor register signal d_reg, d_next: unsigned(W-1 downto 0); -- iteration register signal n_reg, n_next: unsigned(ITER_REG_WIDTH-1 downto 0); -- quotient bit for each iteration signal q_bit: std_logic; begin -- state and register logic process(clk, reset) begin if (reset = '1') then state_reg <= idle; rh_reg <= (others => '0'); rl_reg <= (others => '0'); d_reg <= (others => '0'); n_reg <= (others => '0'); elsif (clk'event and clk = '1') then state_reg <= state_next; rh_reg <= rh_next; rl_reg <= rl_next; d_reg <= d_next; n_reg <= n_next; end if; end process; -- Combo logic for state machine, iteration cnter and shift operations in data path process(state_reg, n_reg, rh_reg, rl_reg, d_reg, start, dvsr, dvnd, q_bit, rh_tmp, n_next) begin ready <= '0'; done_tick <= '0'; state_next <= state_reg; rh_next <= rh_reg; rl_next <= rl_reg; d_next <= d_reg; n_next <= n_reg; case state_reg is when idle => -- set output 'ready' in idle state -- otherwise, we are carrying out division ready <= '1'; if (start = '1') then -- latch dividend -- rh hold '0's. Quotient will be shifted into rl. rh_next <= (others => '0'); rl_next <= dvnd; -- latch divisor d_next <= unsigned(dvsr); -- loop counter initialized to the value (W+1), e.g., 9 n_next <= to_unsigned(W+1, ITER_REG_WIDTH); -- start division state_next <= op; end if; when op => -- shift rh and rl left one position rl_next <= rl_reg(W-2 downto 0) & q_bit; -- rh_tmp is determined below as 'rh_reg' or 'rh_reg minus divisor' rh_next <= rh_tmp(W-2 downto 0) & rl_reg(W-1); n_next <= n_reg - 1; -- Last iteration is special if (n_next = 1) then state_next <= last; end if; -- don't shift rh_next on last iteration when last => rl_next <= rl_reg(W-2 downto 0) & q_bit; rh_next <= rh_tmp; state_next <= done; when done => state_next <= idle; done_tick <= '1'; end case; end process; -- subtract data path operations process (rh_reg, d_reg) begin -- if portion of dividend is greater than or equal to divisor, subtract it and set -- q_bit to 1 if (rh_reg >= d_reg) then rh_tmp <= rh_reg - d_reg; q_bit <= '1'; -- else perserve rh_reg else rh_tmp <= rh_reg; q_bit <= '0'; end if; end process; -- assign quotient and remainder to output quo <= rl_reg; rmd <= std_logic_vector(rh_reg); end arch;