📄 calculation2.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 + -