forked from cores/microwatt
				
			Merge branch 'divider' of https://github.com/paulusmack/microwatt
						commit
						b57325ce29
					
				@ -0,0 +1,133 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.common.all;
 | 
			
		||||
use work.decode_types.all;
 | 
			
		||||
use work.crhelpers.all;
 | 
			
		||||
 | 
			
		||||
entity divider is
 | 
			
		||||
    port (
 | 
			
		||||
        clk   : in std_logic;
 | 
			
		||||
        rst   : in std_logic;
 | 
			
		||||
        d_in  : in Decode2ToDividerType;
 | 
			
		||||
        d_out : out DividerToWritebackType
 | 
			
		||||
        );
 | 
			
		||||
end entity divider;
 | 
			
		||||
 | 
			
		||||
architecture behaviour of divider is
 | 
			
		||||
    signal dend       : std_ulogic_vector(127 downto 0);
 | 
			
		||||
    signal div        : unsigned(63 downto 0);
 | 
			
		||||
    signal quot       : std_ulogic_vector(63 downto 0);
 | 
			
		||||
    signal result     : std_ulogic_vector(63 downto 0);
 | 
			
		||||
    signal sresult    : std_ulogic_vector(63 downto 0);
 | 
			
		||||
    signal qbit       : std_ulogic;
 | 
			
		||||
    signal running    : std_ulogic;
 | 
			
		||||
    signal count      : unsigned(6 downto 0);
 | 
			
		||||
    signal neg_result : std_ulogic;
 | 
			
		||||
    signal is_modulus : std_ulogic;
 | 
			
		||||
    signal is_32bit   : std_ulogic;
 | 
			
		||||
    signal rc         : std_ulogic;
 | 
			
		||||
    signal write_reg  : std_ulogic_vector(4 downto 0);
 | 
			
		||||
 | 
			
		||||
    function compare_zero(value : std_ulogic_vector(63 downto 0); is_32 : std_ulogic)
 | 
			
		||||
        return std_ulogic_vector is
 | 
			
		||||
    begin
 | 
			
		||||
        if is_32 = '1' then
 | 
			
		||||
            if value(31) = '1' then
 | 
			
		||||
                return "1000";
 | 
			
		||||
            elsif unsigned(value(30 downto 0)) > 0 then
 | 
			
		||||
                return "0100";
 | 
			
		||||
            else
 | 
			
		||||
                return "0010";
 | 
			
		||||
            end if;
 | 
			
		||||
        else
 | 
			
		||||
            if value(63) = '1' then
 | 
			
		||||
                return "1000";
 | 
			
		||||
            elsif unsigned(value(62 downto 0)) > 0 then
 | 
			
		||||
                return "0100";
 | 
			
		||||
            else
 | 
			
		||||
                return "0010";
 | 
			
		||||
            end if;
 | 
			
		||||
        end if;
 | 
			
		||||
    end function compare_zero;
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
    divider_0: process(clk)
 | 
			
		||||
    begin
 | 
			
		||||
        if rising_edge(clk) then
 | 
			
		||||
            if rst = '1' then
 | 
			
		||||
                dend <= (others => '0');
 | 
			
		||||
                div <= (others => '0');
 | 
			
		||||
                quot <= (others => '0');
 | 
			
		||||
                running <= '0';
 | 
			
		||||
                count <= "0000000";
 | 
			
		||||
            elsif d_in.valid = '1' then
 | 
			
		||||
                if d_in.is_extended = '1' then
 | 
			
		||||
                    dend <= d_in.dividend & x"0000000000000000";
 | 
			
		||||
                else
 | 
			
		||||
                    dend <= x"0000000000000000" & d_in.dividend;
 | 
			
		||||
                end if;
 | 
			
		||||
                div <= unsigned(d_in.divisor);
 | 
			
		||||
                quot <= (others => '0');
 | 
			
		||||
                write_reg <= d_in.write_reg;
 | 
			
		||||
                neg_result <= d_in.neg_result;
 | 
			
		||||
                is_modulus <= d_in.is_modulus;
 | 
			
		||||
                is_32bit <= d_in.is_32bit;
 | 
			
		||||
                rc <= d_in.rc;
 | 
			
		||||
                count <= "0000000";
 | 
			
		||||
                running <= '1';
 | 
			
		||||
            elsif running = '1' then
 | 
			
		||||
                if count = "0111111" then
 | 
			
		||||
                    running <= '0';
 | 
			
		||||
                end if;
 | 
			
		||||
                if dend(127) = '1' or unsigned(dend(126 downto 63)) >= div then
 | 
			
		||||
                    dend <= std_ulogic_vector(unsigned(dend(126 downto 63)) - div) &
 | 
			
		||||
                            dend(62 downto 0) & '0';
 | 
			
		||||
                    quot <= quot(62 downto 0) & '1';
 | 
			
		||||
                    count <= count + 1;
 | 
			
		||||
                elsif dend(127 downto 56) = x"000000000000000000" and count(5 downto 3) /= "111" then
 | 
			
		||||
                    -- consume 8 bits of zeroes in one cycle
 | 
			
		||||
                    dend <= dend(119 downto 0) & x"00";
 | 
			
		||||
                    quot <= quot(55 downto 0) & x"00";
 | 
			
		||||
                    count <= count + 8;
 | 
			
		||||
                else
 | 
			
		||||
                    dend <= dend(126 downto 0) & '0';
 | 
			
		||||
                    quot <= quot(62 downto 0) & '0';
 | 
			
		||||
                    count <= count + 1;
 | 
			
		||||
                end if;
 | 
			
		||||
            else
 | 
			
		||||
                count <= "0000000";
 | 
			
		||||
            end if;
 | 
			
		||||
        end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    divider_1: process(all)
 | 
			
		||||
    begin
 | 
			
		||||
        d_out <= DividerToWritebackInit;
 | 
			
		||||
        d_out.write_reg_nr <= write_reg;
 | 
			
		||||
 | 
			
		||||
        if count(6) = '1' then
 | 
			
		||||
            d_out.valid <= '1';
 | 
			
		||||
            d_out.write_reg_enable <= '1';
 | 
			
		||||
            if is_modulus = '1' then
 | 
			
		||||
                result <= dend(127 downto 64);
 | 
			
		||||
            else
 | 
			
		||||
                result <= quot;
 | 
			
		||||
            end if;
 | 
			
		||||
            if neg_result = '1' then
 | 
			
		||||
                sresult <= std_ulogic_vector(- signed(result));
 | 
			
		||||
            else
 | 
			
		||||
                sresult <= result;
 | 
			
		||||
            end if;
 | 
			
		||||
            d_out.write_reg_data <= sresult;
 | 
			
		||||
            if rc = '1' then
 | 
			
		||||
                d_out.write_cr_enable <= '1';
 | 
			
		||||
                d_out.write_cr_mask <= num_to_fxm(0);
 | 
			
		||||
                d_out.write_cr_data <= compare_zero(sresult, is_32bit) & x"0000000";
 | 
			
		||||
            end if;
 | 
			
		||||
        end if;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
end architecture behaviour;
 | 
			
		||||
@ -0,0 +1,613 @@
 | 
			
		||||
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.glibc_random.all;
 | 
			
		||||
use work.ppc_fx_insns.all;
 | 
			
		||||
 | 
			
		||||
entity divider_tb is
 | 
			
		||||
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               : Decode2ToDividerType;
 | 
			
		||||
    signal d2               : DividerToWritebackType;
 | 
			
		||||
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);
 | 
			
		||||
    begin
 | 
			
		||||
        rst <= '1';
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        rst <= '0';
 | 
			
		||||
 | 
			
		||||
        d1.valid <= '1';
 | 
			
		||||
        d1.write_reg <= "10001";
 | 
			
		||||
        d1.dividend <= x"0000000010001000";
 | 
			
		||||
        d1.divisor  <= x"0000000000001111";
 | 
			
		||||
        d1.neg_result <= '0';
 | 
			
		||||
        d1.is_32bit <= '0';
 | 
			
		||||
        d1.is_extended <= '0';
 | 
			
		||||
        d1.is_modulus <= '0';
 | 
			
		||||
        d1.rc <= '0';
 | 
			
		||||
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert d2.valid = '0';
 | 
			
		||||
 | 
			
		||||
        d1.valid <= '0';
 | 
			
		||||
 | 
			
		||||
        for j in 0 to 64 loop
 | 
			
		||||
            wait for clk_period;
 | 
			
		||||
            if d2.valid = '1' then
 | 
			
		||||
                exit;
 | 
			
		||||
            end if;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        assert d2.valid = '1';
 | 
			
		||||
        assert d2.write_reg_enable = '1';
 | 
			
		||||
        assert d2.write_reg_nr = "10001";
 | 
			
		||||
        assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
 | 
			
		||||
        assert d2.write_cr_enable = '0';
 | 
			
		||||
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert d2.valid = '0' report "valid";
 | 
			
		||||
 | 
			
		||||
        d1.valid <= '1';
 | 
			
		||||
        d1.rc <= '1';
 | 
			
		||||
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert d2.valid = '0' report "valid";
 | 
			
		||||
 | 
			
		||||
        d1.valid <= '0';
 | 
			
		||||
 | 
			
		||||
        for j in 0 to 64 loop
 | 
			
		||||
            wait for clk_period;
 | 
			
		||||
            if d2.valid = '1' then
 | 
			
		||||
                exit;
 | 
			
		||||
            end if;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        assert d2.valid = '1';
 | 
			
		||||
        assert d2.write_reg_enable = '1';
 | 
			
		||||
        assert d2.write_reg_nr = "10001";
 | 
			
		||||
        assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
 | 
			
		||||
        assert d2.write_cr_enable = '1';
 | 
			
		||||
        assert d2.write_cr_mask = "10000000";
 | 
			
		||||
        assert d2.write_cr_data = x"40000000" report "cr data is " & to_hstring(d2.write_cr_data);
 | 
			
		||||
 | 
			
		||||
        wait for clk_period;
 | 
			
		||||
        assert d2.valid = '0';
 | 
			
		||||
 | 
			
		||||
        -- test divd
 | 
			
		||||
        report "test divd";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    if ra(63) = '1' then
 | 
			
		||||
                        d1.dividend <= std_ulogic_vector(- signed(ra));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.dividend <= ra;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if rb(63) = '1' then
 | 
			
		||||
                        d1.divisor <= std_ulogic_vector(- signed(rb));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.divisor <= rb;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if ra(63) = rb(63) then
 | 
			
		||||
                        d1.neg_result <= '0';
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.neg_result <= '1';
 | 
			
		||||
                    end if;
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := ppc_divd(ra, rb);
 | 
			
		||||
                        assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
 | 
			
		||||
                            report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divd";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divdu
 | 
			
		||||
        report "test divdu";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    d1.dividend <= ra;
 | 
			
		||||
                    d1.divisor <= rb;
 | 
			
		||||
                    d1.neg_result <= '0';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := ppc_divdu(ra, rb);
 | 
			
		||||
                        assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
 | 
			
		||||
                            report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divdu";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divde
 | 
			
		||||
        report "test divde";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    if ra(63) = '1' then
 | 
			
		||||
                        d1.dividend <= std_ulogic_vector(- signed(ra));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.dividend <= ra;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if rb(63) = '1' then
 | 
			
		||||
                        d1.divisor <= std_ulogic_vector(- signed(rb));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.divisor <= rb;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if ra(63) = rb(63) then
 | 
			
		||||
                        d1.neg_result <= '0';
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.neg_result <= '1';
 | 
			
		||||
                    end if;
 | 
			
		||||
                    d1.is_extended <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if unsigned(d1.divisor) > unsigned(d1.dividend) then
 | 
			
		||||
                        d128 := ra & x"0000000000000000";
 | 
			
		||||
                        q128 := std_ulogic_vector(signed(d128) / signed(rb));
 | 
			
		||||
                        behave_rt := q128(63 downto 0);
 | 
			
		||||
                        assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
 | 
			
		||||
                            report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
 | 
			
		||||
                        assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divde";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divdeu
 | 
			
		||||
        report "test divdeu";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    d1.dividend <= ra;
 | 
			
		||||
                    d1.divisor <= rb;
 | 
			
		||||
                    d1.neg_result <= '0';
 | 
			
		||||
                    d1.is_extended <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if unsigned(d1.divisor) > unsigned(d1.dividend) then
 | 
			
		||||
                        d128 := ra & x"0000000000000000";
 | 
			
		||||
                        q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
 | 
			
		||||
                        behave_rt := q128(63 downto 0);
 | 
			
		||||
                        assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
 | 
			
		||||
                            report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
 | 
			
		||||
                        assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divdeu";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divw
 | 
			
		||||
        report "test divw";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    if ra(63) = '1' then
 | 
			
		||||
                        d1.dividend <= std_ulogic_vector(- signed(ra));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.dividend <= ra;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if rb(63) = '1' then
 | 
			
		||||
                        d1.divisor <= std_ulogic_vector(- signed(rb));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.divisor <= rb;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if ra(63) = rb(63) then
 | 
			
		||||
                        d1.neg_result <= '0';
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.neg_result <= '1';
 | 
			
		||||
                    end if;
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := ppc_divw(ra, rb);
 | 
			
		||||
                        assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
 | 
			
		||||
                            report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divw";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divwu
 | 
			
		||||
        report "test divwu";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    d1.dividend <= ra;
 | 
			
		||||
                    d1.divisor <= rb;
 | 
			
		||||
                    d1.neg_result <= '0';
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := ppc_divwu(ra, rb);
 | 
			
		||||
                        assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
 | 
			
		||||
                            report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divwu";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divwe
 | 
			
		||||
        report "test divwe";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 32)) & x"00000000";
 | 
			
		||||
                    rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    if ra(63) = '1' then
 | 
			
		||||
                        d1.dividend <= std_ulogic_vector(- signed(ra));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.dividend <= ra;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if rb(63) = '1' then
 | 
			
		||||
                        d1.divisor <= std_ulogic_vector(- signed(rb));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.divisor <= rb;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if ra(63) = rb(63) then
 | 
			
		||||
                        d1.neg_result <= '0';
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.neg_result <= '1';
 | 
			
		||||
                    end if;
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if unsigned(d1.divisor(31 downto 0)) > unsigned(d1.dividend(63 downto 32)) then
 | 
			
		||||
                        behave_rt := std_ulogic_vector(signed(ra) / signed(rb));
 | 
			
		||||
                        assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
 | 
			
		||||
                            report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
 | 
			
		||||
                        assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divwe";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test divweu
 | 
			
		||||
        report "test divweu";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 32)) & x"00000000";
 | 
			
		||||
                    rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    d1.dividend <= ra;
 | 
			
		||||
                    d1.divisor <= rb;
 | 
			
		||||
                    d1.neg_result <= '0';
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if unsigned(d1.divisor(31 downto 0)) > unsigned(d1.dividend(63 downto 32)) then
 | 
			
		||||
                        behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
 | 
			
		||||
                        assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
 | 
			
		||||
                            report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
 | 
			
		||||
                        assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for divweu";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test modsd
 | 
			
		||||
        report "test modsd";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    if ra(63) = '1' then
 | 
			
		||||
                        d1.dividend <= std_ulogic_vector(- signed(ra));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.dividend <= ra;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if rb(63) = '1' then
 | 
			
		||||
                        d1.divisor <= std_ulogic_vector(- signed(rb));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.divisor <= rb;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    d1.neg_result <= ra(63);
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '0';
 | 
			
		||||
                    d1.is_modulus <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
 | 
			
		||||
                        assert behave_rt = d2.write_reg_data
 | 
			
		||||
                            report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for modsd";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test modud
 | 
			
		||||
        report "test modud";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    d1.dividend <= ra;
 | 
			
		||||
                    d1.divisor <= rb;
 | 
			
		||||
                    d1.neg_result <= '0';
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '0';
 | 
			
		||||
                    d1.is_modulus <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
 | 
			
		||||
                        assert behave_rt = d2.write_reg_data
 | 
			
		||||
                            report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for modud";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test modsw
 | 
			
		||||
        report "test modsw";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    if ra(63) = '1' then
 | 
			
		||||
                        d1.dividend <= std_ulogic_vector(- signed(ra));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.dividend <= ra;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    if rb(63) = '1' then
 | 
			
		||||
                        d1.divisor <= std_ulogic_vector(- signed(rb));
 | 
			
		||||
                    else
 | 
			
		||||
                        d1.divisor <= rb;
 | 
			
		||||
                    end if;
 | 
			
		||||
                    d1.neg_result <= ra(63);
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '1';
 | 
			
		||||
                    d1.is_modulus <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := x"00000000" & std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
 | 
			
		||||
                        assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
 | 
			
		||||
                            report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for modsw";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        -- test moduw
 | 
			
		||||
        report "test moduw";
 | 
			
		||||
        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(pseudorand(dlength * 8)), 64));
 | 
			
		||||
                    rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
 | 
			
		||||
 | 
			
		||||
                    d1.dividend <= ra;
 | 
			
		||||
                    d1.divisor <= rb;
 | 
			
		||||
                    d1.neg_result <= '0';
 | 
			
		||||
                    d1.is_extended <= '0';
 | 
			
		||||
                    d1.is_32bit <= '1';
 | 
			
		||||
                    d1.is_modulus <= '1';
 | 
			
		||||
                    d1.valid <= '1';
 | 
			
		||||
 | 
			
		||||
                    wait for clk_period;
 | 
			
		||||
 | 
			
		||||
                    d1.valid <= '0';
 | 
			
		||||
                    for j in 0 to 64 loop
 | 
			
		||||
                        wait for clk_period;
 | 
			
		||||
                        if d2.valid = '1' then
 | 
			
		||||
                            exit;
 | 
			
		||||
                        end if;
 | 
			
		||||
                    end loop;
 | 
			
		||||
                    assert d2.valid = '1';
 | 
			
		||||
 | 
			
		||||
                    if rb /= x"0000000000000000" then
 | 
			
		||||
                        behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
 | 
			
		||||
                        assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
 | 
			
		||||
                            report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
 | 
			
		||||
                        assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
 | 
			
		||||
                            report "bad CR setting for moduw";
 | 
			
		||||
                    end if;
 | 
			
		||||
                end loop;
 | 
			
		||||
            end loop;
 | 
			
		||||
        end loop;
 | 
			
		||||
 | 
			
		||||
        assert false report "end of test" severity failure;
 | 
			
		||||
        wait;
 | 
			
		||||
    end process;
 | 
			
		||||
end behave;
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue