⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pre_norm_arch.vhd

📁 使用VHDL语言描述的单精度浮点处理器。源代码来自国外网站。可实现单精度浮点数的加减乘运算。
💻 VHD
字号:
LIBRARY ieee ;USE ieee.std_logic_1164.ALL;USE ieee.std_logic_misc.ALL;USE ieee.std_logic_unsigned.ALL;USE ieee.std_logic_arith.ALL;--USE ieee.numeric_std.ALL;--USE ieee.numeric_bit.ALL;ENTITY pre_norm IS   PORT(       add              : IN     std_logic  ;      clk              : IN     std_logic  ;      opa              : IN     std_logic_vector (31 downto 0) ;      opa_nan          : IN     std_logic  ;      opb              : IN     std_logic_vector (31 downto 0) ;      opb_nan          : IN     std_logic  ;      rmode            : IN     std_logic_vector (1 downto 0) ;      exp_dn_out       : OUT    std_logic_vector (7 downto 0) ;      fasu_op          : OUT    std_logic  ;      fracta_out       : OUT    std_logic_vector (26 downto 0) ;      fractb_out       : OUT    std_logic_vector (26 downto 0) ;      nan_sign         : OUT    std_logic  ;      result_zero_sign : OUT    std_logic  ;      sign             : OUT    std_logic    );END pre_norm ;ARCHITECTURE arch OF pre_norm IS        signal signa, signb : std_logic ;    signal signd_sel : std_logic_vector(2 DOWNTO 0) ;    signal add_d_sel : std_logic_vector(2 DOWNTO 0) ;    signal expa, expb : std_logic_vector (7 downto 0);    signal fracta, fractb : std_logic_vector (22 downto 0);    signal expa_lt_expb : std_logic ;    signal fractb_lt_fracta : std_logic ;    signal exp_small, exp_large : std_logic_vector (7 downto 0);    signal exp_diff : std_logic_vector (7 downto 0);    signal adj_op : std_logic_vector (22 downto 0);    signal adj_op_tmp : std_logic_vector (26 downto 0);    signal adj_op_out : std_logic_vector (26 downto 0);    signal fracta_n, fractb_n : std_logic_vector (26 downto 0);    signal fracta_s, fractb_s : std_logic_vector (26 downto 0);    signal sign_d : std_logic ;    signal add_d : std_logic ;    signal expa_dn, expb_dn : std_logic ;    signal sticky : std_logic ;    signal add_r, signa_r, signb_r : std_logic ;    signal exp_diff_sft : std_logic_vector (4 downto 0);    signal exp_lt_27 : std_logic ;    signal op_dn : std_logic ;    signal adj_op_out_sft : std_logic_vector (26 downto 0);    signal fracta_lt_fractb, fracta_eq_fractb : std_logic ;    signal nan_sign1 : std_logic ;    signal exp_diff1, exp_diff1a, exp_diff2 : std_logic_vector (7 downto 0);        BEGIN    signa <= opa(31);    signb <= opb(31);    expa <= opa(30 downto 23);    expb <= opb(30 downto 23);    fracta <= opa(22 downto 0);    fractb <= opb(22 downto 0);    expa_lt_expb <= '1' WHEN (expa > expb) ELSE '0';    expa_dn <= NOT or_reduce(expa);    expb_dn <= NOT or_reduce(expb);    -- Calculate the difference between the smaller and larger exponent    exp_small <= expb WHEN (expa_lt_expb = '1') ELSE expa;    exp_large <= expa WHEN (expa_lt_expb = '1') ELSE expb;    exp_diff1 <= exp_large - exp_small;    exp_diff1a <= exp_diff1 - '1';    -- if one of the exponents is zero then exp_diff1a else exp_diff1    exp_diff2 <= exp_diff1a WHEN ((expa_dn OR expb_dn) = '1') ELSE                 exp_diff1;    -- exp_diff is 0 if both exponents are zero    exp_diff <= X"00" WHEN ((expa_dn AND expb_dn) = '1') ELSE                exp_diff2;    PROCESS (clk)    BEGIN         IF clk'event AND clk = '1' THEN            IF ((add_d = '0') AND  (expa = expb) AND  (fracta = fractb)) THEN                exp_dn_out <= X"00";            ELSE                exp_dn_out <= exp_large;            END IF;        END IF;    END PROCESS;    -- Adjust the smaller fraction        op_dn <= expb_dn WHEN (expa_lt_expb = '1') ELSE expa_dn;    adj_op <= fractb WHEN (expa_lt_expb = '1') ELSE fracta;    adj_op_tmp <= (NOT op_dn) & adj_op & "000";    -- adj_op_out is 27 bits wide, so can only be shifted    -- 27 bits to the right (8'd27)    exp_lt_27 <= '1' WHEN (exp_diff  > "00011011") ELSE '0';    exp_diff_sft <= "11011" WHEN (exp_lt_27 = '1') ELSE exp_diff(4 downto 0);    -- adj_op_tmp_bitvec <= STD_LOGIC_VECTORtoBIT_VECTOR(adj_op_tmp);    -- adj_op_out_sft <= To_StdLogicVector(adj_op_tmp_bitvec SRL conv_integer(exp_diff_sft));    -- (conv_integer(exp_diff_sft));    adj_op_out_sft <= shr(adj_op_tmp,exp_diff_sft);    adj_op_out <= adj_op_out_sft(26 DOWNTO 1) &                  (adj_op_out_sft(0) OR sticky);    -- Get truncated portion (sticky bit)    PROCESS (exp_diff_sft,adj_op_tmp)    BEGIN        CASE exp_diff_sft IS             WHEN "00000" => sticky <= '0';            WHEN "00001" => sticky <= adj_op_tmp(0);             WHEN "00010" => sticky <= or_reduce(adj_op_tmp(1 downto 0));            WHEN "00011" => sticky <= or_reduce(adj_op_tmp(2 downto 0));            WHEN "00100" => sticky <= or_reduce(adj_op_tmp(3 downto 0));            WHEN "00101" => sticky <= or_reduce(adj_op_tmp(4 downto 0));            WHEN "00110" => sticky <= or_reduce(adj_op_tmp(5 downto 0));            WHEN "00111" => sticky <= or_reduce(adj_op_tmp(6 downto 0));            WHEN "01000" => sticky <= or_reduce(adj_op_tmp(7 downto 0));            WHEN "01001" => sticky <= or_reduce(adj_op_tmp(8 downto 0));            WHEN "01010" => sticky <= or_reduce(adj_op_tmp(9 downto 0));            WHEN "01011" => sticky <= or_reduce(adj_op_tmp(10 downto 0));            WHEN "01100" => sticky <= or_reduce(adj_op_tmp(11 downto 0));            WHEN "01101" => sticky <= or_reduce(adj_op_tmp(12 downto 0));            WHEN "01110" => sticky <= or_reduce(adj_op_tmp(13 downto 0));            WHEN "01111" => sticky <= or_reduce(adj_op_tmp(14 downto 0));            WHEN "10000" => sticky <= or_reduce(adj_op_tmp(15 downto 0));            WHEN "10001" => sticky <= or_reduce(adj_op_tmp(16 downto 0));            WHEN "10010" => sticky <= or_reduce(adj_op_tmp(17 downto 0));            WHEN "10011" => sticky <= or_reduce(adj_op_tmp(18 downto 0));            WHEN "10100" => sticky <= or_reduce(adj_op_tmp(19 downto 0));            WHEN "10101" => sticky <= or_reduce(adj_op_tmp(20 downto 0));            WHEN "10110" => sticky <= or_reduce(adj_op_tmp(21 downto 0));            WHEN "10111" => sticky <= or_reduce(adj_op_tmp(22 downto 0));            WHEN "11000" => sticky <= or_reduce(adj_op_tmp(23 downto 0));            WHEN "11001" => sticky <= or_reduce(adj_op_tmp(24 downto 0));            WHEN "11010" => sticky <= or_reduce(adj_op_tmp(25 downto 0));            WHEN "11011" => sticky <= or_reduce(adj_op_tmp(26 downto 0));            WHEN OTHERS => sticky <= '0';        END CASE;            END PROCESS;    -- Select operands for add/sub (recover hidden bit)    fracta_n <= ((NOT expa_dn) & fracta & "000") WHEN (expa_lt_expb = '1') else                adj_op_out;    fractb_n <= adj_op_out WHEN (expa_lt_expb = '1') else                ((NOT expb_dn) & fractb & "000");    -- Sort operands (for sub only)    fractb_lt_fracta <= '1' WHEN (fractb_n > fracta_n) ELSE '0';    fracta_s <= fractb_n WHEN (fractb_lt_fracta = '1') ELSE fracta_n;    fractb_s <= fracta_n WHEN (fractb_lt_fracta = '1') ELSE fractb_n;        PROCESS (clk)    BEGIN         IF clk'event AND clk = '1' THEN            fracta_out <= fracta_s;            fractb_out <= fractb_s;        END IF;    END PROCESS;    -- Determine sign for the output    -- sign: 0=Positive Number; 1=Negative Number    signd_sel <= signa & signb & add;    PROCESS (signd_sel, fractb_lt_fracta)    BEGIN         CASE signd_sel IS             -- Add            WHEN "001" => sign_d <= '0';            WHEN "011" => sign_d <= fractb_lt_fracta;            WHEN "101" => sign_d <= NOT fractb_lt_fracta;            WHEN "111" => sign_d <= '1';                                        -- Sub                      WHEN "000" => sign_d <= fractb_lt_fracta;            WHEN "010" => sign_d <= '0';            WHEN "100" => sign_d <= '1';            WHEN "110" => sign_d <= NOT fractb_lt_fracta;            WHEN OTHERS => sign_d <= 'X';        END CASE;    END PROCESS;            PROCESS (clk)    BEGIN         IF clk'event AND clk = '1' THEN            sign <= sign_d;            -- Fix sign for ZERO result            signa_r <= signa;            signb_r <= signb;            add_r <= add;            result_zero_sign <= ( add_r AND  signa_r AND  signb_r) OR                                (NOT add_r AND  signa_r AND NOT signb_r) OR                                ( add_r AND (signa_r OR  signb_r) AND                                  (rmode(1) AND rmode(0))) OR                                (NOT add_r AND NOT (signa_r xor signb_r) AND                                 (rmode(1) AND rmode(0)));        END IF;    END PROCESS;    -- Fix sign for NAN result    PROCESS (clk)    BEGIN         IF clk'event AND clk = '1' THEN            IF (fracta < fractb) THEN                fracta_lt_fractb <= '1';            ELSE                fracta_lt_fractb <= '0';            END IF;            IF fracta = fractb THEN                fracta_eq_fractb <= '1';            ELSE                fracta_eq_fractb <= '0';            END IF;            IF ((opa_nan AND opb_nan) = '1') THEN                nan_sign <= nan_sign1;            ELSIF (opb_nan = '1') THEN                nan_sign <= signb_r;                ELSE                nan_sign <= signa_r;            END IF;        END IF;    END PROCESS;         nan_sign1 <= (signa_r AND signb_r) WHEN (fracta_eq_fractb = '1') ELSE                 signb_r WHEN (fracta_lt_fractb = '1') ELSE                 signa_r;    add_d_sel <= signa & signb & add;    -- Decode Add/Sub operation    -- add: 1=Add; 0=Subtract    PROCESS (add_d_sel)    BEGIN         CASE add_d_sel IS             -- Add            WHEN "001" => add_d <= '1';            WHEN "011" => add_d <= '0';            WHEN "101" => add_d <= '0';            WHEN "111" => add_d <= '1';                                 -- Sub             WHEN "000" => add_d <= '0';            WHEN "010" => add_d <= '1';            WHEN "100" => add_d <= '1';            WHEN "110" => add_d <= '0';            WHEN OTHERS => add_d <= 'X';        END CASE;    END PROCESS;    PROCESS (clk)    BEGIN         IF clk'event AND clk = '1' THEN            fasu_op <= add_d;        END IF;    END PROCESS;    END arch;

⌨️ 快捷键说明

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