------------------------------------- --Define el ancho de la ruta de datos -- ------------------------------------- package mypackage is constant NDIGITS :INTEGER := 7; constant PDIGITS :INTEGER := 5; constant BASE :INTEGER := 10; subtype digit is INTEGER range 0 to BASE-1; type digit_vector is array (natural range <>) of digit; function baseB_2_int (signal a: in digit_vector) return integer; function int_2_baseB (int: in integer; size: in integer) return digit_vector; end mypackage; package body mypackage is function baseB_2_int (signal a: in digit_vector) return INTEGER is variable int: INTEGER := 0; begin for i in a'Length-1 downto 0 loop int := int * BASE + A(i); end loop; return int; end baseB_2_int; function int_2_baseB (int: in INTEGER; size: in integer ) return digit_vector is variable s: digit_vector(size-1 downto 0); variable aux1, aux2: integer; begin aux1 := int; for i in 0 to size-1 loop s(i) := aux1 mod BASE; aux2 := aux1 / BASE; aux1 := aux2; end loop; return s; end int_2_baseB; end mypackage; --------------------------------------------------------------- -- RESTORING base-B Divisor -- -- --------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use work.mypackage.all; entity div_rest_baseB is port ( A: in digit_vector(NDIGITS-1 downto 0); B: in digit_vector(NDIGITS-1 downto 0); Q: out digit_vector(PDIGITS-1 downto 0); R: out digit_vector(NDIGITS-1 downto 0) ); end div_rest_baseB; architecture div_arch of div_rest_baseB is component rest_baseB_step is port ( a: in digit_vector(NDIGITS-1 downto 0); b: in digit_vector(NDIGITS-1 downto 0); q: out digit; r: out digit_vector(NDIGITS-1 downto 0) ); end component; type conections is array (0 to PDIGITS) of digit_vector(NDIGITS-1 downto 0); Signal wires: conections; begin wires(0) <= A; divisor: for i in 0 to PDIGITS-1 generate rest_step: rest_baseB_step port map (a => wires(i), b => B, q => Q(PDIGITS-i-1), r => wires(i+1)); end generate; R <= wires(PDIGITS)(NDIGITS-1 downto 0); end div_arch; --------------------------------------------------------------- -- RESTORING base-B Division step -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity rest_baseB_step is port ( a: in digit_vector(NDIGITS-1 downto 0); b: in digit_vector(NDIGITS-1 downto 0); q: out digit; r: out digit_vector(NDIGITS-1 downto 0) ); end rest_baseB_step; architecture behavioural of rest_baseB_step is component look_up_table is port ( at: in digit_vector(2 downto 0); bt: in digit_vector(1 downto 0); qt: out digit; qt_1: out digit ); end component; component base_b_mult is port ( a: in digit; b: in digit_vector(NDIGITS-1 downto 0); m: out digit_vector(NDIGITS downto 0) ); end component; component base_b_adder is port ( a: in digit_vector(NDIGITS-1 downto 0); b: in digit_vector(NDIGITS-1 downto 0); s: out digit_vector(NDIGITS downto 0) ); end component; component base_b_subt is port ( a: in digit_vector(NDIGITS downto 0); b: in digit_vector(NDIGITS downto 0); s: out digit_vector(NDIGITS downto 0); sign: out bit ); end component; signal at: digit_vector(2 downto 0); signal bt: digit_vector(1 downto 0); signal qt,qt_1: digit; signal q_x_b, a_x_BASE, remainder, rem_plus_b: digit_vector(NDIGITS downto 0); signal sign: bit; begin at <= A(NDIGITS-1 downto NDIGITS-3); bt <= B(NDIGITS-1 downto NDIGITS-2); a_x_BASE(NDIGITS downto 1) <= a; a_x_BASE(0) <= 0; LookUpTable: look_up_table port map (at => at, bt => bt, qt => qt, qt_1 => qt_1); mult: base_b_mult port map (a => qt, b => B, m => q_x_b); subtrator: base_b_subt port map (a => a_x_BASE, b => q_x_b, s => remainder, sign => sign); adder: base_b_adder port map (a => remainder(NDIGITS-1 downto 0), b => B, s => rem_plus_b); multiplexers: process (sign,qt_1, qt, rem_plus_b,remainder) begin if sign = '1' then q <= qt_1; r <= rem_plus_b(NDIGITS-1 downto 0); else q <= qt; r <= remainder(NDIGITS-1 downto 0); end if; end process; end behavioural; --------------------------------------------------------------- -- RESTORING base-B Division step: base B adder -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity base_B_adder is port ( a: in digit_vector(NDIGITS-1 downto 0); b: in digit_vector(NDIGITS-1 downto 0); s: out digit_vector(NDIGITS downto 0) ); end base_B_adder; architecture behavior of base_B_adder is begin process(B,A) variable carry: digit_vector(NDIGITS downto 0); begin carry(0) := 0; for i in 0 to NDIGITS-1 loop s(i) <= (B(i) + A(i) + carry(i)) mod BASE; carry(i+1) := (B(i) + A(i) + carry(i)) / BASE; end loop; s(NDIGITS) <= carry(NDIGITS); end process; end behavior; --------------------------------------------------------------- -- RESTORING base-B Division step: base B multiplier -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity base_B_mult is port ( a: in digit; b: in digit_vector(NDIGITS-1 downto 0); m: out digit_vector(NDIGITS downto 0) ); end base_B_mult; architecture behavior of base_B_mult is begin process(B,A) variable carry: digit_vector(NDIGITS downto 0); begin carry(0) := 0; for i in 0 to NDIGITS-1 loop m(i) <= (B(i) * A + carry(i)) mod BASE; carry(i+1) := ( B(i) * A + carry(i) ) / BASE; end loop; m(NDIGITS) <= carry(NDIGITS); end process; end behavior; --------------------------------------------------------------- -- RESTORING base-B Division step: base B subtractor -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity base_B_subt is port ( a: in digit_vector(NDIGITS downto 0); b: in digit_vector(NDIGITS downto 0); s: out digit_vector(NDIGITS downto 0); sign: out bit ); end base_B_subt; architecture behavior of base_B_subt is begin process(b,a) variable borrow: digit_vector(NDIGITS+1 downto 0); begin borrow(0) := 0; for i in 0 to NDIGITS loop s(i) <= (A(i) - B(i) - borrow(i)) mod BASE; --borrow(i+1) <= (A(i) - B(i) - borrow(i)) / BASE; if (A(i) - B(i) - borrow(i)) < 0 then borrow(i+1) := 1; else borrow(i+1) := 0; end if; end loop; if borrow(NDIGITS+1) = 0 then sign <= '0'; else sign <= '1'; end if; end process; end behavior; --------------------------------------------------------------- -- RESTORING base-B Division step: Look Up Table -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity look_up_table is port ( at: in digit_vector(2 downto 0); bt: in digit_vector(1 downto 0); qt: out digit; qt_1: out digit ); end look_up_table; architecture behavior of look_up_table is begin process(at,bt) variable at_i,bt_i,qt_i: integer ; begin qt <= 0; qt_1 <= 0; at_i := at(2) *BASE*BASE + at(1)*BASE + at(0); bt_i := bt(1) *BASE + bt(0); if bt_i > 0 then qt_i := at_i / bt_i; if qt_i < BASE and qt_i > 0 then qt <= qt_i; qt_1 <= qt_i - 1; elsif qt_i = BASE then qt <= BASE - 1; qt_1 <= BASE - 1; end if; end if; end process; end behavior; -------------------------------------------------------- -- VHDL Test Bench: div_rest_baseB -- Exhaustive TestBench -------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; use work.mypackage.all; LIBRARY ieee; USE IEEE.STD_LOGIC_TEXTIO.ALL; USE STD.TEXTIO.ALL; ENTITY test_div_rest_baseB_exhaustive IS END test_div_rest_baseB_exhaustive; ARCHITECTURE behavior OF test_div_rest_baseB_exhaustive IS COMPONENT div_rest_baseB PORT( A : IN digit_vector(NDIGITS-1 downto 0); B : IN digit_vector(NDIGITS-1 downto 0); Q : OUT digit_vector(PDIGITS-1 downto 0); R : OUT digit_vector(NDIGITS-1 downto 0) ); END COMPONENT; SIGNAL A : digit_vector(NDIGITS-1 downto 0); SIGNAL B : digit_vector(NDIGITS-1 downto 0); SIGNAL Q : digit_vector(PDIGITS-1 downto 0); SIGNAL R : digit_vector(NDIGITS-1 downto 0); constant AMOUNTS_TRIALS : integer := 100; constant DELAY : time := 100 ns; BEGIN uut: div_rest_baseB PORT MAP( A => A, B => B, Q => Q, R => R ); tb_gen : PROCESS VARIABLE TX_LOC : LINE; VARIABLE TX_STR : String(1 to 4096); VARIABLE t1,te : String(1 to 4096); VARIABLE iQ,iR : integer; BEGIN for iA in BASE**(NDIGITS-1) to BASE**NDIGITS-1 loop for iB in iA+1 to BASE**NDIGITS-1 loop A <= int_2_baseB(iA,NDIGITS); B <= int_2_baseB(iB,NDIGITS); WAIT FOR DELAY; iQ := baseB_2_int(Q); iR := baseB_2_int(R); IF ((iA*(BASE**(PDIGITS))) /= (iB * iQ) + iR) or (iR >= iB )THEN write(TX_LOC,string'("ERROR!!! A=")); write(TX_LOC, iA); write(TX_LOC,string'(" B=")); write(TX_LOC, iB); write(TX_LOC,string'(" Q=")); write(TX_LOC, iQ); write(TX_LOC,string'(" R=")); write(TX_LOC, iR); TX_STR(TX_LOC.all'range) := TX_LOC.all; Deallocate(TX_LOC); ASSERT (FALSE) REPORT TX_STR SEVERITY FAILURE; 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;