资源描述
目录
目录 I
第一章 定时计数器的设计要求和方案选择 1
第一节 定时计数器的设计要求 1
第二节 定时计数器的设计方案 1
第二章 定时计数器8253-PIT 3
第一节8253-PIT概述 3
一 8253-PIT的主要功能 3
二 8253-PIT的内部结构 3
三 8253-PIT的引线 4
四 8253-PIT控制字 5
第二节 8253的工作方式 6
一 方式0—计完最后一个数时中断 6
二 方式4—软件触发选通 9
三 8253-PIT的编程 12
第三章 定时计数器的设计 14
第一节 定时计数器源程序 14
一 总线控制部分设计 14
二 数据读取源程序 15
三 数据写入源程序 15
四 计数器定时计数的实现 17
五 计数器级联的实现 21
第二节 设计仿真和验证 23
一 仿真图 23
二 设计结果验证 23
第四章 原器件清单 24
第五章 课程设计心得体会 25
参考文献 26
附图 27
第一章 定时计数器的设计要求和方案选择
第一节 定时计数器的设计要求
① 在所选择器件内完成三路16位定时计数器的设计,要求设计完成后芯片具有总线读写接口(8031单片机标准接口)、定时计数器信号引线;
② 每路定时计数器可以通过配置字配置工作方式,要求每路接口可以进行定时计数工作,并要求可以进行中断(具体的工作模式可以参照8253芯片的六种工作模式进行,但要求至少完成两种工作模式),可以进行级联;
③ 在相应的器件平台上完成设计的输入、编译、综合或适配通过。
第二节 定时计数器的设计方案
在控制系统中,常常要求有一些时钟以实现定时或延时控制,如定时中断、定时检测、定时扫描等,也往往要求有计数器能对外部事件计数。要实现定时或延时控制,有三种主要方法:软件定时、不可编程的硬件定时、可编程的硬件定时器。
软件定时—即让计算机执行一个程序段,这个程序本身没有具体的执行目的,但由于执行每条指令都需要时间,则执行一个程序就需要一个固定时间。通过正确地挑选指令和安排循环次数就很容易实现软件定时,但软件定时占用了CPU的时间,降低了CPU的利用率。
不可编程的硬件定时可以采用小规模集成电路器件如555,外接定时部件—电阻和电容。这样的定时电路简单而且利用改变电阻和电容,可以使定时在一定范围内改变。但是,这种定时电路在硬件连接好后,定时值及定时范围不能由程序(软件)来控制和改变,由此就产生了可编程的定时计数器电路。
可编程定时计数器电路的定时及其范围,可以很容易的由软件来确定和改变。所以,功能较强,使用灵活,本课程就根据定时计数器的设计要求,选择计数器定时器8253-PIT。
第二章 定时计数器8253-PIT
第一节8253-PIT概述
一 8253-PIT的主要功能
8253-PIT的主要功能有:
①有3个独立的16位计数器。
②每个计数器都可以按照二进制或BCD码进行计数。
③每个计数器的计数速率可高达2MHz(8254-2计数频率可达到10MHz)。
④每个计数器有6种工作方式,可由程序设置和改变。
⑤所有的输入输出引脚电平都与TTL电平兼容。
二 8253-PIT的内部结构
图一 8253的内部结构图
①数据总线缓冲器。这是8253与CPU数据总线连接的8位双向三态缓冲器。CPU用输入输出指令对8253进行读写的所有信息,都是通过这8条总线传送的
②读/写逻辑。这是8253内部操作的控制部分。
③控制字寄存器。在8253初始化编程时,由CPU写入控制字以决定计数器的工作方式。此寄存器只能写入而不能读出。
④计数器0、计数器1、计数器2。这是三个计数器/定时器,每一个都是由一个16位的可预置值的减法计数器构成。这三个计数器的操作是完全独立的。
三 8253-PIT的引线
8253-PIT引线如图。每一个通道有三条引线:
CLK:输入脉冲线。计数器就是对这个脉冲计数。
GATE:门控信号输入引脚。这是控制计数器工作的一个外部信号。当GATE引脚为低电平(无效)时,通常都是禁止计数器工作;只有当GATE为高电平,才允许计数器工作。
OUT:输出引脚。当计数到“0”时,OUT引线上必然有输出,输出信号的波形取决于工作方式。
图二 8253的引线
四 8253-PIT控制字
在8253的初始化编程中,由CPU向8253的控制字寄存器写入一个控制字,它规定了8253的工作方式。其格式如图所示。
图三 8253的控制字格式图
①计数器选择(D7D6)。控制字的最高两位决定这个控制字是哪一个计数器的控制字。
②数据读/写格式(D5D4)。CPU向计数器写入初值和读取它们的当前状态时,有几种不同的格式。
③工作方式(D3D2D1)。8253的每个计数器可以有6种不同的工作方式,由这三位决定。
④数制选择(D0)。8253的每个计数器有两种计数制:二进制计数和BCD码计数,由这位决定。
第二节 8253的工作方式
一 方式0—计完最后一个数时中断
在这种方式下,当控制字CW(Control Word)写入控制字寄存器,则使OUT输出端变低,此时计数器没有赋予初值,也没开始计数。
要开始计数,GATE信号必须为高电平,并在写入计数初值后,通道开始计数,在计数过程中 OUT线一直维持为低,直到计数到“0”时。OUT输出变高。
图四 方式0时GATE信号的作用
图五 方式0在计数过程中改变计数值
方式0的主要特点是:
计数器只计数一遍。当计数到0时,并不恢复计数初值,不开始重新计数,且输出保持为高。只有在写入另一个计数值时,OUT变低,开始新的计数。
8253内部是在CPU写计数值的WR#信号上升沿,将此值写入通道的时常数寄存器,在WR#信号上升沿后的下一个CLR脉冲,才将计数值由时常数寄存器送至计数器作为初值,开始计数。所以,8253—PIT是在写计数器装入计数器,下一个脉冲才开始计数。因此,如果设置计数器初值为N,则输出信号OUT是在N+1个CLK脉冲之后才变高的。
在计数过程中,可由门控制信号GATE控制暂停。当GATE=0时,计数暂停;当GATE变高后,就接着计数。
在计数过程中可以改变计数值。若是8位计数,则在写入新的计数值后,计数器将按新的计数值重新开始计数。如果是16位计数,在写入第一个字节后,计数器停止计数,在写入第二个字节后,计数器便按照新的数值开始计数,即改变计数值是立即有效的。
8253内部没有中断控制电路,也没有专用的中断请求引线,所以若要用于中断,则可以用OUT信号作为中断请求信号,但是,需要有外接的中断优先权排队电路与中断向量产生电路。
根据方式0的波形编程如下:
If (cs==0andwr==1)
if clk0'event and clk1='0' then ——时钟脉冲下降沿到来
if gate0='1' then ——门控位为1,允许计数
if ce0>"0000000000000001" then
ce0<=ce0-1;
——减1计数,ce为计数执行部件
elsif ce0="0000000000000000" then
out0<='1'; ——初值减到0时输出高电平
elsif gate1='0' then
——门控位为0,禁止计数
end if;
end if;
end if;
二 方式4—软件触发选通
在这种方式下,当写入控制字后,输出为高(原为高则保持为高,原为低则变为高)。当写入计数值后立即开始计数(相当于软件启动),当计数到0后,输出变低,经过一个输入时钟周期,输出又变高,计数器停止计数。这种方式计数也是一次性的,只有在输入新的计数值后,才能开始新的计数。
图六 方式4的波形
图七 方式4时GATE信号的作用
方式4的特点:
CPU写入计数值后的下一个CLK脉冲,把计数值写入计数器,再下一个CLK脉冲开始减数。因此,若设置计数值为N,则是在写了计数值后的N+1个脉冲,才输出一个负脉冲。
当GATE=1时允许计数,而GATE=0时禁止计数。所以,要做到软件启动,则GATE应保持为“1”。GATE信号不影响输出。
若在计数过程中,改变计数值,则按新的计数值重新开始计数。若计数值是双字节,则在设置第一字节时停止计数,在设置第二字节后,按照新的计数值开始计数。
图八 方式4在计数过程中改变计数值
方式4的设计过程: CPU写入控制字后,输出outs立即复位,方式4中复位后outs为高电平。CPU写入计数初值的下一个CLK脉冲,计数初值被送到计数执行部件并开始减1计数,又经过N个时钟周期后才输出一个负脉冲。当GATE=1时,允许计数,GATE=0时,禁止计数。这样就实现了方式4基本的软件触发功能。
If (cs==0andwr==0)
if clk1'event and clk1='0' then ——时钟脉冲下降沿到来
if gate1='1' then ——门控位为1,允许计数
if ce1>"0000000000000001" then
ce1<=ce1-1;
——减1计数,ce为计数执行部件
elsif ce1="0000000000000001" then
out1<='0'; ——初值减到1时输出低电平
ce1<=ce1-1; ——继续减1
elsif ce1="0000000000000000" then
out1<='1'; ——初值减到0时输出高电平
end if;
elsif gate1='0' then
——门控位为0,禁止计数
null;
end if;
end if;
三 8253-PIT的编程
要使用8253必须首先进行初始化编程,初始化编程的内容为:必须先写入每一个计数器的控制字,然后写入计数器的计数值。计数器的控制字和计数值,是通过两个不同的端口地址写入的。控制字都是写入至控制字寄存器(地址总线低两位A1A0=11),由控制字中的D7D6来确定是哪一个计数器的控制字;而计数值是由各个计数器的端口地址写入的。
①若规定只写低8位,则写入的为计数值的低8位,高8位自动置0;
②若规定只写高8位,则写入的为计数值的高8位,低8位自动置0;
③若是16位计数值,则分两次写入,先写入低8位,再写入高8位。
任一通道的计数值,CPU可用输入指令读取。CPU读到的是执行输入指令瞬间计数器的现行值。但8253的计数器是16位的,所以要分两次读至CPU,因此,若不设法锁存,则在输入过程中,计数值可能已经变化了。要锁存有两种办法:
①利用GATE信号使计数过程暂停。
②向8253输送一个通道控制字,令8253通道中的锁存器锁存。8253的每一个通道都有一个输出锁存器(16位),平时,他的值随通道计数器的值变化,当向通道写入锁存的控制字时,它把计数器的现行值锁存(计数器中继续计数)。于是CPU读取的就是锁存器中的值。
当对计数器重新编程,或CPU读取了计数值偶,自动解除锁存状态,它的值又随计数器变化。
第三章 定时计数器的设计
第一节 定时计数器源程序
一 总线控制部分设计
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
entity lq8253 is
port(cs: in std_logic;
wr: in std_logic;
rd: in std_logic;
a1,a0: in std_logic;
clk0,clk1,clk2,gate0,gate1,gate2: in std_logic;
out0,out1,out2: out std_logic;
data: inout std_logic_vector(15 downto 0));
end lq8253;
architecture lq of lq8253 is
signal internal_bus_in,internal_bus_out:std_logic_vector(15 downto 0);……………………计数初值寄存器
signal port_no,ad,st: std_logic_vector(1 downto 0);…………控制字寄存器
signal xzflag0,xzflag1,xzflag2:std_logic_vector(1 downto 0); ……计数器选择
signal fsflag0,fsflag1,fsflag2:std_logic_vector(2 downto 0);…………方式选择
signal cnt0,cnt1,cnt2:std_logic_vector(15 downto 0);…………计数值寄存器
二 数据读取源程序
read: process(rd,cs)
begin
if (cs='0' and rd='0') then
if (port_no="00" then …………读计数器0计数值
internal_bus_out<=cnt0_latch;
elsif (port_no="01"then …………读计数器1计数值
internal_bus_out<=cnt1_latch;
elsif (port_no="10" then …………读计数器2计数值
internal_bus_out<=cnt2_latch;
end if;
end if;
end process;
三 数据写入源程序
write: process(wr,cs)
variable xzflag: std_logic_vector(1 downto 0);
begin
if (cs='0' and wr='0') then
ad<=a1&a0;
xzflag:=data(7)&data(6);
internal_bus_in<=data;
end if;
if rising_edge(wr) then
if ad="00" then …………写计数器0初值
cnt0_init<=internal_bus_in;
initflag0<='1';
elsif ad="01" then …………写计数器1初值
cnt1_init<=internal_bus_in;
initflag1<='1';
elsif ad="10" then …………写计数器2初值
cnt2_init<=internal_bus_in;
initflag2<='1';
elsif ad="11" and xzflag="00" then …………写计数器0控制字寄存器
ctrl_reg0<=internal_bus_in;
output0<='1';
elsif ad="11" and xzflag="01" then …………写计数器1控制字寄存器
ctrl_reg1<=internal_bus_in;
output1<='1';
elsif ad="11" and xzflag="10" then …………写计数器2控制字寄存器
end if;
end if;
end process;
四 计数器定时计数的实现
modoule TIMECOUNTER0
(
input clk, enable0, count_up, reset,
output reg [15:0] count;
output reg s0);
reg [15:0] i;
reg [15:0] max;
always @ (posedge clk or posedge reset)
begin
if (reset)
count <= 0;
else if (enable0 == 1'b1)
begin
if (count_up)
begin
i<= 1;
max <= {15{1'b1}}; // max value is all 1's
end
else
begin
i <= -1;
max <= {WIDTH{1'b0}};
end
if (count != max)
count <= count + i;
end
else
begin
if(count==max)
count<=0;
s0<=1;
end
end
endmodule
module TIMECOUNTER1
(
input clk, enable1, count_up, reset,
output reg [WIDTH-1:0] count
output reg s1);
parameter WIDTH = 16;
reg [WIDTH-1:0] i;
reg [WIDTH-1:0] max;
always @ (posedge clk or posedge reset)
begin
if (reset)
count <= 0;
else if (enable1== 1'b1)
begin
if (count_up)
begin
i<= 1;
max <= {WIDTH{1'b1}}; // max value is all 1's
end
else
begin
i <= -1;
max<= {WIDTH{1'b0}};
end
if (count != max)
count <= count + i;
else
begin
if(count==max)
count<=0;
s1<=1;
end
end
end
endmodule
module TIMECOUNTER2
(
input clk, enable2, count_up, reset,
output reg [WIDTH-1:0] count
output reg s2);
parameter WIDTH = 16;
reg [WIDTH-1:0] i;
reg [WIDTH-1:0] max;
always @ (posedge clk or posedge reset)
begin
if (reset)
count <= 0;
else if (enable2== 1'b1)
begin
if (count_up)
begin
i<= 1;
max <= {WIDTH{1'b1}}; // max value is all 1's
end
else
begin
i <= -1;
max<= {WIDTH{1'b0}};
end
if (count != max)
count <= count + i;
else
begin
if(count==max)
count<=0;
s2<=1;
end
end
end
endmodule
五 计数器级联的实现
Module TOP_CNT(input clk, enable, count_up, reset,
output reg [WIDTH-1:0] count
output reg s);
wire clk,enable,count_up,reset;
wire[15:0]count;
TIMECOUNTER0 u1(
.clk( clk),
.count_up( count_up),
.reset(reset),
.count(count));
TIMECOUNTER1 u2(
.clk( clk),
.count_up( count_up),
.reset(reset),
.count(count)
);
TIMECOUNTER2 u3(
.clk( clk),
.count_up( count_up),
.reset(reset),
.count(count)
.enable(enable));
assign s0 = enable1;
assign s1 = enable2;
assign s2 = enable0;
endmodule
第二节 设计仿真和验证
一 仿真图
图九 波形图
二 设计结果验证
本设计开发软件采用Altera公司的集成开发软件QuartusII8.0完成,并用该公司的CycloneII系列FPGA芯片其型号为EP2C35予以验证。通过仿真、综合,并下载到FPGA中进行验证,本设计可以很好地实现其功能。
第四章 原器件清单
元件种类
数量
EP2C35 型号FPGA芯片
1
K4S641632型号SDRAM芯片
1
IS61LV25616AL SRAM芯片
1
JS28F640 FLASH
1
配制芯片: EP2C35核心板
1
FPGA供电系统
1
有源时钟或晶振
1
第五章 课程设计心得体会
一周的EDA课程设计收获很多,对EDA技术及应用和数字部分知识进行了巩固,也练习了对mxa-plusII的熟练掌握。首先是对数字电路这门课程有了更深的理解,因为这门课程设计要求将以前所学的理论知识运用到实际的电路设计中,在电路的设计过程中,无形中便加深了对数字电路的了解及运用能力,对课本以及以前学过的知识 有了一个更好的总结与了解。
刚接触这个题目,感觉很茫然,不知道从哪部分开始,就去图书馆借阅相关的资料,看计数器的工作原理,并理解程序、仿真波形。以前的数字实验只是针对某一个小的功能设计,而EDA课程设计对我们的总体电路设计的要求更高更严格,需要通过翻阅复习以前学过的知识确立实验总体设计方案,然后逐步细化进行各模块的设计;其次,在电路仿真的过程中总会出现一些问题,需要我们细心解决,所以这两周下来,我对设计故障的排查能力有了很大的提高,再次通过这次课程设计,使我对VHDL语言有了更进一步的了解,也巩固了以前学过的数电知识。对大量资料的查询,使自己的视野变的宽阔,了解到VHDL广阔的应用范围。在设计的过程中我与搭档相互帮助解决了很多问题,体现了团结互助的重要性。 设计的过程是苦涩的,可是我们的收获是甜蜜的。通过这一次一次的亲身体验,仿佛发生了一次洗礼,经过了一个质的飞跃。希望以后的自己多进行这样的锻炼,让自己的能力越来越高。
参考文献
1.康华光 主编,《电子技术基础-数字部分》,高等教育出版社,1998。
2.谭会生等 主编,《EDA技术及应用》,西安电子科技大学出版社,2001
3.潘松等 主编,《EDA技术实用教程》,科学出版社,2006
4.雷伏容 主编,《VHDL电路设计》,清华大学出版社,2006
5.Charles H.Roth等著,《数字系统设计与VHDL》,电子工业出版社,2008
附图
图十 定时计数器结构框图
图十一 计数器结构图
28
展开阅读全文