altera_mf.vhd

来自「一个非常好的dc使用书籍 一个非常好的dc使用书籍」· VHDL 代码 · 共 1,443 行 · 第 1/5 页

VHD
1,443
字号
        sign_aclr_b                    : string  := "ACLR3";
        sign_pipeline_reg_b            : string  := "CLOCK0";
        sign_pipeline_aclr_b           : string  := "ACLR3";
        multiplier_reg                 : string  := "CLOCK0";
        multiplier_aclr                : string  := "ACLR3";
        output_reg                     : string  := "CLOCK0";
        output_aclr                    : string  := "ACLR3";
        extra_multiplier_latency       : integer := 0;
        extra_accumulator_latency      : integer := 0;
        dedicated_multiplier_circuitry : string  := "AUTO";
        dsp_block_balancing            : string  := "AUTO";
        lpm_hint                       : string  := "UNUSED";
        lpm_type                       : string  := "altmult_accum"
    );

    port (

        -- ----------------
        -- PORT DECLARATION
        -- ----------------

        -- input data ports
        dataa       : in std_logic_vector(width_a -1 downto 0);
        datab       : in std_logic_vector(width_b -1 downto 0);
        -- control signals
        addnsub   : in std_logic := 'Z';
        accum_sload : in std_logic := '0';
        signa       : in std_logic := 'Z';
        signb       : in std_logic := 'Z';
        -- clock ports
        clock0      : in std_logic := '1';
        clock1      : in std_logic := '1';
        clock2      : in std_logic := '1';
        clock3      : in std_logic := '1';
        -- clock enable ports
        ena0        : in std_logic := '1';
        ena1        : in std_logic := '1';
        ena2        : in std_logic := '1';
        ena3        : in std_logic := '1';
        -- clear ports
        aclr0       : in std_logic := '0';
        aclr1       : in std_logic := '0';
        aclr2       : in std_logic := '0';
        aclr3       : in std_logic := '0';
        -- output ports
        result      : out std_logic_vector(width_result -1 downto 0) := (others => '0');
        overflow    : out std_logic :='0';
        scanouta    : out std_logic_vector (width_a -1 downto 0) := (others => '0');
        scanoutb    : out std_logic_vector (width_b -1 downto 0) := (others => '0')
    );
end altmult_accum;


architecture behaviour of altmult_accum is

    -- -------------------------------------
    -- INTERNAL TEMPLATE DECLARATION
    -- -------------------------------------
    type pipeline_accum is array (extra_accumulator_latency downto 0) of std_logic_vector (width_result downto 0);
    type pipeline_multi is array (extra_multiplier_latency downto 0) of std_logic_vector (width_a + width_b + 4 downto 0);

    -- -------------------------------------
    -- INTERNAL SIGNALS AND TYPE DECLARATION
    -- -------------------------------------
    signal temp_sum           : std_logic_vector (width_result + 1 downto 0):= (others => '0');
    signal mult_a             : std_logic_vector (width_a -1 downto 0):= (others => '0');
    signal mult_b             : std_logic_vector (width_b -1 downto 0):= (others => '0');
    signal mult_res           : std_logic_vector (width_a + width_b -1 downto 0):= (others => '0');
    signal acc_sload_reg      : std_logic := '0';
    signal accum_sload_pipe   : std_logic := '0';
    signal sign_a_reg         : std_logic := '0';
    signal sign_a_pipe        : std_logic := '0';
    signal sign_a_latent      : std_logic := '0';
    signal sign_b_reg         : std_logic := '0';
    signal sign_b_pipe        : std_logic := '0';
    signal sign_b_latent      : std_logic := '0';
    signal addsub_reg         : std_logic := '0';
    signal addsub_pipe        : std_logic := '0';
    signal addsub_latent      : std_logic := '0';
    signal accum_sload_latent : std_logic := '0';

    signal result_pipe : pipeline_accum := (others => (others => '0'));
    signal mult_pipe   : pipeline_multi := (others => (others => '0'));

    signal temp_mult       : std_logic_vector (width_a + width_b -1 downto 0):= (others => '0');
    signal mult_out_latent : std_logic_vector (width_a + width_b -1 downto 0):= (others => '0');
    signal result_int      : std_logic_vector (width_result -1 downto 0):= (others => '0');
    signal temp_mult_zero  : std_logic_vector (width_a + width_b downto 0):= (others => '0');
    signal mult_full       : std_logic_vector (width_a + width_b +4 downto 0):= (others => '0');

    signal mult_signed, do_add, temp_mult_signed : std_logic := '0';
    signal head_result, head_mult                : integer   := 0;

    begin

        scanouta           <= mult_a;
        scanoutb           <= mult_b;
        sign_a_latent      <= mult_full (width_a + width_b + 4) when extra_multiplier_latency >0 else sign_a_reg;
        sign_b_latent      <= mult_full (width_a + width_b + 3) when extra_multiplier_latency >0 else sign_b_reg;
        accum_sload_latent <= mult_full (width_a + width_b + 2) when extra_multiplier_latency >0 else acc_sload_reg;
        addsub_latent      <= mult_full (width_a + width_b + 1) when extra_multiplier_latency >0 else addsub_reg;
        mult_signed        <= mult_full (width_a + width_b) when extra_multiplier_latency >0 else temp_mult_signed;
        mult_out_latent    <= mult_full (width_a + width_b -1 downto 0) when extra_multiplier_latency >0 else temp_mult;


        -- Parameter Checking
        process (clock0, clock1, clock2, clock3)
        begin
            if ((dedicated_multiplier_circuitry /= "AUTO") and 
                (dedicated_multiplier_circuitry /= "YES") and 
                (dedicated_multiplier_circuitry /= "NO")) then
                assert false
                report "Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."
                severity error;
            end if;

            if (width_result < (width_a + width_b)) then
                assert false
                report "Error: width_result cannot be less than (width_a + width_b)"
                severity error;
            end if;

            if (width_a <= 0) then
                assert false
                report "Error: width_a must be greater than 0."
                severity error;
            end if;

            if (width_b <= 0) then
                assert false
                report "Error: width_b must be greater than 0."
                severity error;
            end if;

            if (width_result <= 0) then
                assert false
                report "Error: width_result must be greater than 0."
                severity error;
            end if;
            
        end process;

        -- ----------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set mult_a)
        -- The signal registered is dataa
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if input_reg_a is unregistered and
        --       dataa changes value
        -- ---------------------------------------------------------------------------
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3, dataa)
        begin
            if (input_reg_a = "UNREGISTERED") then
            mult_a <= dataa;
            else
                if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
                    ((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
                    ((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
                    ((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                    mult_a <= (others => '0');
                elsif (((input_reg_a = "CLOCK0") and (clock0= '1') and clock0'event and (ena0 ='1')) or
                       ((input_reg_a = "CLOCK1") and (clock1= '1') and clock1'event and (ena1 ='1')) or
                       ((input_reg_a = "CLOCK2") and (clock2= '1') and clock2'event and (ena2 ='1')) or
                       ((input_reg_a = "CLOCK3") and (clock3= '1') and clock3'event and (ena3 ='1'))) then
                    mult_a <= dataa;
                end if;
            end if;
        end process;


        -- ----------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set mult_b)
        -- The signal registered is datab
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if input_reg_b is unregistered and
        --       datab changes value
        -- ---------------------------------------------------------------------------
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3, datab)
        begin
            if (input_reg_b = "UNREGISTERED") then
                mult_b <= datab;
            else
                if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
                    ((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
                    ((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
                    ((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                    mult_b <= (others => '0');
                elsif (((input_reg_b = "CLOCK0") and (clock0= '1') and clock0'event and (ena0 ='1')) or
                       ((input_reg_b = "CLOCK1") and (clock1= '1') and clock1'event and (ena1 ='1')) or
                       ((input_reg_b = "CLOCK2") and (clock2= '1') and clock2'event and (ena2 ='1')) or
                       ((input_reg_b = "CLOCK3") and (clock3= '1') and clock3'event and (ena3 ='1'))) then
                    mult_b <= datab;
                end if;
            end if;
        end process;


        -- ------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set addsub_reg)
        -- The signal registered is addnsub
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_reg is unregistered and
        --       addnsub changes value
        -- ------------------------------------------------------------------------------
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3, addnsub)
        begin
            if (addnsub_reg = "UNREGISTERED") then
                addsub_reg <= addnsub;
            else
                if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
                    ((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
                    ((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
                    ((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
                    addsub_reg <= '0';
                elsif (((addnsub_reg = "CLOCK0") and (clock0= '1') and clock0'event and (ena0 ='1')) or
                       ((addnsub_reg = "CLOCK1") and (clock1= '1') and clock1'event and (ena1 ='1')) or
                       ((addnsub_reg = "CLOCK2") and (clock2= '1') and clock2'event and (ena2 ='1')) or
                       ((addnsub_reg = "CLOCK3") and (clock3= '1') and clock3'event and (ena3 ='1'))) then
                    addsub_reg <= addnsub;
                end if;
            end if;
        end process;


        -- ------------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set addsub_pipe)
        -- The signal registered is addnsub_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_pipeline_reg is unregistered and
        --       addsub_latent changes value
        -- ------------------------------------------------------------------------------------
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3, addsub_latent)
        begin
            if (addnsub_pipeline_reg = "UNREGISTERED") then
                addsub_pipe <= addsub_latent;
            else
                if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                    ((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                    ((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                    ((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                    addsub_pipe <= '0';
                elsif (((addnsub_pipeline_reg = "CLOCK0") and (clock0= '1') and clock0'event and (ena0 ='1')) or
                       ((addnsub_pipeline_reg = "CLOCK1") and (clock1= '1') and clock1'event and (ena1 ='1')) or
                       ((addnsub_pipeline_reg = "CLOCK2") and (clock2= '1') and clock2'event and (ena2 ='1')) or
                       ((addnsub_pipeline_reg = "CLOCK3") and (clock3= '1') and clock3'event and (ena3 ='1'))) then
                    addsub_pipe <= addsub_latent;
                end if;
            end if;
        end process;

        -- ---------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set acc_sload_reg)
        -- The signal registered is accum_sload
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_reg is unregistered and
        --       accum_sload changes value
        -- ---------------------------------------------------------------------------------
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (accum_sload_reg = "UNREGISTERED") then
                acc_sload_reg <= accum_sload;
            else
                if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
                    ((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
                    ((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
                    ((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
                    acc_sload_reg <= '0';
                elsif (((accum_sload_reg = "CLOCK0") and (clock0= '1') and clock0'event and (ena0 ='1')) or
                       ((accum_sload_reg = "CLOCK1") and (clock1= '1') and clock1'event and (ena1 ='1')) or
                       ((accum_sload_reg = "CLOCK2") and (clock2= '1') and clock2'event and (ena2 ='1')) or
                       ((accum_sload_reg = "CLOCK3") and (clock3= '1') and clock3'event and (ena3 ='1'))) then
                    acc_sload_reg <= accum_sload;
                end if;
            end if;
        end process;


        -- ------------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set accum_sload_pipe)
        -- The signal registered is accum_sload_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_pipeline_reg
        -- is unregistered and accum_sload_latent changes value
        -- ------------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?