altera_mf.vhd

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

VHD
1,443
字号
    if (pos >= 1) then
        read(str_line, str);
    end if;
end;
end ALTERA_COMMON_CONVERSION;
-- END OF PACKAGE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  altaccumulate
--
-- Description     :  Parameterized accumulator megafunction. The accumulator
-- performs an add function or a subtract function based on the add_sub
-- parameter. The input data can be signed or unsigned.
--
-- Limitation      : n/a
--
-- Results expected:  result - The results of add or subtract operation. Output
--                             port [width_out-1 .. 0] wide.
--                    cout   - The cout port has a physical interpretation as 
--                             the carry-out (borrow-in) of the MSB. The cout
--                             port is most meaningful for detecting overflow
--                             in unsigned operations. The cout port operates
--                             in the same manner for signed and unsigned
--                             operations.
--                    overflow - Indicates the accumulator is overflow.
--
---END_ENTITY_HEADER-----------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

-- BEGINNING OF ENTITY
entity altaccumulate is
    -- GENERIC DECLARATION
    generic (
        width_in           : integer := 4;      -- Required
        width_out          : integer := 8;      -- Required
        lpm_representation : string  := "UNSIGNED";
        extra_latency      : integer := 0;
        use_wys            : string  := "ON";
        lpm_hint           : string  := "UNUSED";
        lpm_type           : string  := "altaccumulate"
    );

    -- PORT DECLARATION
    port (
        -- INPUT PORT DECLARATION
        cin       : in std_logic := 'Z';
        data      : in std_logic_vector(width_in -1 downto 0);  -- Required port
        add_sub   : in std_logic := '1';
        clock     : in std_logic;   -- Required port
        sload     : in std_logic := '0';
        clken     : in std_logic := '1';
        sign_data : in std_logic := '0';
        aclr      : in std_logic := '0';

        -- OUTPUT PORT DECLARATION
        result    : out std_logic_vector(width_out -1 downto 0) := (others => '0'); -- Required port
        cout      : out std_logic := '0';
        overflow  : out std_logic := '0'
    );
end altaccumulate;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
architecture behaviour of altaccumulate is

-- TYPE DECLARATION
type pipeline is array (extra_latency-1 downto 0) of std_logic_vector (width_out+1 downto 0);

-- SIGNAL DECLARATION
signal temp_sum : std_logic_vector (width_out downto 0) := (others => '0');
signal cout_int : std_logic := '0';
signal overflow_int : std_logic := '0';
signal result_int : std_logic_vector (width_out+1 downto 0) := (others => '0');

signal result_pipe : pipeline := (others => (others => '0'));

signal head : integer := 0;

begin

    MSG: process
    begin
        if( width_in <= 0 ) then
            ASSERT FALSE
            REPORT "Error! Value of width_in parameter must be greater than 0."
            SEVERITY ERROR;
        end if;

        if( width_out <= 0 ) then
            ASSERT FALSE
            REPORT "Error! Value of width_out parameter must be greater than 0."
            SEVERITY ERROR;
        end if;
        
        if( extra_latency > width_out ) then
            ASSERT FALSE
            REPORT "Info: Value of extra_latency parameter should be lower than width_out parameter for better performance/utilization."
            SEVERITY NOTE;
        end if;
        
        if( width_in > width_out ) then
            ASSERT FALSE
            REPORT "Error! Value of width_in parameter should be lower than or equal to width_out."
            SEVERITY ERROR;
        end if;
        wait;
    end process MSG;

    -- PROCESS DECLARATION
    ADDSUB : process (data, add_sub, sload, cin, sign_data,
                      result_int (width_out-1 downto 0))

    -- VARIABLE DECLARATIOM
    variable fb_int : std_logic_vector (width_out downto 0) := (others => '0');
    variable data_int : std_logic_vector (width_out-1 downto 0) := (others => '0');
    variable zeropad : std_logic_vector ((width_out - width_in)-1 downto 0) := (others => '0');
    variable temp_sum_int : std_logic_vector (width_out downto 0) := (others => '0');
    variable cout_temp, borrow : std_logic;
    variable result_full : std_logic_vector (width_out downto 0);
    variable temp_sum_zero : std_logic_vector (width_out downto 0) := (others => '0');
    variable cin_int : std_logic;
    begin

        if ((LPM_REPRESENTATION = "SIGNED") or (sign_data = '1')) then
            zeropad := (others => data (width_in-1));
        else
            zeropad := (others => '0');
        end if;

        if (sload = '1') then
            fb_int := (others => '0');
        else
            fb_int := ('0' & result_int (width_out-1 downto 0));
        end if;

        if ((data (0) = '1') or (data (0) = '0')) then
            data_int := (zeropad & data);
        end if;

        -- If cin is omitted (i.e. cin = 'z'), cin default is 0 for add operation
        -- and 1 for subtract operation.
        if ((cin /= '0') and (cin /= '1')) then
            cin_int := not add_sub;
        else
            cin_int := cin;
        end if;

        if (sload = '1') then
            temp_sum_int := unsigned(temp_sum_zero) + unsigned(data_int);
        else
            if (add_sub = '1') then
                temp_sum_int := unsigned(temp_sum_zero) + unsigned(fb_int) +
                                unsigned(data_int) + cin_int;
                cout_temp := temp_sum_int(width_out);
            else
                borrow := not cin_int;
                if ((borrow /= '1') and (borrow /= '0')) then
                    borrow := '0';
                end if;

                temp_sum_int := unsigned(temp_sum_zero) + unsigned (fb_int) -
                                unsigned (data_int) - borrow;
                result_full := unsigned(temp_sum_zero) + unsigned(data_int) +
                               borrow;

                if (fb_int >= result_full) then
                    cout_temp :='1';
                else
                    cout_temp :='0';
                end if;
            end if;
        end if;

        if (sload = '0') then
            if ((LPM_REPRESENTATION = "SIGNED") or (sign_data = '1')) then
                overflow_int <= ((not (data (width_in-1) xor result_int (width_out -1))) xor (not (add_sub))) and
                                (result_int (width_out -1) xor temp_sum_int (width_out -1));
            else
                overflow_int <= not (add_sub xor cout_temp);
            end if;
        else
            overflow_int <= '0';
            cout_temp := not add_sub;
        end if;

        cout_int <= cout_temp;
        temp_sum <= temp_sum_int;

    end process ADDSUB;

    ACC: process (clock, aclr, cout_int)

    -- VARIABLE DECLARATIOM
    variable head_pipe : integer;
    variable full_res: std_logic_vector (width_out+1 downto 0);
    begin
        head_pipe := head;

        if (aclr = '1') then
            result <= (others => '0');
            result_int <= (others => '0');
            cout <= '0';
            overflow <= '0';
            result_pipe <= (others => (others => '0'));
        else
            if (extra_latency = 0) then
                cout <= cout_int;
            end if;

            if (clock'event and (clock = '1' and clken = '1')) then
                if (extra_latency > 0) then
                    result_pipe (head_pipe) <= (result_int (width_out+1) &
                                                cout_int &
                                                result_int (width_out-1 downto 0));

                    head_pipe := (head_pipe + 1) mod (extra_latency);
                    if (head_pipe = head) then
                        full_res := (result_int (width_out+1) &
                                     cout_int &
                                     result_int (width_out-1 downto 0));
                    else
                        full_res := result_pipe (head_pipe);
                    end if;
                    cout <= full_res (width_out);
                    result <= full_res (width_out-1 downto 0);
                    overflow <= full_res (width_out+1);
                else
                    overflow <= overflow_int;
                    result <= temp_sum (width_out-1 downto 0);
                end if;
                result_int <= (overflow_int & cout_int &
                               temp_sum (width_out-1 downto 0));
            end if;
        end if;

        head <= head_pipe;
    end process ACC;

end behaviour; -- End behaviour of altaccumulate
-- END OF ARCHITECTURE

-- --------------------------------------------------------------------------
-- Module Name      : altmult_accum
--
-- Description      : a*b + x (MAC)
--
-- Limitation       : Stratix DSP block
--
-- Results expected : signed & unsigned, maximum of 3 pipelines(latency) each.
--
-- --------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity altmult_accum is
    generic (

        -- ---------------------
        -- PARAMETER DECLARATION
        -- ---------------------
        width_a                        : integer := 1;
        width_b                        : integer := 1;
        width_result                   : integer := 2;
        input_reg_a                    : string  := "CLOCK0";
        input_aclr_a                   : string  := "ACLR3";
        input_reg_b                    : string  := "CLOCK0";
        input_aclr_b                   : string  := "ACLR3";
        addnsub_reg                    : string  := "CLOCK0";
        addnsub_aclr                   : string  := "ACLR3";
        addnsub_pipeline_reg           : string  := "CLOCK0";
        addnsub_pipeline_aclr          : string  := "ACLR3";
        accum_direction                : string  := "ADD";
        accum_sload_reg                : string  := "CLOCK0";
        accum_sload_aclr               : string  := "ACLR3";
        accum_sload_pipeline_reg       : string  := "CLOCK0";
        accum_sload_pipeline_aclr      : string  := "ACLR3";
        representation_a               : string  := "UNSIGNED";
        sign_reg_a                     : string  := "CLOCK0";
        sign_aclr_a                    : string  := "ACLR3";
        sign_pipeline_reg_a            : string  := "CLOCK0";
        sign_pipeline_aclr_a           : string  := "ACLR3";
        representation_b               : string  := "UNSIGNED";
        sign_reg_b                     : string  := "CLOCK0";

⌨️ 快捷键说明

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