第十章 数字系统设计范例
10.1 跑马灯设计
1.设计要求控制 8个 LED进行花式显示,设计 4中显示模式:
S0:从左到右逐个点亮 LED;
S1:从右到左逐个点亮 LED;
S2:从两边到中间逐个点亮 LED;
S3:从中间到两边逐个点亮 LED;
4种模式循环切换,复位键 (rst)控制系统的运行和停止。
led的电路符号
clk
q[7…0]
clk –时钟
q – 数据输出端
led
rstrst – 复位信号输入端
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity led is
port(clk:in std_logic;
rst:in std_logic;
q:out std_logic_vector(7 downto 0));
end led;
architecture one of led is
type states is (s0,s1,s2,s3); --定义四种模式
signal present:states;
signal q1,std_logic_vector(7 downto 0);
signal count:std_logic_vector(3 downto 0);
begin
process(clk,rst)
begin
if rst=‘1’ then --系统复位
present<=s0;
q1<=?00000000?;
elsif clk’event and clk=‘1’ then
case present is
when s0 => if q1=?00000000? then --S0模式,从左到右逐个点亮 LED
q1<=?10000000?;
else
if count=?0111? then
count<=?0000?;
q1<=?00000001?;
present<=s1;
else q1<=q1(0)&q1(7 downto 1);
count<=count+1;
present<=s0;
end if;
end if;
when s1 => if count=?0111? then --S1模式,从右到左逐个点亮 LED
count<=?0000?;
q1<=?10000001?;
present<=s2;
else q1<=q1(6 downto 0)&q1(7);
count<=count+1;
present<=s1;
end if;
when s2 => if count=?0111? then --S2模式,从两边到中间逐个点亮 LED
count<=?0000?;
q1<=?00011000?;
present<=s3;
else q1(7 downto 4)<=q1(4)&q1(7 downto 5);
q1(3 downto 0)<=q1(2 downto 0)&q1(3);
count<=count+1;
present<=s2;
end if;
when s3 => if count=?0111? then --S3模式,从中间到两边逐个点亮 LED
count<=?0000?;
q1<=?10000000?;
present<=s0;
else q1(7 downto 4)<=q1(6 downto 4)&q1(7);
q1(3 downto 0)<=q1(0)&q1(3 downto 1);
count<=count+1;
present<=s3;
end if;
end case;
end if;
end process;
q<=q1;
end one;
10.2 8位数码扫描显示电路设计
a
g
K 1
a
g
K 2
a
g
K 3
a
g
K 4
a
g
K 5
a
g
K 6
a
g
K 7
a
g
K 8
要求:在 8个数码管上显示数据? 124579DF?
原理,K1-K8:选通信号;
8位数码扫描显示电路
8位数码管扫描显示电路的电路符号
clk
scan[7…0]
clk –时钟
seg –段显示控制信号输出端
Scan_led
scan – 地址选择控制信号输入端 seg[7…0]
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity scan_led is
port(clk:in std_logic;
seg:out std_logic_vector(7 downto 0);
scan:out std_logic_vector(7 downto 0));
end scan_led;
architecture one of scan_led is
signal cnt,integer range 0 to 7; --数码管地址指针
signal data:integer range 0 to 15; --7段译码指针
begin
process(clk) --用于扫描数码管地址的计数器
begin
if clk’event and clk=‘1’ then
cnt<=cnt+1;
end if;
end process;
process(cnt) --数码管地址扫描
begin
case cnt is
when 0 => scan <=?00000001?; data<=1; --K1
when 1 => scan <=?00000010?; data<=2; --K2
when 2 => scan <=?00000100?; data<=4; --K3
when 3 => scan <=?00001000?; data<=5; --K4
when 4 => scan <=?00010000?; data<=7; --K5
when 5 => scan <=?00100000?; data<=9; --K6
when 6 => scan <=?01000000?; data<=13; --K7
when 7 => scan <=?10000000?; data<=15; --K8
when others => null;
end case;
end process;
process(data) --7段译码
begin
case data is
when 0 => seg <=?11111100? ; --0
when 1 => seg <=?01100000? ; --1
when 2 => seg <=?11011010? ; --2
when 3 => seg <=?11110010? ; --3
when 4 => seg <=?01100110? ; --4
when 5 => seg <=?10110110? ; --5
when 6 => seg <=?10111110? ; --6
when 7 => seg <=?11100000? ; --7
when 8 => seg <=?11111110? ; --8
when 9 => seg <=?11110110? ; --9
when 10 => seg <=?11101110? ; --a
when 11 => seg <=?00111110? ; --b
when 12 => seg <=?10011100? ; --c
when 13 => seg <=?01111010? ; --d
when 14 => seg <=?10011110? ; --e
when 15 => seg <=?10001110? ; --f
when others => null;
end case;
end process;
end one;
10.3 4× 4键盘扫描电路的设计
1,设计要求在时钟控制下循环扫描键盘,根据列扫描信号和对应键盘相应信号确定键盘按键位置,并将按键值显示在 7段数码管上。
2,设计原理
4× 4矩阵键盘
C 8 4 0
D 9 5 1
E A 6 2
F B 7 3
0 0 0 10 0 1 00 1 0 01 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
用列信号进行扫描时的基本原理
3,电路符号
4× 4矩阵键盘扫描电路的电路符号
clk
scan[7…0]
clk –时钟
seg – 7段显示控制信号输出端
kb4X4
scan – 数码管地址选择控制信号输出端
seg[6…0]start
kbcol[3…0]
kbrow[3…0]start – 开始信号输入端
kbcol – 列扫描信号输入端
kbrow – 行扫描信号输出端
4.设计方法
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity kb4x4 is
port(start,clk:in std_logic;
kbcol:in std_logic_vector(3 downto 0);
kbrow:out std_logic_vector(3 downto 0);
scan:out std_logic_vector(7 downto 0);
seg:out std_logic_vector(6 downto 0));
end kb4x4;
architecture one of kb4x4 is
signal cnt,std_logic_vector(1 downto 0);
signal sta,std_logic_vector(1 downto 0);
signal seg7:std_logic_vector(6 downto 0);
signal dat,std_logic_vector(4 downto 0);
signal fn:std_logic; --按键标志位,判断是否有键被按下
begin
scan<=?00000001?; --只用一个数码管显示
process(clk) --循环扫描计数器
begin
if clk’event and clk=‘1’ then
cnt<=cnt+1;
end if;
end process;
process(clk) --循环列扫描
begin
if clk’event and clk=‘1’ then
case cnt is
when?00? => kbrow <=?0001?; sta<=?00?;
when?01? => kbrow <=?0010?; sta<=?01?;
when?10? => kbrow <=?0100?; sta<=?10?;
when?11? => kbrow <=?1000?; sta<=?11?;
when others => kbrow <=?1111?;
end case;
end if;
end process;
process(clk,start) --行扫描译码
begin
if start=?0? then seg7<=?0000000?;
elsif clk’event and clk=‘1’ then
case sta is
when?00? =>
case kbcol is
when?0001? => seg7<=?1111001?; dat<=?00011?; --3
when?0010? => seg7<=?1101101?; dat<=?00010?; --2
when?0100? => seg7<=?0110000?; dat<=?00001?; --1
when?1000? => seg7<=?1111110?; dat<=?00000?; --0
when others => seg7 <=?0000000?; dat<=?11111?;
end case;
when?01? =>
case kbcol is
when?0001? => seg7<=?0011111?; dat<=?00111?; --7
when?0010? => seg7<=?1011111?; dat<=?00110?; --6
when?0100? => seg7<=?1011011?; dat<=?00101?; --5
when?1000? => seg7<=?0110011?; dat<=?00100?; --4
when others => seg7 <=?0000000?; dat<=?11111?;
end case;
when?10? =>
case kbcol is
when?0001? => seg7<=?0011111?; dat<=?01011?; --b
when?0010? => seg7<=?1110111?; dat<=?01010?; --a
when?0100? => seg7<=?1111011?; dat<=?01001?; --9
when?1000? => seg7<=?1111111?; dat<=?01000?; --8
when others => seg7 <=?0000000?; dat<=?11111?;
end case;
when?11? =>
case kbcol is
when?0001? => seg7<=?1000111?; dat<=?01111?; --f
when?0010? => seg7<=?1001111?; dat<=?01110?; --e
when?0100? => seg7<=?0111101?; dat<=?01101?; --d
when?1000? => seg7<=?1001110?; dat<=?01100?; --c
when others => seg7 <=?0000000?; dat<=?11111?;
end case;
when others => seg7<=?0000000?;
end case;
end if;
end process;
fn<= not(dat(0) and dat(1) and dat(2) and dat(3) and dat(4)); --产生按键标志位
process(fn)
begin
if fn’event and fn=‘1’ then
seg<=seg7;
end if;
end process;
end one;