------------------------------------- -- Defines data path width -- ------------------------------------- package mypackage is constant NDIGITS :INTEGER := 3; constant MDIGITS :INTEGER := 5; constant BASE :INTEGER := 4; 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; --------------------------------------------------------- -- Basic base B multiplier (unsigned operands) -- Iterative implementation -- ---------------------------------------------------------- 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 basic_base_B_mult_seq is port ( clk: in std_logic; ini: in std_logic; X: in digit_vector(NDIGITS-1 downto 0); Y: in digit_vector(MDIGITS-1 downto 0); done: out std_logic; P: out digit_vector(NDIGITS+MDIGITS-1 downto 0) ); end basic_base_B_mult_seq; architecture simple_arch of basic_base_B_mult_seq is component mult_by_1_digit is port ( A: in digit_vector(MDIGITS-1 downto 0); B: in digit_vector(MDIGITS-1 downto 0); x_i : in digit; P: out digit_vector(MDIGITS downto 0) ); end component; signal Reg_X: digit_vector(NDIGITS-1 downto 0); signal Reg_Y, Reg_P: digit_vector(MDIGITS-1 downto 0); signal n_Reg_P: digit_vector(MDIGITS downto 0); signal counter: integer range 0 to NDIGITS+1; signal work: STD_LOGIC; begin state_mach: process (CLK, work, ini) begin if CLK'event and CLK='0' then if ini='1' then work <= '1'; Reg_P <= (others => 0); counter <= 0; Reg_X <= X; Reg_Y <= Y; elsif work = '1' then counter <= counter+1; Reg_P <= n_Reg_P(MDIGITS downto 1); Reg_X <= n_Reg_P(0) & Reg_X(NDIGITS-1 downto 1); if (counter = NDIGITS) then P <= Reg_P & Reg_X; work <= '0'; end if; end if; end if; end process; done <= not work; mult: mult_by_1_digit port map (A => Reg_P, B => Reg_Y, x_i => REG_X(0), P => n_Reg_P ); end simple_arch; ---------------------------------------------------- -- Mult_by_1_digit: Caclutate P <= A + (x_i*B) -- where x_i is a digit; A and B are digit vectors ---------------------------------------------------- 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 mult_by_1_digit is Port ( A: in digit_vector(MDIGITS-1 downto 0); B: in digit_vector(MDIGITS-1 downto 0); x_i : in digit; P: out digit_vector(MDIGITS downto 0) ); end mult_by_1_digit; architecture Behavioral of mult_by_1_digit is begin process(B,A, x_i) variable carry: digit_vector(MDIGITS downto 0); begin carry(0) := 0; for i in 0 to MDIGITS-1 loop P(i) <= (B(i) * X_i + A(i) + carry(i)) mod BASE; carry(i+1) := (B(i) * X_i + A(i) + carry(i)) / BASE; end loop; P(MDIGITS) <= carry(MDIGITS); end process; end Behavioral; ---------------------------------------------------------------------- -- VHDL Test Bench for basic_base_B_mult_seq -- -- Notes: ---------------------------------------------------------------------- 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 test_exhaustive IS END test_exhaustive; ARCHITECTURE behavioural OF test_exhaustive IS constant DELAY: time := 100 ns; FILE RESULTS: TEXT OPEN WRITE_MODE IS "results.txt"; COMPONENT basic_base_B_mult_seq PORT( clk: in std_logic; ini: in std_logic; X: in digit_vector(NDIGITS-1 downto 0); Y: in digit_vector(MDIGITS-1 downto 0); done: out std_logic; P: out digit_vector(NDIGITS+MDIGITS-1 downto 0) ); END COMPONENT; SIGNAL x : digit_vector(NDIGITS-1 downto 0); SIGNAL y : digit_vector(MDIGITS-1 downto 0); SIGNAL p : digit_vector(NDIGITS+MDIGITS-1 downto 0); SIGNAL clk, ini, done: std_logic; BEGIN uut: basic_base_B_mult_seq PORT MAP(clk => clk, ini => ini, X => x, Y => y, done => done, P => p); PROCESS -- clock process for clk, BEGIN clk <= '0'; WAIT FOR 10 ns; CLOCK_LOOP : LOOP clk <= '1'; WAIT FOR DELAY/2; clk <= '0'; WAIT FOR DELAY/2; END LOOP CLOCK_LOOP; END PROCESS; tb_test : PROCESS VARIABLE TX_LOC : LINE; VARIABLE TX_STR : String(1 to 4096); VARIABLE iP : natural; BEGIN for i in 0 to BASE**NDIGITS-1 loop for j in 0 to BASE**MDIGITS-1 loop x <= int_2_baseB(i,NDIGITS); y <= int_2_baseB(j,MDIGITS); ini <= '1'; WAIT FOR DELAY; ini <= '0'; WAIT FOR (NDIGITS+1)*DELAY; iP := baseB_2_int(P); IF ( I*J /= iP) THEN write(TX_LOC,string'("ERROR!!! X=")); write(TX_LOC, i); write(TX_LOC,string'(" Y=")); write(TX_LOC, j); write(TX_LOC,string'(" P=")); write(TX_LOC, iP); 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; END IF; end loop; end loop; ASSERT (FALSE) REPORT "Simulation successful (not a failure). No problems detected. " SEVERITY FAILURE; END PROCESS; END;