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

📄 alu.vhd

📁 组成原理的大作业
💻 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 + -