library vunit_lib; context vunit_lib.vunit_context; library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; use work.decode_types.all; use work.common.all; use work.ppc_fx_insns.all; library osvvm; use osvvm.RandomPkg.all; entity multiply_tb is generic (runner_cfg : string := runner_cfg_default); end multiply_tb; architecture behave of multiply_tb is signal clk : std_ulogic; constant clk_period : time := 10 ns; constant pipeline_depth : integer := 4; signal m1 : MultiplyInputType := MultiplyInputInit; signal m2 : MultiplyOutputType; begin multiply_0: entity work.multiply generic map (PIPELINE_DEPTH => pipeline_depth) port map (clk => clk, m_in => m1, m_out => m2); clk_process: process begin clk <= '0'; wait for clk_period/2; clk <= '1'; wait for clk_period/2; end process; stim_process: process variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0); variable si: std_ulogic_vector(15 downto 0); variable rnd : RandomPType; begin rnd.InitSeed(stim_process'path_name); test_runner_setup(runner, runner_cfg); while test_suite loop if run("Test interface") then wait for clk_period; m1.valid <= '1'; m1.data1 <= x"0000000000001000"; m1.data2 <= x"0000000000001111"; wait for clk_period; check_false(?? m2.valid, result("for valid")); m1.valid <= '0'; wait for clk_period; check_false(?? m2.valid, result("for valid")); wait for clk_period; check_false(?? m2.valid, result("for valid")); wait for clk_period; check_true(?? m2.valid, result("for valid")); check_equal(m2.result, 16#1111000#); wait for clk_period; check_false(?? m2.valid, result("for valid")); m1.valid <= '1'; wait for clk_period; check_false(?? m2.valid, result("for valid")); m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result, 16#1111000#); elsif run("Test mulld") then mulld_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulld(ra, rb); m1.data1 <= ra; m1.data2 <= rb; m1.is_signed <= '1'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(63 downto 0), behave_rt, result("for mulld " & to_hstring(behave_rt))); end loop; elsif run("Test mulhdu") then mulhdu_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhdu(ra, rb); m1.data1 <= ra; m1.data2 <= rb; m1.is_signed <= '0'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(127 downto 64), behave_rt, result("for mulhdu " & to_hstring(behave_rt))); end loop; elsif run("Test mulhd") then mulhd_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhd(ra, rb); m1.data1 <= ra; m1.data2 <= rb; m1.is_signed <= '1'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(127 downto 64), behave_rt, result("for mulhd " & to_hstring(behave_rt))); end loop; elsif run("Test mullw") then mullw_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); rb := rnd.RandSlv(rb'length); behave_rt := ppc_mullw(ra, rb); m1.data1 <= (others => ra(31)); m1.data1(31 downto 0) <= ra(31 downto 0); m1.data2 <= (others => rb(31)); m1.data2(31 downto 0) <= rb(31 downto 0); m1.is_signed <= '1'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(63 downto 0), behave_rt, result("for mullw " & to_hstring(behave_rt))); end loop; elsif run("Test mulhw") then mulhw_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhw(ra, rb); m1.data1 <= (others => ra(31)); m1.data1(31 downto 0) <= ra(31 downto 0); m1.data2 <= (others => rb(31)); m1.data2(31 downto 0) <= rb(31 downto 0); m1.is_signed <= '1'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(63 downto 32) & m2.result(63 downto 32), behave_rt, result("for mulhw " & to_hstring(behave_rt))); end loop; elsif run("Test mulhwu") then mulhwu_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); rb := rnd.RandSlv(rb'length); behave_rt := ppc_mulhwu(ra, rb); m1.data1 <= (others => '0'); m1.data1(31 downto 0) <= ra(31 downto 0); m1.data2 <= (others => '0'); m1.data2(31 downto 0) <= rb(31 downto 0); m1.is_signed <= '0'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(63 downto 32) & m2.result(63 downto 32), behave_rt, result("for mulhwu " & to_hstring(behave_rt))); end loop; elsif run("Test mulli") then mulli_loop : for i in 0 to 1000 loop ra := rnd.RandSlv(ra'length); si := rnd.RandSlv(si'length); behave_rt := ppc_mulli(ra, si); m1.data1 <= ra; m1.data2 <= (others => si(15)); m1.data2(15 downto 0) <= si; m1.is_signed <= '1'; m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; m1.valid <= '0'; wait for clk_period * (pipeline_depth-1); check_true(?? m2.valid, result("for valid")); check_equal(m2.result(63 downto 0), behave_rt, result("for mulli " & to_hstring(behave_rt))); end loop; end if; end loop; test_runner_cleanup(runner); wait; end process; end behave;