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

📄 alu.vhd

📁 实现16种运算的alu,包括+,-,+1,-1,与或非以及移位比较运算。经调试成功。
💻 VHD
字号:
--算逻运算单元:实现的功能有+、-、+1、-1、与、或、非、异或、六种移位运算以及算术比较运算。其
--中定义了临时变量c_tmp,z_tmp,z1_tmp分别用来表示C,Z符号位,最后赋值输出。
Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity alu is
	port(
		 reset,clk :	in std_logic;	--时钟信号,复位信号
		 OP:		    in std_logic_vector(3 downto 0);--操作码
		 sel:	        in std_logic;--寄存器选择
		 write:			in std_logic;--写入寄存器
		 C,Z:			out std_logic;--标志位
		 dinput:        in std_logic_vector(15 downto 0);--运算器的输入
		 result:        out std_logic_vector(15 downto 0)--运算器的输出
		);
end alu;

architecture behav of alu is
signal c_tmp :std_logic;		
signal z_tmp :std_logic;		--记录其它运算的临时信号
signal z1_tmp :std_logic;		--用于比较时的临时信号
signal A,B :std_logic_vector(15 downto 0);--定义运算器中的两个临时寄存器分别用来存放左右操作数
signal result_t: std_logic_vector(16 downto 0);--中间结果
begin
alu_proc:process(OP,dinput,reset,clk,sel,write)
begin
	if reset='0' then			--复位时,结果清零
		result_t<="00000000000000000";
	elsif (clk'event and clk='1') then 
		if write='1' then
			if sel='0' then
			    A<=dinput;	--时钟上升沿打入第一个寄存器
			elsif sel='1' then--打入第二个寄存器
				B<=dinput;
			end if;
		elsif write='0' then --当写信号为低电平时则进行运算	
	    case OP is			--十六种操作
		when "0000" =>
			result_t <= ('0' & A) + ('0' & B);	--加
		when "0001" =>
			result_t <= ('0' & A) +  '1';    --+1
 	    when "0010" =>
			result_t <= ('0' & A) - ('0' & B);  --减
		when "0011" =>
			result_t <= ('0' & A) -  '1';		---1
		when "0100" =>
			result_t <= ('0' & A) and ('0' & B);--与运算
		when "0101" =>
			result_t <= ('0' & A) or ('0' & B); --或运算
		when "0110" =>
			result_t <= not ('0' & B);          --非运算
		when "0111" =>
			result_t <= ('0' & A) xor('0' & B );--异或运算
		when "1000" =>
			result_t <= A(15 downto 0) & A(0);  --算术左移一位
		when "1001" =>
			result_t <= A(15 downto 0) & '0';   --逻辑左移一位
		when "1010" =>
			result_t <= A(15 downto 0) & A(15); --循环左移一位
		when "1011" =>
			result_t <='0'&B;			        --输出左操作数
		when "1100" =>
			result_t <= "00" & A(15 downto 1);  --逻辑右移一位
			c_tmp <= A(0);
		when "1101" =>
			result_t <= '0' & A(0) & A(15 downto 1);--循环右移一位
			c_tmp <= A(0);
		when "1110" =>
			result_t <= '0' & A(15)& A(15 downto 1);
			c_tmp <= A(0);							--算术右移一位
		when "1111" =>	
			result_t <=	('0' & A) - ('0' & B);
			if (result_t(16)= '1') then		--通过最高位是否溢出来判断符号位
				c_tmp<='1'; z1_tmp<='0';
			elsif (result_t = "00000000000000000") then
				c_tmp<='0'; z1_tmp<='1';
			else 
				c_tmp<='0'; z1_tmp<='0';
			end if;									--比较运算
		when others => 
			result_t <="XXXXXXXXXXXXXXXXX";
		end case;
		end if;
	end if;
end process;

result <= result_t(15 downto 0);
z_tmp <= (not result_t(15)) and (not result_t(14)) and
		 (not result_t(13)) and (not result_t(12)) and
		 (not result_t(11)) and (not result_t(10)) and
		 (not result_t(9)) and (not result_t(8)) and
		 (not result_t(7)) and (not result_t(6)) and
		 (not result_t(5)) and (not result_t(4)) and
		 (not result_t(3)) and (not result_t(2)) and
		 (not result_t(1)) and (not result_t(0));		--结果是否为全零

c_proc: Process(reset,clk,result_t,OP)
begin
    if reset = '0' then
		C <= '0';
	elsif clk'event and clk = '1' then
	    if (op(3 downto 2)/="11" and op(3 downto 0)/="1011") then  --移位和传送操作不影响C标志位
			C <= result_t(16);
		else 
			C <= c_tmp;
		end if;
	end if;
end process;

z_proc: process(reset,clk,z_tmp,OP)
begin
   if reset = '0' then
		Z <= '0';
	elsif clk'event and clk = '1' then
		if(OP (3 downto 0)/="1011")then
	    	if(OP (3 downto 2)/="11" )then      --移位和传送操作不影响Z标志位
				Z <= z_tmp;
			else
				Z <= z1_tmp;
			end if;
        end if;
	end if;
end process;

end behav;

⌨️ 快捷键说明

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