📄 example16_7.vhd
字号:
library ieee; use ieee.std_logic_1164.all;
--use ieee.std_logic_arith.all;
--use ieee.std_logic_unsigned.all;
package mypackage is
constant p: natural := 4;
constant B: natural := 10;
constant B_div_2: natural := 5;
subtype digit is natural range 0 to B-1;
type digit_vector is array (integer range <>) of digit;
type mybit_vector is array (integer range <>) of std_logic;
end mypackage;
library ieee; use ieee.std_logic_1164.all;
--use ieee.std_logic_arith.all;
--use ieee.std_logic_unsigned.all;
use work.mypackage.all;
entity alignment is
port (
sign1, sign2, operation: in std_logic;
e1, e2: in integer;
s1, s2: in digit_vector(0 downto -p);
dif: inout natural;
sign, new_sign2: out std_logic;
e, new_e2: out natural;
aligned_s1, aligned_s2: out digit_vector(0 downto -(p+3))
);
end alignment;
architecture behavior of alignment is
signal actual_sign2: std_logic;
signal s, new_s2: digit_vector(0 downto -p);
signal shift_length: natural;
signal sticky: digit;
begin
actual_sign2 <= operation xor sign2;
process(sign1, actual_sign2, e1, e2, s1, s2, s)
begin
if e1 < e2 then
dif <= e2 - e1; e <= e2; new_e2 <= e1; sign <= actual_sign2; new_sign2 <= sign1; s <= s2; new_s2 <= s1;
else
dif <= e1 - e2; e <= e1; new_e2 <= e2; sign <= sign1; new_sign2 <= actual_sign2; s <= s1; new_s2 <= s2;
end if;
aligned_s1(-(p+1)) <= 0; aligned_s1(-(p+2)) <= 0; aligned_s1(-(p+3)) <= 0;
for i in 0 downto -p loop aligned_s1(i) <= s(i); end loop;
end process;
barrel_shifter: process(dif, shift_length, new_s2, sticky)
variable a: digit_vector(0 downto -(2*p+3));
variable acc_or: digit;
begin
for i in -(p+1) downto -(2*p+3) loop a(i) := 0; end loop;
for i in 0 downto -p loop a(i) := new_s2(i); end loop;
if dif < p+3 then shift_length <= dif; else shift_length <= p+3; end if;
if shift_length > 0 then
for j in 1 to shift_length loop
for i in -(2*p+3) to -1 loop a(i) := a(i+1); end loop;
a(0) := 0;
end loop;
end if;
acc_or := 0;
for i in -(p+3) downto -(2*p+2) loop if (a(i) > 0) or (acc_or > 0) then acc_or := 1; end if; end loop;
sticky <= acc_or;
aligned_s2 <= a(0 downto -(p+2))&sticky;
end process barrel_shifter;
end behavior;
library ieee; use ieee.std_logic_1164.all;
use work.mypackage.all;
entity test_alignment is end test_alignment;
architecture test of test_alignment is
component alignment
port (
sign1, sign2, operation: in std_logic;
e1, e2: in integer;
s1, s2: in digit_vector(0 downto -p);
dif: inout natural;
sign, new_sign2: out std_logic;
e, new_e2: out natural;
aligned_s1, aligned_s2: out digit_vector(0 downto -(p+3))
);
end component;
signal sign1, sign2, operation: std_logic;
signal e1, e2: integer;
signal s1, s2: digit_vector(0 downto -p);
signal dif: natural;
signal sign, new_sign2: std_logic;
signal e, new_e2: natural;
signal aligned_s1, aligned_s2: digit_vector(0 downto -(p+3));
begin
device_under_test: alignment port map
(sign1, sign2, operation, e1, e2, s1, s2, dif, sign, new_sign2, e, new_e2, aligned_s1, aligned_s2);
sign1 <= '0';
sign2 <= '0';
operation <= '0', '1' after 30 ns, '0' after 70 ns;
e1 <= 3, 3 after 10 ns, 3 after 20 ns, -1 after 30 ns, 3 after 40 ns, 4 after 50 ns;
e2 <= -1, 2 after 10 ns, 2 after 20 ns, 3 after 30 ns, 2 after 40 ns, 2 after 50 ns, -4 after 60 ns;
s1 <= (3,4,3,7,5), (9,4,3,7,5) after 10 ns, (9,4,3,7,5) after 20 ns, (3,4,5,1,8) after 30 ns, (1,0,0,1,4) after 40 ns,
(1,0,7,1,4) after 50 ns;
s2 <= (2,5,4,9,1), (8,6,2,4,7) after 10 ns, (5,6,2,4,7) after 20 ns, (7,2,4,7,1) after 30 ns, (9,9,4,9,1) after 40 ns,
(7,1,4,0,3) after 50 ns;
end test;
library ieee; use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.mypackage.all;
entity addition is
port (
sign, sign2: in std_logic;
aligned_s1, aligned_s2: in digit_vector(0 downto -(p+3));
int_operation: inout std_logic;
result, alt_result: out digit_vector(1 downto -(p+3))
);
end addition;
architecture rtl of addition is
signal long_s, long_s2: digit_vector(1 downto -(p+3));
signal inv_s, inv_s2: digit_vector(1 downto -(p+3));
signal carry1: mybit_vector(1 downto -(p+3));
signal carry2: mybit_vector(1 downto -(p+3));
begin
int_operation <= sign xor sign2;
long_s <= 0&aligned_s1;
long_s2 <= 0&aligned_s2;
inverters1: for i in -(p+3) to 1 generate
inv_s2(i) <= B-1-long_s2(i) when int_operation = '1' else long_s2(i); end generate;
inverters2: for i in -(p+3) to 1 generate inv_s(i) <= B-1-long_s(i); end generate;
carry1(-(p+3)) <= int_operation;
first_adder: for i in -(p+3) to 0 generate
carry1(i+1) <= '1' when long_s(i) + inv_s2(i) + conv_integer(carry1(i)) > B-1 else '0';
result(i) <= (long_s(i) + inv_s2(i) + conv_integer(carry1(i))) mod B;
end generate;
result(1) <= (long_s(1) + inv_s2(1) + conv_integer(carry1(1))) mod B;
carry2(-(p+3)) <= '1';
second_adder: for i in -(p+3) to 0 generate
carry2(i+1) <= '1' when inv_s(i) + long_s2(i) + conv_integer(carry2(i)) > B-1 else '0';
alt_result(i) <= (inv_s(i) + long_s2(i) + conv_integer(carry2(i))) mod B;
end generate;
alt_result(1) <= (inv_s(1) + long_s2(1) + conv_integer(carry2(1))) mod B;
end rtl;
library ieee; use ieee.std_logic_1164.all;
use work.mypackage.all;
entity test_addition is end test_addition;
architecture test of test_addition is
component addition
port (
sign, sign2: in std_logic;
aligned_s1, aligned_s2: in digit_vector(0 downto -(p+3));
int_operation: inout std_logic;
result, alt_result: out digit_vector(1 downto -(p+3))
);
end component;
signal sign, sign2, int_operation: std_logic;
signal aligned_s1, aligned_s2: digit_vector(0 downto -(p+3));
signal result, alt_result: digit_vector(1 downto -(p+3));
begin
device_under_test: addition port map
(sign, sign2, aligned_s1, aligned_s2, int_operation, result, alt_result);
sign <= '0';
sign2 <= '0', '1' after 30 ns;
aligned_s1 <= (3,4,3,7,5,0,0,0), (9,4,3,7,5,0,0,0) after 10 ns, (9,4,3,7,5,0,0,0) after 20 ns,
(0,0,0,0,3,4,5,1) after 30 ns, (1,0,0,1,4,0,0,0) after 40 ns, (1,0,7,1,4,0,0,0) after 50 ns;
aligned_s2 <= (0,0,0,0,2,5,4,1), (0,8,6,2,4,7,0,0) after 10 ns, (0,5,6,2,4,7,0,0) after 20 ns,
(7,2,4,7,1,0,0,0) after 30 ns, (0,9,9,4,9,1,0,0) after 40 ns, (0,0,7,1,4,0,3,0) after 50 ns;
end test;
library ieee; use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.mypackage.all;
entity normalization is
port (
sign, operation: in std_logic;
e, dif: in natural;
result, alt_result: in digit_vector(1 downto -(p+3));
new_sign, zero_flag: out std_logic;
new_s: out digit_vector(0 downto -(p+3));
new_e: out natural
);
end normalization;
architecture behavior of normalization is
signal result_div_B, s1, s, s2: digit_vector(0 downto -(p+3));
signal exp1, k, exp2: natural;
signal sign1, sign2: std_logic;
begin
divide_by_B: for i in -(p+3) to 0 generate result_div_B(i) <= result(i+1); end generate;
s1 <= result(0 downto -(p+3)) when result(1) = 0 else result_div_B;
exp1 <= e when result(1) = 0 else e+1;
sign1 <= sign;
s <= alt_result(0 downto -(p+3)) when (dif = 0) and (result(1) > 0) else result(0 downto -(p+3));
leading_zeroes: process(s)
variable var_k: natural;
begin
var_k := 0;
for i in 0 downto -(p+3) loop
if s(i) > 0 then exit; end if;
var_k := var_k+1;
end loop;
if var_k = p+4 then zero_flag <= '1'; else zero_flag <= '0'; end if;
k <= var_k;
end process leading_zeroes;
shift_k: process (s, k)
variable a: digit_vector(0 downto -(p+3));
begin
a := s;
if k > 0 then
for i in 1 to k loop
for i in 0 downto -(p+2) loop a(i) := a(i-1); end loop;
a(-(p+3)) := 0;
end loop;
end if;
s2 <= a;
end process shift_k;
exp2 <= e - k;
sign2 <= not(sign) when (dif = 0) and (result(1) > 0) else sign;
new_s <= s1 when operation = '0' else s2;
new_e <= exp1 when operation = '0' else exp2;
new_sign <= sign1 when operation = '0' else sign2;
end behavior;
library ieee; use ieee.std_logic_1164.all;
use work.mypackage.all;
entity test_normalization is end test_normalization;
architecture test of test_normalization is
component normalization
port (
sign, operation: in std_logic;
e, dif: in natural;
result, alt_result: in digit_vector(1 downto -(p+3));
new_sign, zero_flag: out std_logic;
new_s: out digit_vector(0 downto -(p+3));
new_e: out natural
);
end component;
signal sign, operation: std_logic;
signal e, dif: natural;
signal result, alt_result: digit_vector(1 downto -(p+3));
signal new_sign, zero_flag: std_logic;
signal new_s: digit_vector(0 downto -(p+3));
signal new_e: natural;
begin
device_under_test: normalization
port map (sign, operation, e, dif, result, alt_result, new_sign, zero_flag, new_s, new_e);
sign <= '0', '1' after 30 ns, '0' after 40 ns;
operation <= '0', '1' after 30 ns;
result <= (0,3,4,3,7,7,5,4,1), (1,0,2,9,9,9,7,0,0) after 10 ns, (0,9,9,9,9,9,7,0,0) after 20 ns,
(0,7,2,4,6,7,5,4,9) after 30 ns, (0,0,0,0,6,4,9,0,0) after 40 ns, (0,0,9,9,9,9,9,7,0) after 50 ns,
(9,9,9,9,9,8,9,9,9) after 60 ns;
alt_result <= (9,6,5,6,2,7,5,4,1), (9,1,4,2,4,9,7,0,0) after 10 ns, (9,1,1,2,4,9,7,0,0) after 20 ns,
(9,2,7,5,3,2,4,5,1) after 30 ns, (9,9,9,9,3,5,1,0,0) after 40 ns, (9,9,0,0,0,0,0,3,0) after 50 ns,
(0,0,0,0,0,0,9,9,9) after 60 ns;
e <= 3, 4 after 50 ns;
dif <= 4, 1 after 10 ns, 4 after 30 ns, 1 after 40 ns, 2 after 50 ns, 0 after 60 ns;
end test;
library ieee; use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.mypackage.all;
entity rounding is
port (
s: in digit_vector(0 downto -(p+3));
e: in natural;
new_s: out digit_vector(0 downto -p);
new_e: out natural
);
end rounding;
architecture behavior of rounding is
begin
process(s)
variable carry: digit_vector(1 downto -p);
variable sum: digit_vector(0 downto -p);
begin
if s(-(p+1)) < B_div_2 then new_s <= s(0 downto -p); new_e <= e;
elsif (s(-(p+1)) > B_div_2) or (s(-(p+2)) > 0) or (s(-(p+3)) > 0) or (s(-p) mod 2 = 1) then
--plus ulp
carry(-p) := 1;
for i in -p to 0 loop
if s(i) + carry(i) > B-1 then carry(i+1) := 1; else carry(i+1) := 0; end if;
sum(i) := (carry(i) + s(i)) mod B;
end loop;
------
if carry(1) = 1 then new_s(0) <= 1; for i in -1 downto -p loop new_s(i) <= 0; end loop; new_e <= e+1;
else new_s <= sum; new_e <= e; end if;
else new_s <= s(0 downto -p); new_e <= e;
end if;
end process;
end behavior;
library ieee; use ieee.std_logic_1164.all;
use work.mypackage.all;
entity test_rounding is end test_rounding;
architecture test of test_rounding is
component rounding
port (
s: in digit_vector(0 downto -(p+3));
e: in natural;
new_s: out digit_vector(0 downto -p);
new_e: out natural
);
end component;
signal s: digit_vector(0 downto -(p+3));
signal new_s: digit_vector(0 downto -p);
signal e, new_e: natural;
begin
device_under_test: rounding
port map (s, e, new_s, new_e);
s <= (9,9,9,9,9,5,0,0), (9,9,9,9,8,5,0,0) after 10 ns, (7,6,5,8,7,4,9,9) after 20 ns,
(9,9,9,9,9,4,9,9) after 30 ns, (5,6,7,3,7,5,0,0) after 40 ns, (4,6,7,5,4,5,0,0) after 50 ns;
e <= 3;
end test;
library ieee; use ieee.std_logic_1164.all;
--use ieee.std_logic_arith.all;
--use ieee.std_logic_unsigned.all;
use work.mypackage.all;
entity adder_subtractor is
port (
sign1, sign2, operation: in std_logic;
e1, e2: in integer;
s1, s2: in digit_vector(0 downto -p);
sign, zero_flag: out std_logic;
e: out natural;
s: out digit_vector(0 downto -p)
);
end adder_subtractor;
architecture circuit of adder_subtractor is
component alignment
port (
sign1, sign2, operation: in std_logic;
e1, e2: in integer;
s1, s2: in digit_vector(0 downto -p);
dif: inout natural;
sign, new_sign2: out std_logic;
e, new_e2: out natural;
aligned_s1, aligned_s2: out digit_vector(0 downto -(p+3))
);
end component;
component addition
port (
sign, sign2: in std_logic;
aligned_s1, aligned_s2: in digit_vector(0 downto -(p+3));
int_operation: inout std_logic;
result, alt_result: out digit_vector(1 downto -(p+3))
);
end component;
component normalization
port (
sign, operation: in std_logic;
e, dif: in natural;
result, alt_result: in digit_vector(1 downto -(p+3));
new_sign, zero_flag: out std_logic;
new_s: out digit_vector(0 downto -(p+3));
new_e: out natural
);
end component;
component rounding
port (
s: in digit_vector(0 downto -(p+3));
e: in natural;
new_s: out digit_vector(0 downto -p);
new_e: out natural
);
end component;
signal sign_a, sign2_a, int_operation: std_logic;
signal e_a, new_e2, dif, e_n: natural;
signal aligned_s1, aligned_s2, s_n: digit_vector(0 downto -(p+3));
signal result, alt_result: digit_vector(1 downto -(p+3));
begin
alignment_component: alignment port map (sign1, sign2, operation, e1, e2, s1, s2, dif, sign_a, sign2_a, e_a, new_e2,
aligned_s1, aligned_s2);
addition_component: addition port map (sign_a, sign2_a, aligned_s1, aligned_s2, int_operation, result, alt_result);
normalization_component: normalization port map (sign_a, int_operation, e_a, dif, result, alt_result,
sign, zero_flag, s_n, e_n);
rounding_component: rounding port map (s_n, e_n, s, e);
end circuit;
library ieee; use ieee.std_logic_1164.all;
use work.mypackage.all;
entity test_adder_subtractor is end test_adder_subtractor;
architecture test of test_adder_subtractor is
component adder_subtractor
port (
sign1, sign2, operation: in std_logic;
e1, e2: in integer;
s1, s2: in digit_vector(0 downto -p);
sign, zero_flag: out std_logic;
e: out natural;
s: out digit_vector(0 downto -p)
);
end component;
signal sign1, sign2, operation: std_logic;
signal e1, e2: integer;
signal s1, s2: digit_vector(0 downto -p);
signal sign, zero_flag: std_logic;
signal e: natural;
signal s: digit_vector(0 downto -p);
begin
device_under_test: adder_subtractor port map
(sign1, sign2, operation, e1, e2, s1, s2, sign, zero_flag, e, s);
sign1 <= '0';
sign2 <= '0';
operation <= '0', '1' after 30 ns, '0' after 70 ns, '1' after 80 ns;
e1 <= 3, 3 after 10 ns, 3 after 20 ns, -1 after 30 ns, 3 after 40 ns, 4 after 50 ns;
e2 <= -1, 2 after 10 ns, 2 after 20 ns, 3 after 30 ns, 2 after 40 ns, 2 after 50 ns, -4 after 60 ns, 4 after 70 ns;
s1 <= (3,4,3,7,5), (9,4,3,7,5) after 10 ns, (9,4,3,7,5) after 20 ns, (3,4,5,1,8) after 30 ns, (1,0,0,1,4) after 40 ns,
(1,0,7,1,4) after 50 ns;
s2 <= (2,5,4,9,1), (8,6,2,4,7) after 10 ns, (5,6,2,4,7) after 20 ns, (7,2,4,7,1) after 30 ns, (9,9,4,9,1) after 40 ns,
(7,1,4,0,3) after 50 ns, (1,0,7,1,4) after 70 ns ;
end test;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -