当前位置:文档之家› 南邮 课程设计VHDL语言报告

南邮 课程设计VHDL语言报告

南京邮电大学

通达学院

课程设计报告

设计类别: EDA-VHDL

专业名称: 通信工程

班级学号: ~~~~~~~~ 学生姓名: ~~~~~ 基本题 : 数字时钟设计

综合题 : 数码管学号滚动显示

同小组成员:

学号:~~~~~~~~~

姓名:~~~~~~

指导教师: 王奇、梅中辉、周小燕、孔凡坤日期:2012年6月11日—6月22日

一、数字时钟

1.实验目的

(1)掌握VHDL语言的语法规范,掌握时序电路描述方法

(2)掌握多个数码管动态扫描显示的原理及设计方法

2.实验任务要求

要求学生设计一个时钟,并输出到数码管显示时,分,秒。

3.设计思路及VHDL代码

首先要设置一个时钟信号,根据时钟信号的变化来进行时钟的变化,从秒的变化到时的变化条件是不同的。将时分秒各分为为十位和各位即六位数字显示时间来分析。

原理图如下:

分针个位信号

VHDL源程序如下:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

entity shizhong is

port( clk:in std_logic;

led1:out std_logic_vector(6 downto 0);

led2:out std_logic_vector(6 downto 0);

led3:out std_logic_vector(6 downto 0);

led4:out std_logic_vector(6 downto 0);

led5:out std_logic_vector(6 downto 0);

led6:out std_logic_vector(6 downto 0));

end shizhong;

architecture main of shizhong is

signal hou1:std_logic_vector(3 downto 0);

signal hou2:std_logic_vector(3 downto 0);

signal min1:std_logic_vector(3 downto 0);

signal min2:std_logic_vector(3 downto 0);

signal sec1:std_logic_vector(3 downto 0);

signal sec2:std_logic_vector(3 downto 0);

begin

-------------------------------------------------------------

h110:process(clk,hou2,min1,min2,sec1,sec2)

begin

if clk'event and clk='1' then

if (hou1="0010" and hou2="0011")and(min1="0101" and min2="1001") and (sec1="0101" and

sec2="1001") then

hou1<="0000";

else if (hou2="1001"and(min1="0101" and min2="1001") and (sec1="0101" and sec2="1001"))

then

hou1<=hou1+1;

end if;

end if;

end if;

end process h110;

——————————时钟的十位

---------------------------------------------------------------

h220:process(clk,min1,min2,sec1,sec2,hou1)

begin

if clk'event and clk='1' then

if (hou1="0010" and hou2="0011")and(min1="0101" and min2="1001") and (sec1="0101" and

sec2="1001") then

hou2<="0000";

else if hou2="1001"and(min1="0101" and min2="1001") and (sec1="0101" and sec2="1001")

then

hou2<="0000";

else if((min1="0101" and min2="1001") and (sec1="0101" and sec2="1001")) then

hou2<=hou2+1;--speak<=clk;

end if;

end if;

end if;

end if;

end process h220;

——————————时钟的个位

--------------------------------------------------------------

m110:process(clk,min2,sec1,sec2)

begin

if clk'event and clk='1' then

if (min1="0101" and min2="1001") and (sec1="0101" and sec2="1001") then min1<="0000";

else if (min2="1001"and (sec1="0101" and sec2="1001"))then

min1<=min1+1;

end if;

end if;

end if;

end process m110;

——————————分钟的十位

--------------------------------------------------------------

m220:process(clk,sec1,sec2)

begin

if clk'event and clk='1' then

if min2="1001"and (sec1="0101" and sec2="1001")then

min2<="0000";

else if (sec1="0101" and sec2="1001") then

min2<=min2+1;

end if;

end if;

end if;

end process m220;

——————————分钟的个位

--------------------------------------------------------------

s110:process(clk)

begin

if clk'event and clk='1' then

if (sec1="0101" and sec2="1001")then

sec1<="0000";

else if sec2="1001"then

sec1<=sec1+1;

end if;

end if;

end if;

end process s110;

——————————秒钟的十位

-------------------------------------------------------------- s220:process(clk)

begin

if clk'event and clk='1' then

if sec2="1001" then

sec2<="0000";

else sec2<=sec2+1;

end if;

end if;

end process s220;

——————————秒钟的个位--------------------------------------------------------------- disp:process(hou1,hou2,min1,min2,sec1,sec2)

begin

case hou1 is

when "0000"=>LED1<="0111111";

when "0001"=>LED1<="0000110";

when "0010"=>LED1<="1011011";

when others=>LED1<="1000000";

end case;

case hou2 is

when "0000"=>LED2<="0111111";

when "0001"=>LED2<="0000110";

when "0010"=>LED2<="1011011";

when "0011"=>LED2<="1001111";

when "0100"=>LED2<="1100110";

when "0101"=>LED2<="1101101";

when "0110"=>LED2<="1111101";

when "0111"=>LED2<="0000111";

when "1000"=>LED2<="1111111";

when "1001"=>LED2<="1101111";

when others=>LED2<="1000000";

end case;

case min1 is

when "0000"=>LED3<="0111111"; when "0001"=>LED3<="0000110"; when "0010"=>LED3<="1011011"; when "0011"=>LED3<="1001111"; when "0100"=>LED3<="1100110"; when "0101"=>LED3<="1101101"; when others=>LED3<="1000000"; end case;

case min2 is

when "0000"=>LED4<="0111111"; when "0001"=>LED4<="0000110"; when "0010"=>LED4<="1011011"; when "0011"=>LED4<="1001111"; when "0100"=>LED4<="1100110"; when "0101"=>LED4<="1101101"; when "0110"=>LED4<="1111101"; when "0111"=>LED4<="0000111"; when "1000"=>LED4<="1111111"; when "1001"=>LED4<="1101111"; when others=>LED4<="1000000"; end case;

case sec1 is

when "0000"=>LED5<="0111111"; when "0001"=>LED5<="0000110"; when "0010"=>LED5<="1011011"; when "0011"=>LED5<="1001111"; when "0100"=>LED5<="1100110"; when "0101"=>LED5<="1101101"; when others=>LED5<="1000000"; end case;

case sec2 is

when "0000"=>LED6<="0111111"; when "0001"=>LED6<="0000110"; when "0010"=>LED6<="1011011"; when "0011"=>LED6<="1001111"; when "0100"=>LED6<="1100110"; when "0101"=>LED6<="1101101"; when "0110"=>LED6<="1111101"; when "0111"=>LED6<="0000111"; when "1000"=>LED6<="1111111"; when "1001"=>LED6<="1101111"; when others=>LED6<="1000000"; end case;

end process disp;

----------------------------------------------------------- end main;

4.仿真波形及分析

通过波形可以看出,秒,分,时各位之间可以很好地完成进位功能,秒钟达最大值59进一并清零,分钟达最大值59进一并清零,时钟打最大值23进一并清零,数字时钟功能可以实现。

5.实验总结与体会

本实验为基础题的第一题,整体功能与实际联系较为紧密,因此各模块的分析和设计方面难度减少了很多,通过这个课题的设计,我们初步认识了VHDL语言,以及quartus II 软件的具体应用方法,能够

很直观地将电路模块化分析并使用vhdl语言设计出来。

二、数码管学号滚动显示

1.实验目的

(1)掌握VHDL 语言的语法规范,掌握时序电路描述方法 (2)掌握多个数码管动态扫描显示的原理及设计方法

2.实验任务要求

要求学生在六个数码管滚动显示自己的学号(六位),每隔一定时间循环移位一次,学号为奇数则左移,学号为偶数则右移。间隔时间可由开关选择1秒,2秒,3秒和4秒。

3.设计思路及VHDL 代码

本题要求六位学号可以滚动显示,通过对其功能的理解,可以找出每个数字对应的数码管位置变化的规律。具体实现可以通过在每个脉冲上升沿触发学号中六个数字001908依次在六个数码管上输出,而在六个脉冲之后,六位学号还是依次输出,但是显示的数码管不同,首个数字在第二位数码管显示,以此类推,最后一位在第一位数码管显示。六个脉冲构成一个循环,以同上的方法类推显示即可实现学号的右移效果。显示的间隔时间可以通过源程序内改变运行次数来控制。

原理图如下:

模块设计:

输入&输出

输入: clk ------时钟信号

column ------行列式键盘的4列

输出: led_out ------数码管8段显示,可显示0~9,A~F led_sel ------选择6个数码管,‘1’表示点亮对应数码管

output ------分频后的时钟

Interval ------随学号移动而数值改变的寄存器

●分频电路模块

PROCESS(clk)--12分频电路

V ARIABLE counter: std_logic_vector(2 downto 0);--计数寄存器,12分频输入时钟为1Hz BEGIN

IF (clk'EVENT AND clk ='0') THEN --下降沿有效

counter := counter + 1 ;

IF (counter = 6) THEN

clk_temp <= NOT clk_temp; --分频后的时钟变化

counter := "000";

END IF;

END IF;

END PROCESS;

PROCESS(clk)--读取行列式键盘的键值

(这段程序是对时钟clock进行分频,进而得到新的时钟clk_temp,并赋值给输出output)

●移位控制模块

BEGIN

IF(clk'EVENT AND clk = '0')THEN

CASE column IS

WHEN "1110" =>

key_code <= "00";

WHEN "1101" =>

key_code <= "01";

WHEN "1011" =>

key_code <= "10";

WHEN "0111" =>

key_code <= "11";

WHEN OTHERS =>

key_code <= "00";

END CASE;

END IF;

END PROCESS;

process (clk_temp)

V ARIABLE time_count : std_logic_vector(1 DOWNTO 0);

begin

if (clk_temp 'event and clk_temp = '0') then--下降沿有效

time_count := time_count + 1;

CASE key_code IS

WHEN "00" =>

shift <= shift- 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

WHEN "01" =>

if(time_count = "10") then

time_count := "00" ;

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

end if;

WHEN "10" =>

if(time_count = "11") then

time_count := "00";

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

end if;

WHEN "11" =>

if(time_count = "00") then

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

end if;

WHEN OTHERS =>

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

END CASE;

end if;

end process;

注: 该模块利用key_code的四个数值来控制四个case,由于time_count 初始值是00,在进入运算时是01,根据case的不同,运行次数不同,分别是一次,两次,三次和四次,根据这个来控制移动的间隔时间。

数码管显示模块

process (clk)------显示学号001908

V ARIABLE led_sel_llb :std_logic_vector(3 DOWNTO 0); --信号量,6个数码管显示的选择

begin

if (clk 'event and clk='0') then --时钟下降沿有效

if (led_sel_count = "0000") then --轮询6个数码管

led_sel_count <= "0101";

else

led_sel_count <= led_sel_count - "0001";

end if;

--0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff

-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 空

case led_sel_count is --选择要要显示的值

when "0000" => led_out <= X"80"; --位置6,内容8

when "0001" => led_out <= X"c0"; --位置5,内容0

when "0010" => led_out <= X"90"; --位置4,内容9

when "0011" => led_out <= X"f9"; --位置3,内容1

when "0100" => led_out <= X"c0"; --位置2,内容0

when "0101" => led_out <= X"c0"; --位置1,内容0

when others => led_out <= X"92"; --其他情况下,位置6,内容5

end case;

led_sel_llb := led_sel_count + shift;

if (led_sel_llb >= "0110") then

led_sel_llb := led_sel_llb - "0110";

end if;

case led_sel_llb is --选择要被点亮的数码管

when "0000" => led_sel <= "000001"; --位置6

when "0001" => led_sel <= "000010"; --位置5

when "0010" => led_sel <= "000100"; --位置4

when "0011" => led_sel <= "001000"; --位置3

when "0100" => led_sel <= "010000"; --位置2

when "0101" => led_sel <= "100000"; --位置1

when others => led_sel <= "000001"; --其他情况下,位置6,内容5

end case;

end if;

end process;

注: 该模块中,led_sel用来表示选中的数码管,led_out 表示输出的数值。每一个clock 过来,都会输出一个数,依次是0-0-1-9-0-8,而数字输出在哪个数码管是由相同时刻的led_sel决定的。由于时钟频率很高,虽然每个时钟来临时只有一个数码管被点亮,但由于视觉停留,所以可以达到每个数码管都被点亮的效果。

VHDL源程序如下:

LIBRARY ieee ;

USE ieee.std_logic_1164.all ;

USE ieee.std_logic_unsigned.all ;

--显示模块

ENTITY llb IS

PORT (

clk : IN STD_LOGIC;

led_out : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --数码管8段显示,可显示0~9,A~F

led_sel : BUFFER STD_LOGIC_VECTOR(5 DOWNTO 0); --选择6个数码管,‘1’表示点亮对应数码管

output : OUT STD_LOGIC;

interval : OUT STD_LOGIC_VECTOR(2 downto 0);

column : IN STD_LOGIC_VECTOR(3 downto 0) --行列式键盘的4列) ;

END llb ;

ARCHITECTURE Behavior OF llb IS

signal clk_temp : std_logic := '1'; --用作分频后的电路时钟signal led_sel_count : std_logic_vector(3 DOWNTO 0); --信号量,6个数码管显示的选择

signal div_cnt : std_logic_vector(1 downto 0); --行扫描驱动

signal scan_key : std_logic_vector(3 DOWNTO 0); --扫描码寄存器

signal key_code : std_logic_vector(1 DOWNTO 0); --存储键值

signal shift : std_logic_vector(2 DOWNTO 0):= "110"; --控制数码管显示的数据右移

begin

output <= clk_temp;

interval <= shift;

PROCESS(clk)--12分频电路

V ARIABLE counter: std_logic_vector(2 downto 0);--计数寄存器,12分频输入时钟为1Hz

BEGIN

IF (clk'EVENT AND clk ='0') THEN --下降沿有效

counter := counter + 1 ;

IF (counter = 6) THEN

clk_temp <= NOT clk_temp; --分频后的时钟变化

counter := "000";

END IF;

END IF;

END PROCESS;

PROCESS(clk)--读取行列式键盘的键值

BEGIN

IF(clk'EVENT AND clk = '0')THEN

CASE column IS

WHEN "1110" =>

key_code <= "00";

WHEN "1101" =>

key_code <= "01";

WHEN "1011" =>

key_code <= "10";

WHEN "0111" =>

key_code <= "11";

WHEN OTHERS =>

key_code <= "00";

END CASE;

END IF;

END PROCESS;

process (clk_temp)

V ARIABLE time_count : std_logic_vector(1 DOWNTO 0);

begin

if (clk_temp 'event and clk_temp = '0') then--下降沿有效

time_count := time_count + 1;

CASE key_code IS

WHEN "00" =>

shift <= shift- 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

WHEN "01" =>

if(time_count = "10") then

time_count := "00" ;

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

end if;

WHEN "10" =>

if(time_count = "11") then

time_count := "00";

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

end if;

WHEN "11" =>

if(time_count = "00") then

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

end if;

WHEN OTHERS =>

shift <= shift - 1; --数据右移1位

if(shift = "000") then

shift <="110";

end if;

END CASE;

end if;

end process;

PROCESS(clk)--行扫描驱动,产生行扫描的值

BEGIN

IF(clk'EVENT AND clk = '0')THEN

div_cnt <= div_cnt + 1;

END IF;

END PROCESS;

PROCESS(div_cnt)--产生行扫描的值用于一行一行的轮询4行

BEGIN

CASE div_cnt IS

WHEN "00" =>

scan_key<="1110";

WHEN "01" =>

scan_key<="1101";

WHEN "10" =>

scan_key<="1011";

WHEN "11" =>

scan_key<="0111";

WHEN OTHERS =>

NULL;

END CASE;

END PROCESS;

process (clk)--显示学号001908

V ARIABLE led_sel_llb :std_logic_vector(3 DOWNTO 0); --信号量,6个数码管显示的

选择

begin

if (clk 'event and clk='0') then --时钟下降沿有效

if (led_sel_count = "0000") then --轮询6个数码管

led_sel_count <= "0101";

else

led_sel_count <= led_sel_count - "0001";

end if;

--0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff

-- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 空

case led_sel_count is --选择要要显示的值

when "0000" => led_out <= X"80"; --位置6,内容8

when "0001" => led_out <= X"c0"; --位置5,内容0

when "0010" => led_out <= X"90"; --位置4,内容9

when "0011" => led_out <= X"f9"; --位置3,内容1

when "0100" => led_out <= X"c0"; --位置2,内容0

when "0101" => led_out <= X"c0"; --位置1,内容0

when others => led_out <= X"92"; --其他情况下,位置6,内容5

end case;

led_sel_llb := led_sel_count + shift;

if (led_sel_llb >= "0110") then

led_sel_llb := led_sel_llb - "0110";

end if;

case led_sel_llb is --选择要被点亮的数码管

when "0000" => led_sel <= "000001"; --位置6

when "0001" => led_sel <= "000010"; --位置5

when "0010" => led_sel <= "000100"; --位置4

when "0011" => led_sel <= "001000"; --位置3

when "0100" => led_sel <= "010000"; --位置2

when "0101" => led_sel <= "100000"; --位置1

when others => led_sel <= "000001"; --其他情况下,位置6,内容5

end case;

end if;

end process;

end Behavior;

4.仿真波形及分析

学号右移功能:

11000000表示学号0 11111001表示学号1 10010000表示学号9 10000000表示学号8

100000表示左第一位数码管亮,010000表示第二位,以此类推。

初始状态,数码管显示学号0 0 1 9 0 8

右移一位,8 0 0 1 9 0

右移两位,0 8 0 0 1 9

右移三位,9 0 8 0 0 1

右移四位,1 9 0 8 0 0

右移五位,0 1 9 0 8 0

以上为一次循环。

循环间隔控制功能

显示间隔的控制由column决定,1110表示循环间隔为1秒,1101表示循环间隔为2秒,1011表示循环间隔为3秒,0111表示循环间隔为4秒。

间隔一秒情况:

间隔两秒情况:

间隔三秒情况:

间隔四秒情况:

5.实验总结与体会

本题为提高题第四题,整体功能和各模块的功能分析方面都比基础题要更为复杂,但由于与前一题同样是使用数码管扫描显示的设计方法,使的一些模块的设计方面可以很好地简化,虽然其中也有很多错误与缺陷,在学号的右移时也有一些问题,调试时问题更是不断,仿真波形也与课题要求有所差异,但最终还是达到了预期效果。通过实验,我们加深了对VHDL语言的认识和运用,对EDA的硬件应用方面也不仅仅是表面浅显的了解。不但学会了设计程序的方法,更重要的是学会了将一个课题进行功能分析,具体到各个功能子模块的分析方法。

相关主题
相关文档 最新文档