------------------------------------------------------------- -- Define Data Width ------------------------------------------------------------- package mypackage is constant NBITS :INTEGER := 8; constant PBITS :INTEGER := 9; end mypackage; --------------------------------------------------------------- -- NON RESTORING Division algorithm for natural (unsigned) X and Y -- The correction step is only a conditional adder -- divisor Y should be greater than dividend X -- NBITS operands, PBITS quotient and NBITS remainder --------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.mypackage.all; entity div_nr_frac is port ( X: in STD_LOGIC_VECTOR (NBITS-1 downto 0); Y: in STD_LOGIC_VECTOR (NBITS-1 downto 0); Q: out STD_LOGIC_VECTOR (PBITS-1 downto 0); R: out STD_LOGIC_VECTOR (NBITS-1 downto 0) ); end div_nr_frac; architecture mult_arch of div_nr_frac is COMPONENT cond_adder PORT( a : IN std_logic_vector(NBITS-1 downto 0); b : IN std_logic_vector(NBITS-1 downto 0); x_i : IN std_logic; r : OUT std_logic_vector(NBITS-1 downto 0) ); END COMPONENT; component nr_cell port ( a: in STD_LOGIC_VECTOR (NBITS downto 0); b: in STD_LOGIC_VECTOR (NBITS-1 downto 0); q: in STD_LOGIC; r: out STD_LOGIC_VECTOR (NBITS downto 0) ); end component; type conections is array (0 to PBITS-1) of STD_LOGIC_VECTOR (NBITS downto 0); Signal wires_in, wires_out: conections; Signal QQ: STD_LOGIC_VECTOR (PBITS downto 0); signal adjust: STD_LOGIC; Signal zeros: STD_LOGIC_VECTOR (NBITS-1 downto 0); begin QQ(PBITS) <= '0'; wires_in(0) <= X & '0'; divisor: for I in 0 to PBITS-1 generate nr_step: nr_cell port map (a => wires_in(I), b => Y, q => QQ(PBITS-I), r => wires_out(i) ); end generate; wires_conections: for I in 0 to PBITS-2 generate QQ(PBITS-i-1) <= wires_out(i)(NBITS); wires_in(i+1) <= wires_out(i)(NBITS-1 downto 0) & '0'; end generate; adjust <= (wires_out(PBITS-1)(NBITS)); final_adjust: cond_adder port map ( a => wires_out(PBITS-1)(NBITS-1 downto 0), b => Y, x_i => adjust, r => R); Q(PBITS-1 downto 1) <= not QQ(PBITS-1 downto 1); Q(0) <= not adjust; end mult_arch; -------------------------------------------------------- -- non_restoring division cell -- Actually an adder-subtracter -------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.mypackage.all; entity nr_cell is port ( a: in STD_LOGIC_VECTOR (NBITS downto 0); b: in STD_LOGIC_VECTOR (NBITS-1 downto 0); q: in STD_LOGIC; r: out STD_LOGIC_VECTOR (NBITS downto 0) ); end nr_cell; architecture nr_cel_arch of nr_cell is begin adder_subtracter: process (q,a,b) begin if q = '1' then r <= a + b; else r <= a - b; end if; end process; end nr_cel_arch; ---------------------------------------- -- Conditional Adder -- Add a+b depeding on x_i ---------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.mypackage.all; entity cond_adder is port ( a: in STD_LOGIC_VECTOR (NBITS-1 downto 0); b: in STD_LOGIC_VECTOR (NBITS-1 downto 0); x_i: in STD_LOGIC; r: out STD_LOGIC_VECTOR (NBITS-1 downto 0) ); end cond_adder; architecture cond_adder_arch of cond_adder is begin conditional_adder: process (x_i,a,b) begin if x_i = '1' then r <= a + b; else r <= a; end if; end process; end cond_adder_arch; ----------------------------------------------------------------------------- -- VHDL Test Bench NON-Restoring divisor for unsigned X and Y -- -- Exhaustive Analysis -- Notes: -- if NBITS and/or PBITS are big, It will need much time -- ----------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; USE IEEE.std_logic_unsigned.all; USE work.mypackage.all; LIBRARY ieee; USE IEEE.STD_LOGIC_TEXTIO.ALL; USE STD.TEXTIO.ALL; ENTITY testbench_nr_unsigned IS END testbench_nr_unsigned; ARCHITECTURE behavior OF testbench_nr_unsigned IS FILE RESULTS: TEXT OPEN WRITE_MODE IS "results.txt"; COMPONENT div_nr_frac PORT( X: in STD_LOGIC_VECTOR (NBITS-1 downto 0); Y: in STD_LOGIC_VECTOR (NBITS-1 downto 0); Q: out STD_LOGIC_VECTOR (PBITS-1 downto 0); R: out STD_LOGIC_VECTOR (NBITS-1 downto 0) ); END COMPONENT; CONSTANT DELAY: time := 100 ns; CONSTANT print_ok: boolean := false; SIGNAL A: STD_LOGIC_VECTOR (NBITS-1 downto 0); SIGNAL B: STD_LOGIC_VECTOR (NBITS-1 downto 0); SIGNAL Q: STD_LOGIC_VECTOR (PBITS-1 downto 0); SIGNAL R: STD_LOGIC_VECTOR (NBITS-1 downto 0); BEGIN uut: div_nr_frac PORT MAP( X => A, Y => B, Q => Q, R => R ); tb_gen : PROCESS BEGIN for I in 0 to 2**NBITS-1 loop for J in I+1 to 2**NBITS-1 loop A <= CONV_STD_LOGIC_VECTOR (I, NBITS); B <= CONV_STD_LOGIC_VECTOR (J, NBITS); WAIT FOR DELAY; end loop; end loop; WAIT FOR DELAY; --wait; -- will wait forever END PROCESS; tb_test : PROCESS VARIABLE TX_LOC : LINE; VARIABLE TX_STR : String(1 to 4096); Variable iQ, iR: natural; BEGIN WAIT FOR 10 ns; for I in 0 to 2**NBITS -1 loop for J in I+1 to 2**NBITS -1 loop iQ := CONV_INTEGER(Q); iR := CONV_INTEGER(R); IF (I*2**PBITS /= (J * iQ) + iR) THEN write(TX_LOC,string'("Error!!! -> A=")); write(TX_LOC, A); write(TX_LOC,string'(" B=")); write(TX_LOC, B); write(TX_LOC,string'(" Q=")); write(TX_LOC, Q); write(TX_LOC,string'(" R=")); write(TX_LOC, R); write(TX_LOC,string'(" (i=")); write(TX_LOC, i); write(TX_LOC,string'(" j=")); write(TX_LOC, j); write(TX_LOC,string'(" iQ=")); write(TX_LOC, iQ); write(TX_LOC,string'(" iR=")); write(TX_LOC, iR); write(TX_LOC, string'(") ")); TX_STR(TX_LOC.all'range) := TX_LOC.all; writeline(results, TX_LOC); Deallocate(TX_LOC); ASSERT (FALSE) REPORT TX_STR SEVERITY ERROR; elsif (iR > J) then write(TX_LOC,string'("Error Remainder bigger than Divider !!! -> A=")); write(TX_LOC, A); write(TX_LOC,string'(" B=")); write(TX_LOC, B); write(TX_LOC,string'(" Q=")); write(TX_LOC, Q); write(TX_LOC,string'(" R=")); write(TX_LOC, R); write(TX_LOC,string'(" (i=")); write(TX_LOC, i); write(TX_LOC,string'(" j=")); write(TX_LOC, j); write(TX_LOC,string'(" iQ=")); write(TX_LOC, iQ); write(TX_LOC,string'(" iR=")); write(TX_LOC, iR); write(TX_LOC, string'(") ")); TX_STR(TX_LOC.all'range) := TX_LOC.all; writeline(results, TX_LOC); Deallocate(TX_LOC); ASSERT (FALSE) REPORT TX_STR SEVERITY ERROR; elsif (print_ok) then write(TX_LOC,string'("OK -> A=")); write(TX_LOC, A); write(TX_LOC,string'(" B=")); write(TX_LOC, B); write(TX_LOC,string'(" Q=")); write(TX_LOC, Q); write(TX_LOC,string'(" R=")); write(TX_LOC, R); write(TX_LOC, string'(" ")); TX_STR(TX_LOC.all'range) := TX_LOC.all; writeline(results, TX_LOC); Deallocate(TX_LOC); ASSERT (FALSE) REPORT TX_STR SEVERITY WARNING; END IF; WAIT FOR DELAY; end loop; end loop; ASSERT (FALSE) REPORT "Simulation successful (not a failure). No problems detected. " SEVERITY FAILURE; END PROCESS; END;