题目要求:
(1)设计10以内的加减法计算器。
(2)1个按键用于指定加法或减法,一个用于指定加数或被加数,还有两个分别控制加数或被加数的增加或减少。
(3)设置的结果和计算的结果用数码管显示。
本实验我还是将其视作Mealy型向量机,具体的见我之前关于秒表的内容:VHDL实验:基于有限状态机实现秒表
按照题目意思,有4个键是必不可少的,但我还是决定增加两个推键,本实验状态图如下:
S0:初态模式,所有数码管置零
S1:计算模式,等待用户设置并计算
这两者之间的转换我用开发板上的推键来完成。
另一个推键指示是进行整数运算还是一位小数。
我的代码:(抱歉注释是全英文的)
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all ;
use ieee.std_logic_arith.all ;
entity Computer is
port (
key3 : in std_logic ; -- is addition or subtraction?
key2 : in std_logic ; -- who is augend or minuend?
key1 : in std_logic ; -- change the value of augend or minuend
key0 : in std_logic ; -- change the value of addend or subtrahend
sw0 : in std_logic ; -- change the state of circuit
sw1 : in std_logic ;
first1 : out std_logic_vector(0 to 6) ;
first2 : out std_logic_vector(0 to 6) ;
second1 : out std_logic_vector(0 to 6) ;
second2 : out std_logic_vector(0 to 6) ;
negative : out std_logic_vector(0 to 6) ; -- Is the result a negative number?
empty : out std_logic_vector(0 to 6) ;
result1 : out std_logic_vector(0 to 6) ; -- the result of computing
result2 : out std_logic_vector(0 to 6) ; -- the result of computing
Point : out std_logic_vector(7 downto 0) ; -- Radix point
ledg8 : out std_logic ; -- if substraction
ledr16 : out std_logic ; -- it is augend or minuend
ledr13 : out std_logic -- it is augend or minuend
) ;
end Computer ;
architecture mathematic of Computer is
constant matrix_num : integer := 9 ;
TYPE Number is array (0 to matrix_num) of std_logic_vector(0 to 6);
signal Display : Number := (('0', '0', '0', '0', '0', '0', '1'), -- 0
('1', '0', '0', '1', '1', '1', '1'), -- 1
('0', '0', '1', '0', '0', '1', '0'), -- 2
('0', '0', '0', '0', '1', '1', '0'), -- 3
('1', '0', '0', '1', '1', '0', '0'), -- 4
('0', '1', '0', '0', '1', '0', '0'), -- 5
('0', '1', '0', '0', '0', '0', '0'), -- 6
('0', '0', '0', '1', '1', '1', '1'), -- 7
('0', '0', '0', '0', '0', '0', '0'), -- 8
('0', '0', '0', '0', '1', '0', '0') -- 9
) ;
TYPE state_type is (s0, s1) ; -- how many states does the circuit have?
signal current_state : state_type ;
-- all of them below are middle data
signal neg : std_logic_vector(0 to 6) := ('1', '1', '1', '1', '1', '1', '1') ;
signal led8 : std_logic ;
signal led16 : std_logic ;
signal led13 : std_logic ;
signal p : std_logic_vector(7 downto 0) ;
begin
process(sw0) -- to change the state of circuit
begin
if (sw0 = '0') then
current_state <= s0 ;
else
current_state <= s1 ;
end if ;
end process ;
process(current_state, key3, key2, key1, key0, sw1) -- take action according to state
variable First : integer := 0 ;
variable Second : integer := 0 ;
variable Result : integer := 0 ;
variable num3 : integer := 0 ;
variable num2 : integer := 0 ;
begin
if (current_state = s0) then
First := 0 ;
Second:= 0 ;
Result:= 0 ;
num3 := 0 ;
num2 := 0 ;
neg <= ('1', '1', '1', '1', '1', '1', '1') ;
p <= ('1', '1', '1', '1', '1', '1', '1', '1') ;
led8 <= '0' ;
led16 <= '0' ;
led13 <= '0' ;
elsif (current_state = s1) then
if (sw1 = '1') then -- make sure integer or float
p <= ('0', '1', '0', '1', '1', '1', '0', '1') ;
else
p <= ('1', '1', '1', '1', '1', '1', '1', '1') ;
end if ;
if falling_edge(key2) then -- make sure who is augend or minuend?
num2 := num2 + 1 ;
end if ;
if ((num2 > 0) and(num2 MOD 2 = 0)) then
led16 <= '0' ;
led13 <= '1' ;
elsif (num2 MOD 2 = 1) then
led16 <= '1' ;
led13 <= '0' ;
end if ;
if falling_edge(key1) then -- decide the value of first number
First := First + 1 ;
if (First > 10) then
First := 0 ;
end if ;
end if ;
if falling_edge(key0) then -- decide the value of second number
Second := Second + 1 ;
if (Second > 10) then
Second := 0 ;
end if ;
end if ;
if falling_edge(key3) then
num3 := num3 + 1 ;
end if ;
if (num3 MOD 2 = 1) then
led8 <= '0' ;
neg(6) <= '1' ;
Result := First + Second ;
elsif ((num3>0) and (num3 MOD 2 = 0)) then
led8 <= '1' ;
if (led13 = '1') then
if (Second < first) then
neg(6) <= '0' ;
Result := First - Second ;
else
neg(6) <= '1' ;
Result := Second - First ;
end if ;
elsif (led16 = '1') then
if (first < Second) then
neg(6) <= '0' ;
Result := Second - First ;
else
neg(6) <= '1' ;
Result := First - Second ;
end if ;
end if ;
end if ;
end if ;
empty <= ('1', '1', '1', '1', '1', '1', '1') ;
first1 <= Display(First/10) ;
first2 <= Display(First MOD 10) ;
second1 <= Display(Second/10) ;
second2 <= Display(Second MOD 10) ;
negative <= neg ;
result1 <= Display(Result/10) ;
result2 <= Display(Result MOD 10);
Point <= p ;
ledg8 <= led8 ;
ledr16 <= led16 ;
ledr13 <= led13 ;
end process ;
end mathematic ;