📄 alu.vhd
字号:
---------------------------------------------------------------------------
---------------------------------------------------------------------------
--组原 Group 6;
--运算器ALU;
--在其中实现了加,减,乘(带符号和不带符号),除(带符号和不带符号),模;
--十进制的加减,取补运算,与、或等逻辑运算,共16个运算功能;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.myconstantlibrary.all;
entity alu is
port (
w_ctl : in std_logic; --字/字节控制信号
r,s : in std_logic_vector(15 downto 0); --运算数据
c_n : in std_logic; --最低位进
alu_ctl : in std_logic_vector(3 downto 0); --运算选择
f1 : buffer std_logic_vector(15 downto 0);
f2 : buffer std_logic_vector(15 downto 0);
c_n_32,c_n_16, c_n_8, ovr, zero, sign
: buffer std_logic --输出标志位(最高位进位,溢出,零,符号)
);
end alu;
architecture archalu of alu is
signal r1,s1,fl: std_logic_vector( 16 downto 0);
signal fh: std_logic_vector( 15 downto 0);
begin
process (r,s,c_n,alu_ctl,w_ctl)
variable temp: std_logic_vector(32 downto 0);
variable fl_temp : std_logic_vector(14 downto 0);
variable fh_temp : std_logic_vector(15 downto 0);
variable x: std_logic_vector(16 downto 0);
variable y: std_logic_vector(32 downto 0);
variable x4: std_logic_vector(3 downto 0);
variable x8: std_logic_vector(7 downto 0);
variable x12: std_logic_vector(11 downto 0);
variable x16: std_logic_vector(15 downto 0);
variable vc_n_32,vc_n_16, vc_n_8, vovr, vzero, vsign : std_logic;
variable ix,iy: integer;
begin
---初始化
temp := "000000000000000000000000000000000";
x(16) := '0';
y(32) := '0';
fh <= "0000000000000000";
if alu_ctl=subr or alu_ctl=subs then ---若为减法高位补符
if w_ctl='1' then r1<=r(15) & r(15 downto 0);s1<=s(15) & s(15 downto 0);
else r1<="00000000" & r(7) & r( 7 downto 0);s1<="00000000" & s(7) & s( 7 downto 0);
end if; ---不是减法,高位补零
else
if w_ctl='1' then
r1<='0'& r(15 downto 0);
s1<='0'& s(15 downto 0);
else
r1<="000000000"& r(7 downto 0);
s1<="000000000"& s(7 downto 0);
end if;
end if;
---选择运算功能进行计算
case alu_ctl is
when add => if c_n='0' then fl<=r1+s1;else fl<=r1+s1+1;end if; ---r+s
when subr => if c_n='0' then fl<=r1-s1;else fl<=r1-s1+1;end if; ---r-s
when subs => if c_n='0' then fl<=s1-r1;else fl<=s1-r1+1;end if; ---s-r
when mul => ---带符号乘法
if w_ctl='0' then
temp := r1(6 downto 0) * s1(6 downto 0);
fl(14 downto 0) <= temp(14 downto 0);
fl(16)<=temp(16); --溢出判断
fl(15) <= r1(7) XOR s1(7); ---符号位
else
temp := r1(14 downto 0) * s1(14 downto 0);
fl(15 downto 0) <= temp(15 downto 0);
fl(16)<=temp(32); --溢出判断
fh(14 downto 0) <= temp(30 downto 16);
fh(15) <= r1(15) XOR s1(15); ---符号位
end if;
when imul => ---无符号乘法
if w_ctl='0' then
temp := r1(7 downto 0) * s1(7 downto 0);
fl(15 downto 0) <= temp(15 downto 0);
fl(16)<=temp(16); --溢出判断
else
temp := r1 * s1;
fl(15 downto 0) <= temp(15 downto 0);
fl(16)<=temp(32); --溢出判断
fh <= temp(31 downto 16);
end if;
when div => ---带符号除法
if r="0000000000000000" then vovr:='1';---除数为零溢出,跳出
else
vovr:='0';
if w_ctl='1' then ---字运算
fl(15) <= r(15) xor s(15);
ix := conv_integer(s(14 downto 0));
iy := conv_integer(r(14 downto 0)&"00000000000000");
for i in 14 downto 0 loop ---求商
if ix >= iy then fl_temp(i) := '1'; ix := ix - iy;
else fl_temp(i) := '0';
end if;
iy := iy / 2;
end loop;
for i in 0 to 15 loop ---取余数
iy := ix /2;
if iy * 2 = ix then fh_temp(i) := '0';
else fh_temp(i) := '1';
end if;
ix := ix /2;
end loop;
if r(15)='1' and s(15)='0' then
fl(14 downto 0)<=fl_temp(14 downto 0)+1;
fh(14 downto 0)<=r-fh_temp;
else
fl(14 downto 0)<=fl_temp(14 downto 0);
fh<=fh_temp;
end if;
else ---字节运算
fl(7) <= r(7) xor s(7);
ix := conv_integer(s(6 downto 0));
iy := conv_integer(r(6 downto 0)&"000000");
for i in 6 downto 0 loop
if ix >= iy then fl_temp(i) := '1';ix := ix - iy;
else fl_temp(i) := '0';
end if;
iy := iy / 2;
end loop;
for i in 0 to 7 loop
iy := ix /2;
if iy * 2 = ix then fh_temp(i) := '0';
else fh_temp(i) := '1';
end if;
ix := ix /2;
end loop;
if r(7)='1' and s(7)='0' then
fl(6 downto 0)<=fl_temp(6 downto 0)+1;
fh<=r-fh_temp;
else
fl(6 downto 0)<=fl_temp(6 downto 0);
fh<=fh_temp;
end if;
end if;
end if;
when idiv => ---无符号除法
if r="0000000000000000" then vovr:='1';---除数为零溢出,跳出
else
vovr:='0';
if w_ctl='1' then
ix := conv_integer(s);
iy := conv_integer(r&"000000000000000");
for i in 15 downto 0 loop
if ix >= iy then fl(i) <= '1';ix := ix - iy;
else fl(i) <= '0';
end if;
iy := iy / 2;
end loop;
for i in 0 to 15 loop
iy := ix /2;
if iy * 2 = ix then fh(i) <= '0';
else fh(i) <= '1';
end if;
ix := ix /2;
end loop;
else
ix := conv_integer(s(7 downto 0));
iy := conv_integer(r(7 downto 0)&"0000000");
for i in 7 downto 0 loop ---求商
if ix >= iy then fl(i) <= '1';ix := ix - iy;
else fl(i) <= '0';
end if;
iy := iy / 2;
end loop;
for i in 0 to 7 loop ---求余数
iy := ix /2;
if iy * 2 = ix then fh(i) <= '0';
else fh(i) <= '1';
end if;
ix := ix /2;
end loop;
end if;
end if;
when inve=> ---反置
if w_ctl='1' then
for i in 15 downto 0 loop
fl(i) <= r(15-i);
end loop;
else
for i in 7 downto 0 loop
fl(i) <= r(7-i);
end loop;
end if;
when addbcd => ---BCD加
x := r1 + s1;
x4 := r1(3 downto 0) + s1(3 downto 0);
x8 := r1(7 downto 0) + s1(7 downto 0);
x12:= r1(11 downto 0) + s1(11 downto 0);
x16:= r1(15 downto 0) + s1(15 downto 0);
if x4 < r1(3 downto 0) then
x(3 downto 0) := x(3 downto 0) + "0110";
end if;
if x(3 downto 0) > "1001" then
x(3 downto 0) := x(3 downto 0) - "1010";
x(16 downto 0) := x(16 downto 0) + "00000000000010000";
end if;
if x8 < r(7 downto 0) then
x(7 downto 4) := x(7 downto 4) + "0110";
end if;
if x(7 downto 4) > "1001" then
x(7 downto 4) := x(7 downto 4) - "1010";
x(16 downto 0) := x(16 downto 0) + "00000000100000000";
end if;
if x12 < r(11 downto 0) then
x(11 downto 8) := x(11 downto 8) + "0110";
end if;
if x(11 downto 8) > "1001" then
x(11 downto 8) := x(11 downto 8) - "1010";
x(16 downto 0) := x(16 downto 0) + "00001000000000000";
end if;
if x16 < r(15 downto 0) then
x(15 downto 12) := x(15 downto 12) + "0110";
end if;
if x(15 downto 12) > "1001" then
x(15 downto 12) := x(15 downto 12) - "1010";
x(16 downto 0) := x(16 downto 0) + "10000000000000000";
end if;
fl <= x;
when subbcd => ---BCD减
x := r1 - s1;
if r1(3 downto 0) < s1(3 downto 0) then
x(16 downto 0) := x(16 downto 0) - "00000000000000110";
end if;
if r1(7 downto 0) < s1(7 downto 0) then
x(16 downto 0) := x(16 downto 0) - "00000000001100000";
end if;
if r1(11 downto 0) < s1(11 downto 0) then
x(16 downto 0) := x(16 downto 0) - "00000011000000000";
end if;
if r1(15 downto 0) < s1(15 downto 0) then
x(16 downto 0) := x(16 downto 0) - "00110000000000000";
end if;
fl <= x;
when orrs => fl(15 downto 0)<=r or s; ---或
when andrs => fl(15 downto 0)<=r and s; ---与
when notrs => fl(15 downto 0)<=(not r) and s ;
when exor => fl(15 downto 0)<=r xor s; ---异或
when exnor => fl(15 downto 0)<=not (r xor s);---同或
when negr => if w_ctl='0' then ---取补
if r(7)='1' then
fl<="000000000" & (not(r(7 downto 0))+1);
else
fl<="000000000" & r(7 downto 0);
end if;
else
if r(15)='1' then
fl<='0'&(not(r(15 downto 0))+1);
else
fl<='0' & r1(15 downto 0);
end if;
end if;
when others => fl<="00000000000000000";
end case;
--计算结果
if w_ctl='0' then
if (alu_ctl=mul or alu_ctl=imul) then f1<=fl(15 downto 0);
else f1<="00000000" & fl(7 downto 0);
end if;
else f1<=fl(15 downto 0);
end if;
f2<=fh;
--进位/借位标志
case alu_ctl is
when orrs | andrs | notrs | exor | exnor | negr | div | idiv | inve =>
vc_n_8:='0';vc_n_16:='0';vc_n_32:='0';
when mul | imul => if w_ctl='0' then vc_n_32:='0';vc_n_16:=fl(16);vc_n_8:='0';
else vc_n_32:=fl(16);vc_n_16:='0';vc_n_8:='0';
end if;
when others => vC_n_32:='0';
if w_ctl='0' then vc_n_8:=fl(8);vc_n_16:='0';
else vc_n_8:='0';vc_n_16:=fl(16);
end if;
end case;
--零标志
if f1="0000000000000000" and f2="0000000000000000" then
vzero:='1';
elsif alu_ctl=mul then
if (w_ctl='1' and f2(14 downto 0)="000000000000000" and f1="000000000000000")
or (w_ctl='0' and f1(14 downto 0)="000000000000000") then
vzero:='1';
else vzero:='0';
end if;
elsif alu_ctl=div then
if (w_ctl='1' and f1(14 downto 0)="000000000000000") or (w_ctl='0' and fl(6 downto 0)="0000000")then
vzero:='1';
else vzero:='0';
end if;
elsif f1="0000000000000000" then vzero:='1';
else vzero:='0';
end if;
--溢出标志
case alu_ctl is
when orrs | andrs | notrs | exor | exnor | negr | inve | add |addbcd | subbcd => vovr:='0';
when mul | imul => vovr:=fl(16);
when subr | subs => if w_ctl='0' then vovr:= fl(8)xor fl(7);
else vovr:= fl(16)xor fl(15);
end if;
when others =>NULL;
end case;
--符号标志
if (alu_ctl=mul or alu_ctl=imul) then
if w_ctl='0' then vsign:=f1(15);
else vsign:=f2(15);
end if;
elsif alu_ctl=subbcd then
if r1<s1 then vsign:='1'; else vsign:='0'; end if;
else
if w_ctl='0' then vsign:=f1(7);
else vsign:=f1(15);
end if;
end if;
c_n_32 <= vc_n_32;
c_n_16 <= vc_n_16;
c_n_8 <= vc_n_8;
zero <= vzero;
ovr <= vovr;
sign <= vsign;
end process;
end archalu;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -