资源描述
南京邮电大学
课程设计报告
设计类别: EDA-VHDL
专业名称: 电子信息工程
班级学号: B08021717
学生姓名: 付祥旭
基本题 : 数字时钟设计
综合题 : 数码管学号动态显示
同小构成员:
学号:
姓名: 曾大千
指引教师: 王奇、梅中辉、周晓燕、孔凡坤
日 期: 9月1日—9月21日
第一章 软件设计简介
一、 各类设计环节性质、目与任务
本课程设计是一门重要专业基本实践课,是《当代电子技术》或《EDA技术》等课程后续实践课程,未选前述课程规定学生具备数字电路和C语言基本。
本课程设计目和任务:1.使学生全面理解如何应用该硬件描述语言进行高速集成电路设计;2.通过软件设计环节与仿真环节使学生熟悉Quartus II设计与仿真环境;3. 通过对基本题、综合题设计实践,使学生掌握硬件系统设计办法(自底向上或自顶向下),熟悉VHDL语言三种设计风格,熟悉其芯片硬件实现过程。
二、实验内容
软件设计课题共分基本课题、综合课题两档。基本课题2题,12个学时完毕;综合课题共4题,20个学时完毕。
四、考核办法
学生软件设计成绩考核来源于如下方面:
考勤及工作态度(占10%)
软件设计报告(占40%)
验收状况(占50%)
五、重要设备
微型计算
EDA-VHDL开发软件(QUARTUS2)
ALtera CPLD硬件实验开发系统
第二章 软件开发平台简介
1 Quartus II简介
Quartus II 提供了完整多平台设计环境,能满足各种特定设计需要,也是单芯片可编程系统(SOPC)设计综合性环境和SOPC开发基本设计工具。Quartus II 设计工具完全支持VHDL、Verilog设计流程,其内部嵌有VHDL、Verilog逻辑综合器。Quartus II 具备仿真功能,同步也支持第三方仿真工具,如Modelsim。
Quartus II 涉及模块化编译器。编译器涉及功能模块有分析/综合器(Analysis & Synthesis)、适配器(Fitter)、装配器(Assembler)、时序分析器(Timing Analyzer)、设计辅助模块(Design Assistant)、EDA网表文献生成器(EDA Netlist Writer)、编辑数据接口(Compiler Database Interface)等。可以通过选取Sart Compilation 来运营所有编译器模块,亦可以通过选取Start 单独运营各个模块。还可以通过选取Compiler Tool(Tools 菜单),在Compiler Tool 窗口中运营该模块来启动编译器模块。在Compiler Tool 窗口中,可以打开该模块设立文献或报告文献,或打开其她有关窗口。
2 Quartus II设计基本流程
① 使用 New Project Wizard (File 菜单)建立新工程并指定目的器件或器件系列。
② 使用 Text Editor (文本编辑器)建立 Verilog HDL、VHDL 或 Altera硬件描述语言 (AHDL) 设计。 也可以使用 Block Editor (原理图编辑器)建立流程图或原理图。流程图中可以包括代表其他设计文献符号。 还可以使用 MegaWizard® Plug-In Manager 生成宏功能模块和IP内核自定义变量,在设计中将它们实例化。
③(可选)使用 Assignment Editor、Settings 对话框(Assignments 菜单)、Floorplan Editor / LogicLock™ 功能指定初始设计约束条件。
④(可选)使用 SOPC Builder 或 DSP Builder 建立系统级设计。
⑤ (可选)使用 Software Builder 为 Excalibur™ 器件解决器或 Nios® 嵌入式解决器建立软件和编程文献。
⑥ 使用 Analysis & Synthesis 对设计进行综合。
⑦(可选)使用仿真器对设计执行功能仿真。
⑧ 使用 Fitter 对设计执行布局布线。 在对源代码进行少量更改之后,还可以使用增量布局布线。
⑨ 使用 Timing Analyzer 对设计进行时序分析。
⑩ 使用仿真器对设计进行时序仿真。
第三章 软件设计内容
3.1数字时钟设计
1设计题目及其规定
规定学生设计一种时钟,并输出到数码管显示时,分,秒。
2设计原理
注:本实验设计采用是自已购买开发板,时钟为25MHZ,3选8数码管位选,以及共阴型数码。
电路重要分为分频电路,选取电路,计数电路各译码扫描电路。
分频电路:
对开板上晶振产生25MHZ调频进行12.5MHZ分频产生1HZ时钟信号.
选取电路:
对分频电路产生1HZ时钟信号,和秒计数器和分计数产生进位信号进行选取,分别用于校分校时.
计数电路:
60计数器和24计数器,分别对秒分和时进行计数.60计数器每计满60个数则产生一种进位信号,用于作为分钟计数器和小时计数器时钟.
译码扫描电路:对于输出秒分时数据时行译,以相应8段数码管段选cout1~8,以及位选Key1~3.
下面是电路设计原理图:
24计数器
译码与扫描电路
ckk
S21
选取
S11
分频电路
选取
60计数器
60计数器
Cout1~8
Key1-3
图1:设计原理图
3、分频电路
由于分频系数过大,仿真不具备可操作性,故把先把分频系数改小后进行仿真。
3.1逻辑仿真
对输入CLK1进行分频,得到CLK2。这是把分频系数改小后仿真图,不代表实际电路。
3.2时序仿真
除有一定期间延迟外,与逻辑仿真基本一致。
4选取电路
对分频电路产生1HZ时钟信号,和秒计数器和分计数产生进位信号进行选取,分别用于校分校时.
4.1逻辑仿真
EN1=0 CLK=CLK1;
EN1=1 CLK=CLK2;
满足实验规定。
4.2时序仿真
有一定期间延迟外,与逻辑仿真基本一致。
5、六十进制计数器
5.1逻辑仿真
计数到3B(16进制)=60(10进制)后产生一种进位脉冲,满足实验规定。
5.2功能仿真
有一定期间延迟外,与逻辑仿真基本一致。
6、二十四进制计数器
6.1逻辑仿真
计数到17(16进制)=23(10进制)重新从0计数,满足实验规定。
6.2时序仿真
有一定期间延迟外,与逻辑仿真基本一致。
7 译码扫描电路
因译码扫描电路正误码仿真不具备可观测性,故不在此仿真。
8 整体电路仿真
8.1逻辑仿真
从图可以看出S1控制校分电路,S2控制校时电路。当S1S2=00时,按正常进行计时。
8.2时序仿真
有一定期间延迟外,与逻辑仿真基本一致。
9总结:本题超额完毕题目规定,增长了校时校分电路,成为一种真正意义上时钟。
3.2数码管学号动态显示
1设计题目及其规定
规定学生设计一种时钟,并输出到数码管显示时,分,秒。
2设计原理
注:本实验设计采用是自已购买开发板,时钟为25MHZ,3选8数码管位选,以及共阴型数码。
电路重要分为分频电路,选取电路,计数电路各译码扫描电路。
分频电路:对开板上晶振产生25MHZ时钟进行分频产生1HZ、2HZ、3HZ、4HZ时钟信号.
选取电路:对分频电路产生1HZ、2HZ、3HZ、4HZ时钟信号,由选取开关进行选取电路时钟频率,以控制学号移动快慢。
循环电路路:用于控制学号循环左移(08021717);
扫描译码电路:译码扫描电路:对于输出学号数据时行译,以相应8段数码管段选cout1~8,以及位选Key1~3.
下面是对设计原理图
分频电路
选取电路
循环电路
译码扫描电路
clk
S1,s22
Cout1~8
Key1~3
3 分频电路: 由于分频系数过大,仿真不具备可操作性,故把先把分频系数改小后进行仿真。
3.1逻辑仿真
从图中可以看出输入一种高频时钟信号CLK1,产生四个不同低频信号CLK2,CLK3,CLK4,CLK5;满足实验规定。
3.2时序仿真
从图中可以看出输入一种高频时钟信号CLK1,产生四个不同低频信号CLK2,CLK3,CLK4,CLK5;满足实验规定。没有浮现毛刺。
4选取电路
对分频电路产生1HZ、2HZ、3HZ、4HZ时钟信号,由选取开关进行选取电路时钟频率,以控制学号移动快慢。
4.1逻辑仿真
从图中可以看出
S1S0=‘00’CK=CLK1
S1S0=‘01’CK=CLK2
S1S0=‘10’CK=CLK3
S1S0=‘11’CK=CLK4
满足实验规定。
4.2时序仿真
从图中可以看出
S1S0=‘00’CK=CLK1
S1S0=‘01’CK=CLK2
S1S0=‘10’CK=CLK3
S1S0=‘11’CK=CLK4
没浮现毛刺,满足实验规定。
5 循环电路
用于控制学号循环左移(08021717)
5.1逻辑仿真
从图中可以看出每当CLK上升沿来暂时,学号移动一位,并且循环移动。满足实验规定。
5.2时序仿真
除有一定延时外与逻辑仿真基本一致 。
6译码扫描电路
因译码扫描电路正误码仿真不具备可观测性,故不在此仿真。
7整体电路仿真
7.1逻辑仿真
从图中可以看出学号循环移位,并且可以用S11,S10来控制循环快慢。
逻辑仿真基本一致 。
7、总结:完全满足实验规定,但在编码时因做了三个并列较大分频,导致资源占用过大。应当进行多次串联分频,可以大大减少占用资源,代码有待优化。
8调试过程与问题
编程和仿真基本上都没有什么问题,但是在烧录到芯片内时却浮现了某些问题,在些仅举一种故意义例子。
显示不稳定:是由于在对数码管加上25MHZ频率进行数码管进行扫描时,由于过快,因此导致不稳定,普通加在扫描电路上频率为几十到几百KHZ。
9 体会与建议
体会:本次为期三周软件设计,共完毕了一种基本题和一种综合题。但是由于我对基本题扩展了功能(校时校分,因此比综合题更显得复杂)。
增强了自己VHDL编程能力,对VHDL自顶向下硬件设计思想有了更进一步理解。
由于自己此前学过VHDL,对VHDL有一定理解,并且也做过一种相对比较大项目,也是采用VHDL编程,因此本次课题都不大难。
在完毕课题期间,我以为对课题理解是重中之中,只对对系统功能有比较进一步了理解,才干保证设计合理性和对的性。然后就是自顶向下思想,如何将一种大型系统分为几种模块,然后再把各模块组合起来,如果能详细地分析出各个模块之间逻辑关系,一种复杂项目也就显得很简朴了。各个模块都是比较基本,只需要理解VHDL语言法则,就可以很轻松完毕。
我以为调试是系统设计过程中最难,也是最痛苦。这需要设计者足够细心,和有足够耐心。由于不细心就会浮现很大错误,并且很难找到。查错能力很重要,这和一种人编程有经验关于,因此要想不久找出错误,减少这个过程痛苦,只能更多地训练。
建议:本次软件设计时间安排比较灵活,均由同窗自已把握,但这样也使得时间比较零散,很难集中精力。因此我建议应当集中安排软件设计时间。此外应当出某些更有挑战性题供选取。
附录一、数字时钟设计
library ieee;--顶层文献
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity d_clock is
port(s1,s2:in std_logic;--校时校分控制开关
ck:in std_logic;--输入25MHZ时钟
css:out std_logic;--数码管和点阵现个区选取,CSS=0选取数码管
key:out std_logic_vector(2 downto 0);--位选
data_out:out std_logic_vector(7 downto 0));--段选
end entity d_clock;
architecture behave of d_clock is
component df —分频模块
port(clk1:in std_logic;
clk2:buffer std_logic);
end component;
component c_24--24位计数器
port(clk:in std_logic;
cout:out std_logic_vector(4 downto 0)
);
end component
component c_60--60位计数器
port(clk:in std_logic;
cc:out std_logic;
cout:out std_logic_vector(5 downto 0));
end component;
component select2—选取频率,即用来校时校分
port(clk1,clk2:in std_logic;
en1:in std_logic;
clk:out std_logic);
end component;
component show24—对0~23进行译码,相应数码管8段
port(
tim_data:in std_logic_vector(4 downto 0);
cout1,cout2:out std_logic_vector(7 downto 0));
end component;
component show60—对0~59进行译码,相应数码管8段
port(
tim_data:in std_logic_vector(5 downto 0);
cout1,cout2:out std_logic_vector(7 downto 0));
end component;
component SAOMIAO—动态扫描电路
port( clk:in std_logic;
cs:out std_logic;
da1,da2,da3,da4,da5,da6:in std_logic_vector(7 downto 0);
k:out std_logic_vector(2 downto 0);
da:out std_logic_vector(7 downto 0));
end component;
signal cp,cp1,cp2,ck1,ck2:std_logic;
signal c1,c2:std_logic_vector(5 downto 0);
signal c3:std_logic_vector(4 downto 0);
signal ten_h,d_h,ten_m,d_m,ten_s,d_s:std_logic_vector(7 downto 0);
begin
u1:df port map(clk1=>ck,clk2=>cp);
u2:c_60 port map(clk=>cp,cc=>ck1,cout=>c1);
u3:select2 port map(clk1=>ck1,clk2=>cp,en1=>s1,clk=>cp1);
u4:c_60 port map(clk=>cp1,cc=>ck2,cout=>c2);
u5:select2 port map(clk1=>ck2,clk2=>cp,en1=>s2,clk=>cp2);
u6:c_24 port map(clk=>cp2,cout=>c3);
u7:show60 port map(tim_data=>c1,cout1=>ten_s,cout2=>d_s);
u8:show60 port map(tim_data=>c2,cout1=>ten_m,cout2=>d_m);
u9:show24 port map(tim_data=>c3,cout1=>ten_h,cout2=>d_h);
u10:SAOMIAO port map(cs=>css,clk=>ck,da1=>ten_h,da2=>d_h,da3=>ten_m,da4=>d_m,da5=>ten_s,da6=>d_s,k=>key,da=>data_out);
end architecture behave;
library ieee;--分频电路
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity df is
port(clk1:in std_logic;--输入25MHZ
clk2:buffer std_logic);--输出1HZ
end entity df;
architecture behave of df is
signal g:std_logic_vector(4 downto 0);
begin
process(clk1)
begin
if clk1'event and clk1='1'then
if(g="0")then g<="0";
clk2<=not clk2;
else g<=g+"1";
end if;
end if;
end process;
end architecture behave;
library ieee;--24位计数器
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity c_24 is
port(clk:in std_logic;--输入时钟,来1HZ校时,或者来自分钟进位
cout:out std_logic_vector(4 downto 0)—输出小时数据
);
end entity c_24;
architecture behave of c_24 is
signal g:std_logic_vector(4 downto 0);
begin
process(clk)
begin
if(clk'event and clk='1')then
if g="10111"then
g<="00000";
else g<="00001"+g;
end if ;
end if;
cout<=g;
end process;
end architecture behave;
library ieee;--60计数器
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity c_60 is
port(clk:in std_logic;--输入时钟,来自1HZ校分或者是秒计数时钟,或者来自秋进位
cc:out std_logic;--秒和分计数到60产生一种进位
cout:out std_logic_vector(5 downto 0));--输出秒或分钟数据
end entity c_60;
architecture behave of c_60 is
signal g:std_logic_vector(5 downto 0);
begin
process(clk,g)
begin
if clk'event and clk='1' then
if g="111011" then
g<="000000";
cc<='1';
else g<=g+"000001";
cc<='0';
end if;
end if;
cout<=g;
end process;
end architecture behave;
library ieee;--选取是频率,即选取与否校时校分
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity select2 is
port(clk1,clk2:in std_logic;--两个供选取频率
en1:in std_logic;--控制开关
clk:out std_logic);--输出被选中频率
end entity select2;
architecture behave of select2 is
begin
process(clk1,clk2,en1)
begin
if en1='0' then
clk<=clk1;
else clk<=clk2;
end if;
end process;
end architecture behave;
library ieee;-- 对0~23进行译码,相应数码管8段
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity show24 is
port(
tim_data:in std_logic_vector(4 downto 0);--输入小时数据
cout1,cout2:out std_logic_vector(7 downto 0));--输出十位和个位相应8段数码管相应数据。
end entity show24;
architecture behave of show24 is
signal tcout1,tcout2:std_logic_vector(7 downto 0);
begin
process(tim_data)
begin
case tim_data is
when "00000"=>tcout1<="00000011";tcout2<="00000011";
when "00001"=>tcout1<="00000011";tcout2<="10011111";
when "00010"=>tcout1<="00000011";tcout2<="00100101";
when "00011"=>tcout1<="00000011";tcout2<="00001101";
when "00100"=>tcout1<="00000011";tcout2<="10011001";
when "00101"=>tcout1<="00000011";tcout2<="01001001";
when "00110"=>tcout1<="00000011";tcout2<="01000001";
when "00111"=>tcout1<="00000011";tcout2<="00011111";
when "01000"=>tcout1<="00000011";tcout2<="00000001";
when "01001"=>tcout1<="00000011";tcout2<="00011001";
when "01010"=>tcout1<="10011111";tcout2<="00000011";
when "01011"=>tcout1<="10011111";tcout2<="10011111";
when "01100"=>tcout1<="10011111";tcout2<="00100101";
when "01101"=>tcout1<="10011111";tcout2<="00001101";
when "01110"=>tcout1<="10011111";tcout2<="10011001";
when "01111"=>tcout1<="10011111";tcout2<="01001001";
when "10000"=>tcout1<="10011111";tcout2<="01000001";
when "10001"=>tcout1<="10011111";tcout2<="00011111";
when "10010"=>tcout1<="10011111";tcout2<="00000001";
when "10011"=>tcout1<="10011111";tcout2<="00011001";
when "10100"=>tcout1<="00100101";tcout2<="00000011";
when "10101"=>tcout1<="00100101";tcout2<="10011111";
when "10110"=>tcout1<="00100101";tcout2<="00100101";
when "10111"=>tcout1<="00100101";tcout2<="00001101";
when others=>tcout1<="11111111";tcout2<="11111111";
end case;
end process;
cout1<=not tcout1;
cout2<=not tcout2;
end architecture behave;
library ieee;对0~59进行译码,相应数码管8段
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity show60 is
port(
tim_data:in std_logic_vector(5 downto 0);--输入秒或分钟数据
cout1,cout2:out std_logic_vector(7 downto 0));--输出十位和个位相应8段数码管
end entity show60;
architecture behave of show60 is
signal tcout1,tcout2:std_logic_vector(7 downto 0);
begin
process(tim_data)
begin
case tim_data is
when "000000"=>tcout1<="00000011";tcout2<="00000011";
when "000001"=>tcout1<="00000011";tcout2<="10011111";
when "000010"=>tcout1<="00000011";tcout2<="00100101";
when "000011"=>tcout1<="00000011";tcout2<="00001101";
when "000100"=>tcout1<="00000011";tcout2<="10011001";
when "000101"=>tcout1<="00000011";tcout2<="01001001";
when "000110"=>tcout1<="00000011";tcout2<="01000001";
when "000111"=>tcout1<="00000011";tcout2<="00011111";
when "001000"=>tcout1<="00000011";tcout2<="00000001";
when "001001"=>tcout1<="00000011";tcout2<="00011001";
when "001010"=>tcout1<="10011111";tcout2<="00000011";
when "001011"=>tcout1<="10011111";tcout2<="10011111";
when "001100"=>tcout1<="10011111";tcout2<="00100101";
when "001101"=>tcout1<="10011111";tcout2<="00001101";
when "001110"=>tcout1<="10011111";tcout2<="10011001";
when "001111"=>tcout1<="10011111";tcout2<="01001001";
when "010000"=>tcout1<="10011111";tcout2<="01000001";
when "010001"=>tcout1<="10011111";tcout2<="00011111";
when "010010"=>tcout1<="10011111";tcout2<="00000001";
when "010011"=>tcout1<="10011111";tcout2<="00011001";
when "010100"=>tcout1<="00100101";tcout2<="00000011";
when "010101"=>tcout1<="00100101";tcout2<="10011111";
when "010110"=>tcout1<="00100101";tcout2<="00100101";
when "010111"=>tcout1<="00100101";tcout2<="00001101";
when "011000"=>tcout1<="00100101";tcout2<="10011001";
when "011001"=>tcout1<="00100101";tcout2<="01001001";
when "011010"=>tcout1<="00100101";tcout2<="01000001";
when "011011"=>tcout1<="00100101";tcout2<="00011111";
when "011100"=>tcout1<="00100101";tcout2<="00000001";
when "011101"=>tcout1<="00100101";tcout2<="00001101";
when "011110"=>tcout1<="00001101";tcout2<="00000011";
when "011111"=>tcout1<="00001101";tcout2<="10011111";
when "100000"=>tcout1<="00001101";tcout2<="00100101";
when "100001"=>tcout1<="00001101";tcout2<="00001101";
when "100010"=>tcout1<="00001101";tcout2<="10011001";
when "100011"=>tcout1<="00001101";tcout2<="01001001";
when "100100"=>tcout1<="00001101";tcout2<="01000001";
when "100101"=>tcout1<="00001101";tcout2<="00011111";
when "100110"=>tcout1<="00001101";tcout2<="00000001";
when "100111"=>tcout1<="00001101";tcout2<="00001101";
when "101000"=>tcout1<="10011001";tcout2<="00000011";
when "101001"=>tcout1<="10011001";tcout2<="10011111";
when "101010"=>tcout1<="10011001";tcout2<="00100101";
when "101011"=>tcout1<="10011001";tcout2<="00001101";
when "101100"=>tcout1<="10011001";tcout2<="10011001";
when "101101"=>tcout1<="10011001";tcout2<="01001001";
when "101110"=>tcout1<="10011001";tcout2<="01000001";
when "101111"=>tcout1<="10011001";tcout2<="00011111";
when "110000"=>tcout1<="10011001";tcout2<="000000
展开阅读全文