时序逻辑之计数电路

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

时序逻辑之计数器或分频器
I数控分频器
1.思路
分频器就是计数器,区别就在于前者是数控的,因此只要把计数器改变下就行。

给计数器增加一个8位预置端,然后把具体进制计数器中的计数上限改成预置端的值即可。

也就是如下代码:if(CNT=D) then CNT:="00000000";cout<='1'; else CNT:=CNT+1 ; cout<='0' ; end if;
2程序代码
A我的程序
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity counter is
port(clk:in std_logic;
D:in std_logic_vector(7 downto 0);
fout:out std_logic);
end counter;
architecture behave of counter is
signal cout:std_logic;
begin
process(clk)
variable CNT:std_logic_vector(7 downto 0);
begin
if(clk'event and clk='1')
then
if(CNT=D)
then CNT:="00000000";cout<='1';
else CNT:=CNT+1;cout<='0';
end if;
end if;
end process;
fout<=cout;
end behave;
B.书上的程序
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity dvf is
port(clk:in std_logic;
D:in std_logic_vector(7 downto 0);
fout:out std_logic);
end dvf;
architecture arc of dvf is
signal full:std_logic;
begin
p_reg:process(clk)
variable cnt8:std_logic_vector(7 downto 0);
begin
if clk'event and clk='1' then
if cnt8="11111111" then
cnt8:=D;
full<='1';
else cnt8:=cnt8+1;
full<='0';
end if;
end if;
end process p_reg;
p_div:process(full)
variable cnt2:std_logic;
begin
if full'event and full='1' then
cnt2:=not cnt2;
if cnt2='1' then fout<='1';
else fout<='0';
end if;
end if;
end process p_div;
end;
3.效果与现象
实验现象用蜂鸣器验证。

当在输入端预置不同的数时,蜂鸣器发出不同的音调。

可以想见,只要输入适当的频率,完全可以利用FPGA实现一个简易的电子钢琴。

II按键+计数器
1.思路
通过按键控制计数器进制的切换,大体思路与数控分频器的实现是一样的,只是加了一个按键。

在程序结构组织上想到了两种方法。

一个是采用多进程。

共有3个进程,分别是按键进程,加法计数进程,译码进程。

另一个是采用元件例化的方法。

分别例化按键,计数器,译码器三个元件,简洁明了。

2.程序代码
A.多进程
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cnt is
port(clk:in std_logic;
key:in std_logic;
SM:out std_logic_vector(7 downto 0);
cout:out std_logic);
end cnt;
architecture behave of cnt is
signal system:integer range 9 downto 0;
signal cqi:std_logic_vector(3 downto 0);
signal p:std_logic_vector(24 downto 0);
begin
process(key) --按键进程variable flag:std_logic:='0';
begin
if key'event and key='0' then
flag:=not flag;
end if;
if flag='1' then system<=8;
else system<=5;
end if;
end process;
process(clk,system) --计数进程begin
if clk'event and clk='1' then
p<=p+1;
if(p="1111111111111111111111111")then
if cqi=system then cout<='1';cqi<="0000";
else cqi<=cqi+1;cout<='0';
end if;
end if;
end if;
end process;
process (cqi) --译码进程begin
case cqi is
when "0000"=>SM<="10111111"; when "0001"=>SM<="10000110"; when "0010"=>SM<="11011011"; when "0011"=>SM<="11001111"; when "0100"=>SM<="11100110"; when "0101"=>SM<="11101101"; when "0110"=>SM<="11111101"; when "0111"=>SM<="10000111"; when "1000"=>SM<="11111111"; when "1001"=>SM<="11101111"; when others=>null;
end case;
end process;
end behave;
B.元件例化
--顶层实体
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity keycnt is
port(clk0,key:in std_logic;
SM:out std_logic_vector(7 downto 0); cout0:out std_logic);
end keycnt;
architecture arc of keycnt is
signal a:integer range 9 downto 0; signal b:std_logic_vector(3 downto 0); component cnt
port(clk:in std_logic;
cq:out std_logic_vector(3 downto 0); cout:out std_logic;
D:in integer range 9 downto 0);
end component;
component decoder
port(A:in std_logic_vector(3 downto 0); LED7:out std_logic_vector(7 downto 0)); end component;
component key1
port(kin:in std_logic;
kout:out integer range 9 downto 0);
end component;
begin
u1:key1 port map (key,a);
u2:cnt port map (clk0,b,cout0,a);
u3:decoder port map (b,SM);
end arc;
--按键
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity key1 is
port(kin:in std_logic;
kout:out integer range 9 downto 0); end key1;
architecture arc of key1 is
begin
process(kin)
variable kflag:std_logic:='0';
begin
if kin'event and kin='0' then
kflag:=not kflag;
end if;
if kflag='0' then kout<=5;
else kout<=8;
end if;
end process;
end arc;
--加法计数器
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cnt is
port(clk:in std_logic;
cq:out std_logic_vector(3 downto 0); cout:out std_logic;
D:in integer range 9 downto 0);
end cnt;
architecture behave of cnt is
signal cqi:std_logic_vector(3 downto 0); signal p:std_logic_vector(24 downto 0); begin
process(clk)
begin
if clk'event and clk='1' then
p<=p+1;
if(p="1111111111111111111111111")then if cqi=D then cout<='1';cqi<="0000"; else cqi<=cqi+1;cout<='0';
end if;
end if;
end if;
cq<=cqi;
end process;
end behave;
--译码器
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity decoder is
port(A:in std_logic_vector(3 downto 0); LED7:out std_logic_vector(7 downto 0)); end decoder;
architecture behave of decoder is
begin
process(A)
begin
case A is
when "0000"=>LED7<="10111111"; when "0001"=>LED7<="10000110"; when "0010"=>LED7<="11011011"; when "0011"=>LED7<="11001111"; when "0100"=>LED7<="11100110"; when "0101"=>LED7<="11101101"; when "0110"=>LED7<="11111101"; when "0111"=>LED7<="10000111"; when "1000"=>LED7<="11111111"; when "1001"=>LED7<="11101111"; when "1010"=>LED7<="11110111"; when "1011"=>LED7<="11111100"; when "1100"=>LED7<="10111001"; when "1101"=>LED7<="11011110"; when "1110"=>LED7<="11111001"; when "1111"=>LED7<="11110001"; when others=>null;
end case;
end process;
end behave;
2.效果与现象
按键做输入预置端,输出接8段数码管。

按键没消抖时,按键不灵敏。

有时候按下后计数进制切换,有时候不切换。

消抖后,按键比较灵敏。

III.问题与思考
1.关于进程
进程是时序逻辑设计中的基本单元,有点类似于函数在C语言中的地位与作用。

进程是一个无限循环结构,只有两种运行状态:执行状态和等待状态,具有顺序/并行运行的双重性。

它的顺序性是指语句按序执行上的顺序性,并行性是指从综合或硬件效果上看,它是并行的。

从process的启动执行到end为止所花的时间与外部因素无关(从综合结果来看),其执行时间从行为仿真的角度看,只有一个VHDL模拟器的最小分辨时间;但从综合和硬件运行的角度看,其执行时间是0,即在同一process语句中,10条语句和1000条语句的执行时间是一样的。

所以说,从效果上看,process中的顺序语句具有并行执行的性质。

进程本身是并行语句。

虽然进程语句做为引导语句属于顺序语句,但同一结构体中的不同进程是并行运行的或者说是根据相应的敏感信号独立运行的。

比如说有两个进程,除非两组敏感信号中的一对同时发生变化,两个进程才被同时启动。

因此也可以说,任何一条信号的并行赋值语句都是一个简化的进程语句,其输入表达式中的各信号时此“进程语句”的敏感信号。

2关于按键消抖
绝大多数按键都是机械式开关结构,由于机械式开关的核心部件为弹性金属簧片,因而在开关切换的瞬间会在接触点出现来回弹跳的现象。

虽然只是进行了一次按键,结果在按键信号稳定的前后出现了多个脉冲,如图1所示。

如果将这样的信号直接送给微处理器扫描采集的话,将可能把按键稳定前后出现的脉冲信号当作按键信号,这就出现人为的一次按键但微处理器以为多次按键现象。

为了确保按键识别的准确性,在按键信号抖动的情况下不能进入状态输入,为此就必须对按键进行消抖处理,消除抖动时不稳定、随机的电压信号。

机械式按键的抖动次数、抖动时间、抖动波形都是随机的。

不同类型的按键其最长抖动时间也有差别,抖动时间的长短和按键的机械特性有关,一般为5~10 ms,但是,有些按键的抖动时间可达到20 ms,甚至更长。

所以,在具体设计中要具体分析,根据实际情况来调整设计。

按键消抖一般采用硬件和软件消抖两种方法。

硬件消抖是利用电路滤波的原理实现,软件消抖是通过按键延时来实现。

在微机系统中一般都采用软件延时的消抖方法。

在用可编程逻辑器件FPGA/CPLD设计数字系统中,也可以用VHDL语言设计相应的时序和逻辑电路,对按键信号进行处理,同样可以达到消抖目的。

按键消抖的关键是提取稳定的低电平(或高电平)状态,滤除按键稳定前后的抖动脉冲。

在用基于VHDL语言的时序逻辑电路设计按键消抖电路时,可以用一个时钟脉冲信号对按键状态进行取样,当第一次采样到低电平时,启动延时电路,延时结束后,再对按键信号进行连续三次取样,如果三次取样都为低电平,则可以认为按键已经处在稳定状态,这时输出一个低电平的按键确认信号,如果连续三次的取样中,至少有一次是高电平,则认为按键仍处在抖动状态,此时不进行按键确认,按键输出信号为高电平。

相关文档
最新文档