You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
523 lines
23 KiB
523 lines
23 KiB
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 divider_tb is |
|
generic (runner_cfg : string := runner_cfg_default); |
|
end divider_tb; |
|
|
|
architecture behave of divider_tb is |
|
signal clk : std_ulogic; |
|
signal rst : std_ulogic; |
|
constant clk_period : time := 10 ns; |
|
|
|
signal d1 : Execute1ToDividerType; |
|
signal d2 : DividerToExecute1Type; |
|
begin |
|
divider_0: entity work.divider |
|
port map (clk => clk, rst => rst, d_in => d1, d_out => d2); |
|
|
|
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 d128: std_ulogic_vector(127 downto 0); |
|
variable q128: std_ulogic_vector(127 downto 0); |
|
variable q64: std_ulogic_vector(63 downto 0); |
|
variable rem32: std_ulogic_vector(31 downto 0); |
|
variable rnd : RandomPType; |
|
begin |
|
rnd.InitSeed(stim_process'path_name); |
|
|
|
test_runner_setup(runner, runner_cfg); |
|
|
|
while test_suite loop |
|
rst <= '1'; |
|
wait for clk_period; |
|
rst <= '0'; |
|
|
|
d1.is_signed <= '0'; |
|
d1.neg_result <= '0'; |
|
d1.is_extended <= '0'; |
|
d1.is_32bit <= '0'; |
|
d1.is_modulus <= '0'; |
|
d1.valid <= '0'; |
|
|
|
if run("Test interface") then |
|
d1.valid <= '1'; |
|
d1.dividend <= x"0000000010001000"; |
|
d1.divisor <= x"0000000000001111"; |
|
|
|
wait for clk_period; |
|
check_false(?? d2.valid, result("for valid")); |
|
|
|
d1.valid <= '0'; |
|
|
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
|
|
check_true(?? d2.valid, result("for valid")); |
|
check_equal(d2.write_reg_data, 16#f001#); |
|
|
|
wait for clk_period; |
|
check_false(?? d2.valid, result("for valid")); |
|
|
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
check_false(?? d2.valid, result("for valid")); |
|
|
|
d1.valid <= '0'; |
|
|
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
|
|
check_true(?? d2.valid, result("for valid")); |
|
check_equal(d2.write_reg_data, 16#f001#); |
|
|
|
wait for clk_period; |
|
check_false(?? d2.valid, result("for valid")); |
|
|
|
elsif run("Test divd") then |
|
divd_loop : for dlength in 1 to 8 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); |
|
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); |
|
d1.is_signed <= '1'; |
|
d1.neg_result <= ra(63) xor rb(63); |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then |
|
behave_rt := ppc_divd(ra, rb); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divd")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divdu") then |
|
divdu_loop : for dlength in 1 to 8 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra; |
|
d1.divisor <= rb; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
behave_rt := ppc_divdu(ra, rb); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divdu")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divde") then |
|
divde_loop : for vlength in 1 to 8 loop |
|
for dlength in 1 to vlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); |
|
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); |
|
d1.is_signed <= '1'; |
|
d1.neg_result <= ra(63) xor rb(63); |
|
d1.is_extended <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
d128 := ra & x"0000000000000000"; |
|
q128 := std_ulogic_vector(signed(d128) / signed(rb)); |
|
if q128(127 downto 63) = x"0000000000000000" & '0' or |
|
q128(127 downto 63) = x"ffffffffffffffff" & '1' then |
|
behave_rt := q128(63 downto 0); |
|
end if; |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divde")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divdeu") then |
|
divdeu_loop : for vlength in 1 to 8 loop |
|
for dlength in 1 to vlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra; |
|
d1.divisor <= rb; |
|
d1.is_extended <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if unsigned(rb) > unsigned(ra) then |
|
d128 := ra & x"0000000000000000"; |
|
q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb)); |
|
behave_rt := q128(63 downto 0); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divdeu")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divw") then |
|
divw_loop : for dlength in 1 to 4 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); |
|
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); |
|
d1.is_signed <= '1'; |
|
d1.neg_result <= ra(63) xor rb(63); |
|
d1.is_32bit <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then |
|
behave_rt := ppc_divw(ra, rb); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divw")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divwu") then |
|
divwu_loop : for dlength in 1 to 4 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra; |
|
d1.divisor <= rb; |
|
d1.is_32bit <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
behave_rt := ppc_divwu(ra, rb); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divwu")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divwe") then |
|
divwe_loop : for vlength in 1 to 4 loop |
|
for dlength in 1 to vlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; |
|
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); |
|
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); |
|
d1.is_signed <= '1'; |
|
d1.neg_result <= ra(63) xor rb(63); |
|
d1.is_32bit <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
q64 := std_ulogic_vector(signed(ra) / signed(rb)); |
|
if q64(63 downto 31) = x"00000000" & '0' or |
|
q64(63 downto 31) = x"ffffffff" & '1' then |
|
behave_rt := x"00000000" & q64(31 downto 0); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divwe")); |
|
end if; |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test divweu") then |
|
divweu_loop : for vlength in 1 to 4 loop |
|
for dlength in 1 to vlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 32)) & x"00000000"; |
|
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra; |
|
d1.divisor <= rb; |
|
d1.is_32bit <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then |
|
behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb)); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for divweu")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test modsd") then |
|
modsd_loop : for dlength in 1 to 8 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); |
|
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); |
|
d1.is_signed <= '1'; |
|
d1.neg_result <= ra(63); |
|
d1.is_modulus <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
behave_rt := std_ulogic_vector(signed(ra) rem signed(rb)); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for modsd")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test modud") then |
|
modud_loop : for dlength in 1 to 8 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra; |
|
d1.divisor <= rb; |
|
d1.is_modulus <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb)); |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for modud")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test modsw") then |
|
modsw_loop : for dlength in 1 to 4 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(signed(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(signed(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra)); |
|
d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb)); |
|
d1.is_signed <= '1'; |
|
d1.neg_result <= ra(63); |
|
d1.is_32bit <= '1'; |
|
d1.is_modulus <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0))); |
|
if rem32(31) = '0' then |
|
behave_rt := x"00000000" & rem32; |
|
else |
|
behave_rt := x"ffffffff" & rem32; |
|
end if; |
|
end if; |
|
check_equal(d2.write_reg_data, behave_rt, result("for modsw")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
|
|
elsif run("Test moduw") then |
|
moduw_loop : for dlength in 1 to 4 loop |
|
for vlength in 1 to dlength loop |
|
for i in 0 to 100 loop |
|
ra := std_ulogic_vector(resize(unsigned(rnd.RandSlv(dlength * 8)), 64)); |
|
rb := std_ulogic_vector(resize(unsigned(rnd.RandSlv(vlength * 8)), 64)); |
|
|
|
d1.dividend <= ra; |
|
d1.divisor <= rb; |
|
d1.is_32bit <= '1'; |
|
d1.is_modulus <= '1'; |
|
d1.valid <= '1'; |
|
|
|
wait for clk_period; |
|
|
|
d1.valid <= '0'; |
|
for j in 0 to 66 loop |
|
wait for clk_period; |
|
if d2.valid = '1' then |
|
exit; |
|
end if; |
|
end loop; |
|
check_true(?? d2.valid, result("for valid")); |
|
|
|
behave_rt := (others => '0'); |
|
if rb /= x"0000000000000000" then |
|
behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0))); |
|
end if; |
|
check_equal(d2.write_reg_data(31 downto 0), behave_rt(31 downto 0), result("for moduw")); |
|
end loop; |
|
end loop; |
|
end loop; |
|
end if; |
|
end loop; |
|
|
|
test_runner_cleanup(runner); |
|
end process; |
|
end behave;
|
|
|