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

📄 calculation2.vhd

📁 用VHDL语言实现0--100范围内简单计算器功能的源代码
💻 VHD
字号:
--    0-100以内计算器的运算控制模块   --

--输入:两位BCD表示的运算数,操作码(+,-,x,/)和控制码(=,CLR)
--输出:BCD码表示的运算结果,当选择除法时有BCD码表示的余数输出
--功能:实现对运算数的加减乘除运算,除法时显示商和余数
--注意运算中若加法结果大于100,乘法结果在100与255之间,或者除数为0时
--本系统输出两个EE表示操作出错,此时需按下cLR复位,才能重新运算
--经仿真观察,该模块实现了上述预期功能
--作者:michael & ZMD
--时间:2006.10.25
--版本:V2.0

Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
Entity calculation2 is
Port(
	 clk: in std_logic; --时钟
	 operator:in std_logic_vector(7 downto 0);  --运算数(两位BCD)
	 add,sub,mult,divd:in std_logic;  --操作码(+,-,x,/)
	 clr,equ:in std_logic;  --控制码(clear,equal)
	 dataout:out std_logic_vector(7 downto 0);  --运算结果输出(两位BCD)
	 remainder:out std_logic_vector(7 downto 0); --余数输出(两位BCD)
	 showminus:out std_logic;   --显示负号控制
	 showremd:out std_logic);  --显示余数控制
end calculation2;

Architecture RTL of calculation2 is

signal disp1,disp0:std_logic_vector(3 downto 0); --显示的数据

type statetype is(state0,state1,state2,state3);  --定义了状态机的各种状态
signal state:statetype;

signal opt:integer range 0 to 4;  --操作码(+,-,X,/)

Begin

dataout<=disp1&disp0;

Process(add,sub,mult,divd)   --实时检测是否有操作码输入的进程
   variable control:std_logic_vector(3 downto 0);
    begin 
     control:=add&sub&mult&divd;
     case control is
       when "1000" =>opt<=1;
       when "0100" =>opt<=2;
       when "0010" =>opt<=3;
 	   when "0001" =>opt<=4;
       when others=>opt<=0;
     end case;
End process;

Process(clk,clr,operator,opt,equ)
    variable temp20,temp21,temp10,temp11:integer range 0 to 9; --两个运算数的BCD码暂存寄存器
    variable result0,result1:integer range 0 to 15;  --运算结果的BCD码表示寄存器
    variable opter:integer range 0 to 4;   --操作码寄存器
    variable data1,data2:integer range 0 to 100;  --两个运算数的二进制码表示寄存器
  
	variable innertemp00:integer range 0 to 255;  --运算结果的二进制码表示寄存器
	variable quot:std_logic_vector(6 downto 0);  --商的二进制码暂存器
	variable remd:integer range 0 to 100;   --余数的二进制码暂存器
	variable remd_h,remd_l:integer range 0 to 9; --余数的BCD码表示寄存器
	
    Begin
     if clr='1' then    --如果Clear键被按下了,系统清零 
      	temp20:=0;temp21:=0;temp10:=0;temp11:=0;
		result0:=0;result1:=0;remd:=0;
		remd_h:=0;remd_l:=0;
		showminus<='0';showremd<='0';
     	state<=state0;disp0<="0000";disp1<="0000";
  
      elsif clk'event and clk='1' then
         case state is
           when state0=>     --判断是否有操作码输入
               if opt/=0 then
                opter:=opt;state<=state1;
               else temp10:=conv_integer(operator(3 downto 0));
                    temp11:=conv_integer(operator(7 downto 4));
                    disp0<=operator(3 downto 0);
                    disp1<=operator(7 downto 4); 
					remainder<="00000000";
                    state<=state0;
               end if;
           when state1=>   --如果有操作码输入,并且equal键未被按下,则保存显示的运算数
               if equ='1' then 
                  state<=state2;
                else temp20:=conv_integer(operator(3 downto 0));
                     temp21:=conv_integer(operator(7 downto 4));
					disp0<=operator(3 downto 0);
                    disp1<=operator(7 downto 4);
                  state<=state1;
               end if;
           when state2=>    --若equal键被按下了,则进行各种运算
						data1:=temp11*10+temp10;  --将BCD 形式的运算数转换为二进制表示
						data2:=temp21*10+temp20;
						
              		 case opter is
							when 1 =>  --执行加法操作
									innertemp00:=data1+data2;
							when 2 =>  --执行减法操作
									if(data1<data2) then  --被减数<减数
										innertemp00:=data2-data1;
										showminus<='1';  --显示负号
									else
										innertemp00:=data1-data2;
									end if;
							when 3 =>  --执行乘法操作(乘积需限制在255以内,否则显示出错)
									innertemp00:=data1*data2;
							when 4=>  --执行除法操作
									quot:="0000000"; --初始化商值
			
									if(data2=0) then   --除数为0时的错误指示
										quot:="1111111";  --该数据传输到显示模块即显示两个"EE"
										remd:=100;      
									elsif(data1=0) then --被除数为0时
										quot:="0000000";
										remd:=0;
									elsif(data1<data2) then  --被除数<除数时
										quot:="0000000";
										remd:=data1;
									else                  --正常情况下,用移位相减法进行除法操作
										if(data1>=data2*64) then   --除数左移6位,比较
											data1:=data1-data2*64;
											quot(6):='1';
										end if;
										if(data1>=data2*32) then
											data1:=data1-data2*32;
											quot(5):='1';
										end if;
										if(data1>=data2*16) then
											data1:=data1-data2*16;
											quot(4):='1';
										end if;
										if(data1>=data2*8) then
											data1:=data1-data2*8;
											quot(3):='1';
										end if;
										if(data1>=data2*4) then
											data1:=data1-data2*4;
											quot(2):='1';
										end if;
										if(data1>=data2*2) then
											data1:=data1-data2*2;
											quot(1):='1';
										end if;
										if(data1>=data2) then
											data1:=data1-data2;
											quot(0):='1';
										end if;
										remd:=data1;   --被除数中减剩下的值,就是余数了
									end if;
									innertemp00:=conv_integer(quot);  --将商值转化为整数类型
									
                                    if(remd>=100) then   --将二进制表示的余数转化为BCD 表示
										remd_h:=0;
										remd_l:=0;
									elsif(remd>=90) then
										remd_h:=9;
										remd_l:=remd-90;
									elsif(remd>=80) then
										remd_h:=8;
										remd_l:=remd-80;
									elsif(remd>=70) then
										remd_h:=7;
										remd_l:=remd-70;
									elsif(remd>=60) then
										remd_h:=6;
										remd_l:=remd-60;
									elsif(remd>=50) then
										remd_h:=5;
										remd_l:=remd-50;
									elsif(remd>=40) then
										remd_h:=4;
										remd_l:=remd-40;
									elsif(remd>=30) then
										remd_h:=3;
										remd_l:=remd-30;
									elsif(remd>=20) then
										remd_h:=2;
										remd_l:=remd-20;
									elsif(remd>=10) then
										remd_h:=1;
										remd_l:=remd-10;
									else
										remd_h:=0;
										remd_l:=remd;
									end if;																			
									
									showremd<='1';  --显示余数					
								
						 when others=>null;
					 end case;
						
						if(innertemp00>=100) then   --将二进制表示的运算结果转化为二进制表示
							result1:=11;
							result0:=11;
						elsif(innertemp00>=90) then
							result1:=9;
							result0:=innertemp00-90;
						elsif(innertemp00>=80) then
							result1:=8;
							result0:=innertemp00-80;
						elsif(innertemp00>=70) then
							result1:=7;
							result0:=innertemp00-70;
						elsif(innertemp00>=60) then
							result1:=6;
							result0:=innertemp00-60;
						elsif(innertemp00>=50) then
							result1:=5;
							result0:=innertemp00-50;
						elsif(innertemp00>=40) then
							result1:=4;
							result0:=innertemp00-40;
						elsif(innertemp00>=30) then
							result1:=3;
							result0:=innertemp00-30;
						elsif(innertemp00>=20) then
							result1:=2;
							result0:=innertemp00-20;
						elsif(innertemp00>=10) then
							result1:=1;
							result0:=innertemp00-10;
						else
							result1:=0;
							result0:=innertemp00;
						end if;	
			
					 	temp10:=result0;temp11:=result1; --保存当前运算结果,便于二次计算
					    disp0<=conv_std_logic_vector(temp10,4); --显示当前运算结果
					    disp1<=conv_std_logic_vector(temp11,4);
					    remainder(7 downto 4)<=conv_std_logic_vector(remd_h,4);
						remainder(3 downto 0)<=conv_std_logic_vector(remd_l,4);
					    state<=state3;
		when state3 =>   --判断是否有新操作码输入,没有就原地等待
					         if opt/=0 then
					         state<=state1;opter:=opt;
					         else state<=state3;
					   		 end if;
		end case;		
	end if;	
end process;

End rtl;


⌨️ 快捷键说明

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