20##级数字电路实验报告
实验名称: EDA基础实验
学生姓名: 桂柯易
班 级: 2009211120
班内序号: 07
学 号: 09210580
日 期: 20##年4月28日
1.实验要求
【实验目的】
1.熟悉用QuartusII原理图输入法进行电路设计和仿真;
2.掌握QuartusII图形模块单元的生成与调用;
3.熟悉用VHDL语言设计组合逻辑电路和时序电路的方法;
4.熟悉用QuartusII文本输入法和图形输入法进行电路设计;
5.熟悉不同的编码及其之间的转换;
6.掌握触发器的逻辑功能及使用方法;
7.熟悉计数器、寄存器、锁存器、分频器、移位寄存器的设计方法
8.掌握VHDL语言的语法规范,掌握时序电路描述方法;
9.掌握多个数码管动态扫描显示的原理及设计方法。
【实验所用仪器及元器件】
1.计算机
2.直流稳压电源
3.数字系统与逻辑设计实验开发板
【实验内容】
1.用逻辑门设计实现一个半加器,仿真验证其功能,并生成新的半加器图形模块单元。
2.用实验内容1中生成的半加器模块和逻辑门设计实现一个全加器,仿真验证其功
能,并下载到实验板测试,要求用拨码开关设定输入信号,发光二极管显示输出信
号。
3.用3线-8线译码器(74LS138)和逻辑门设计实现函数F,仿真验证其功能,并下
载到实验板测试。要求用拨码开关设定输入信号,发光二极管显示输出信号。
4.用VHDL语言设计实现一个3位二进制数值比较器,仿真验证其功能,并下载到实
验板测试。要求用拨码开关设定输入信号,发光二极管显示输出信号。
5.用VHDL语言设计实现一个4选1的数据选择器;一个8421码转换为格雷码的代码
转换器;一个举重比赛裁判器;一个带同步置位和同步复位功能的D触发器;一个
带异步复位的4位二进制减计数器;一个带异步复位的8421码十进制计数器;一
个带异步复位的4位自启动环形计数器;一个带控制端的8位二进制寄存器,当控
制端为‘1’时,电路正常工作,否则输出为高阻态;一个分频系数为12,分频输
出信号占空比为50%的分频器。仿真验证其功能,并下载到实验板测试。要求用拨
码开关和按键开关设定输入信号,发光二极管显示输出信号。(注:有几个不需要
下载到实验板测试)
2.程序分析
全加器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY h_adder IS
PORT(a,b:IN STD_LOGIC;
co,so:OUT STD_LOGIC);
END ENTITY h_adder;
ARCHITECTURE a OF h_adder IS
BEGIN
so<= a XOR b;
co<= a AND b;
END;
library ieee;
use ieee.std_logic_1164.all;
entity GKY07P3 is
port(ain,bin,cin:in std_logic;
cout,sum:out std_logic);
end entity GKY07P3;
architecture a of GKY07P3 is
component h_adder
port(a,b:in std_logic;
co,so:out std_logic);
end component;
signal d,e,f:std_logic;
begin
u1:h_adder port map(a=>ain,b=>bin,co=>d,so=>e);
u2:h_adder port map(a=>e,b=>cin,co=>f,so=>sum);
cout<=d or f;
end;
整体思路是按照实验的要求,先做出一个半加器,然后在这个半加器的基础上实现全加器的功能。
函数F:
3位二进制数值比较器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P4 IS
PORT(A:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
B:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
YA,YB,YC:OUT STD_LOGIC);
END GKY07P4;
ARCHITECTURE behave OF GKY07P4 IS
BEGIN
PROCESS(A,B)
BEGIN
IF(A>B)THEN
YA<='1';YB<='0';YC<='0';
ELSIF(A<B)THEN
YA<='0';YB<='1';YC<='0';
ELSE
YA<='0';YB<='0';YC<='1';
END IF;
END PROCESS;
END behave;
将比较的过程直接交给软件本身,只需通过不同的二进制数输出比较的结果即可。
4选1数据选择器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P5 IS
PORT(G,A1,A0:IN STD_LOGIC;
D0,D1,D2,D3:IN STD_LOGIC;
Y,YB:OUT STD_LOGIC);
END GKY07P5;
ARCHITECTURE behave OF GKY07P5 IS
SIGNAL comb:STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
comb<=A1&A0;
PROCESS(G,comb,D0,D1,D2,D3)
BEGIN
IF G='0'THEN
CASE comb IS
WHEN"00"=>Y<=D0;YB<= NOT D0;
WHEN"01"=>Y<=D1;YB<= NOT D1;
WHEN"10"=>Y<=D2;YB<= NOT D2;
WHEN"11"=>Y<=D3;YB<= NOT D3;
WHEN OTHERS=>Y<='0';YB<='1';
END CASE;
ELSE
Y<='0';YB<='1';
END IF;
END PROCESS;
END behave;
主要是WHEN语句的运用,用两位二进制数表示四种数据输出状态,再用WHEN语句具体实现。
8421码转换为格雷码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P6 IS
PORT(A:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
B:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END GKY07P6;
ARCHITECTURE behave OF GKY07P6 IS
BEGIN
PROCESS(A)
BEGIN
B(3)<=A(3);
B(2)<=A(3) XOR A(2);
B(1)<=A(2) XOR A(1);
B(0)<=A(1) XOR A(0);
END PROCESS;
END behave;
本来是考察WHEN语句的运用,将所有的情况用WHEN语句列出来,但是因为8421码转换为格雷码的时候有一个相关的计算式子,采用这个式子可以使程序简化不少。
举重比赛裁判器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P7 IS
PORT(a:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
b:OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END GKY07P7;
ARCHITECTURE behave OF GKY07P7 IS
BEGIN
PROCESS(a)
BEGIN
CASE a IS
WHEN"000" => b <= "000";
WHEN"001" => b <= "000";
WHEN"010" => b <= "000";
WHEN"011" => b <= "100";
WHEN"100" => b <= "100";
WHEN"101" => b <= "111";
WHEN"110" => b <= "111";
WHEN"111" => b <= "111";
END CASE;
END PROCESS;
END;
与前几题不同,这个更偏向应用。列出实际情况的状态表,发现三个裁判的不同判断各对应红黄绿灯的亮灭情况,故还是WHEN语句的应用。
D触发器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P8 IS
PORT(d,clk,set,reset:IN STD_LOGIC;
q,qb:OUT STD_LOGIC);
END GKY07P8;
ARCHITECTURE struc OF GKY07P8 IS
BEGIN
PROCESS(clk,set,reset)
BEGIN
IF set='0' AND reset='1' THEN
q<='1';qb<='0';
ELSIF set='1' AND reset='0' THEN
q<='0';qb<='1';
ELSIF clk'EVENT AND clk='1' THEN
q<=d;qb<=NOT d;
END IF;
END PROCESS;
END struc;
和书上的例子基本一样,只是同步置位和同步复位都跟随时间脉冲的变化。
4位二进制减计数器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P9 IS
PORT(clk,reset:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END GKY07P9;
ARCHITECTURE struc OF GKY07P9 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF reset='0'THEN
q_temp<="1111";
ELSIF q_temp<="0000" THEN
q_temp<="1111";
ELSE
q_temp<=q_temp-1;
END IF;
END IF;
END PROCESS;
q<=q_temp;
END struc;
从状态‘1111’到状态‘0000’,然后再跳回‘1111’。异步复位不需要跟随脉冲变化,要立即复位。
8421码十进制计数器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P10 IS
PORT(clk,reset:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END GKY07P10;
ARCHITECTURE struc OF GKY07P10 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF reset='1'THEN
q_temp<="0000";
ELSIF q_temp="1001"THEN
q_temp<="0000";
ELSE
q_temp<=q_temp+1;
END IF;
END IF;
END PROCESS;
q<=q_temp;
END struc;
从状态‘0000’到状态‘1001’,然后再跳回‘0000’,异步复位要立即复位。
4位环形计数器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P11 IS
PORT(clk,reset:IN STD_LOGIC;
countout:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END GKY07P11;
ARCHITECTURE behave OF GKY07P11 IS
SIGNAL nextcount: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(clk,reset)
BEGIN
IF RESET='1' THEN nextcount<="0001";
ELSIF(clk'EVENT AND clk='1')THEN
CASE nextcount IS
WHEN"0001"=> nextcount <="0010";
WHEN"0010"=> nextcount <="0100";
WHEN"0100"=> nextcount <="1000";
WHEN OTHERS=>nextcount<="0001";
END CASE;
END IF;
END PROCESS;
countout<=nextcount;
END behave;
计数状态在‘0001’,‘0010’,‘0100’,‘1000’四个之间转换,由于需要能够自启动,对别状态的处理是全部引到那四个计数状态上。
8位二进制寄存器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY GKY07P12 IS
PORT(d:IN STD_LOGIC_VECTOR(7 DOWNTO 0);
oe,clk:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END GKY07P12;
ARCHITECTURE struc OF GKY07P12 IS
SIGNAL temp:STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
PROCESS(clk,oe)
BEGIN
IF oe='1' THEN
IF clk'EVENT AND clk='1' THEN
temp<=d;
END IF;
ELSE
temp<="ZZZZZZZZ";
END IF;
q<=temp;
END PROCESS;
END struc;
和书上的例子基本一样,将低电平控制改成高电平控制即可。
分频器:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P13 IS
PORT(clk,clear:IN STD_LOGIC;
clk_out:OUT STD_LOGIC);
END GKY07P13;
ARCHITECTURE struc OF GKY07P13 IS
SIGNAL temp:INTEGER RANGE 0 TO 11;
BEGIN
p1:PROCESS(clear,clk)
BEGIN
IF clear='0' THEN
temp<=0;
ELSIF clk'EVENT AND clk='1' THEN
IF temp=11 THEN
temp<=0;
ELSE
temp<=temp+1;
END IF;
END IF;
END PROCESS p1;
p2:PROCESS(temp)
BEGIN
IF temp<6 THEN
clk_out<='0';
ELSE
clk_out<='1';
END IF;
END PROCESS p2;
END struc;
很重要的一个器件,但是设计难度并不很高,首先是模为12的计数,然后是占空比50%。
数码管串行扫描电路:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P14 IS
PORT(clk,clear:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
countout:OUT STD_LOGIC_VECTOR(5 DOWNTO 0));
END GKY07P14;
ARCHITECTURE behave OF GKY07P14 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL count:STD_LOGIC_VECTOR(5 DOWNTO 0);
SIGNAL cnt:INTEGER RANGE 0 TO 5;
BEGIN
p1:PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF(cnt=5)THEN cnt<=0;
ELSE
cnt<=cnt+1;
END IF;
END IF;
END PROCESS;
p2:PROCESS(cnt)
BEGIN
IF(clear='0')THEN count<="111111";
ELSE
CASE cnt IS
WHEN 1=>count<="101111";q_temp<="0110000";
WHEN 2=>count<="110111";q_temp<="1101101";
WHEN 3=>count<="111011";q_temp<="1111001";
WHEN 4=>count<="111101";q_temp<="0110011";
WHEN 5=>count<="111110";q_temp<="1011011";
WHEN 0=>count<="011111";q_temp<="1111110";
END CASE;
END IF;
END PROCESS;
countout<=count;
q<=q_temp;
END behave;
先用0~5六进制计数器产生六个计数状态,这六个状态同时决定二极管点亮的数字和数码管接通的电路,在时钟信号频率很高的时候可以同时显示0~5六个数字。只是在下载到实验板的时候与芯片的各个引脚一定要对应,不然容易达不到实验要求。
数码管滚动显示电路:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P14 IS
PORT( clk,clear:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
countout:OUT STD_LOGIC_VECTOR(5 DOWNTO 0));
END GKY07P14;
ARCHITECTURE behave OF GKY07P14 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL count:STD_LOGIC_VECTOR(5 DOWNTO 0);
SIGNAL cnt,cnt1:INTEGER RANGE 0 TO 5;
SIGNAL tmp:INTEGER RANGE 0 TO 1999;
signal clk1:STD_LOGIC;
BEGIN
p0:PROCESS(clk,clear)
BEGIN
IF clear='0' THEN tmp<=0;
ELSIF clk'EVENT AND clk='1' THEN
IF tmp=1999 THEN
tmp<=0;
ELSE
tmp<=tmp+1;
END IF;
END IF;
END PROCESS p0;
p1:PROCESS(tmp)
BEGIN
IF clk'EVENT AND clk='1' THEN
IF tmp<1000 THEN
clk1<='0';
ELSE
clk1<='1';
END IF;
END IF;
END PROCESS p1;
p2:PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF(cnt=5)THEN cnt<=0;
ELSE
cnt<=cnt+1;
END IF;
END IF;
END PROCESS p2;
p3:PROCESS(clk1)
BEGIN
IF(clk1'EVENT AND clk1='1')THEN
IF(cnt1=5)THEN cnt1<=0;
ELSE
cnt1<=cnt1+1;
END IF;
END IF;
END PROCESS p3;
p4:PROCESS(cnt,cnt1)
BEGIN
IF(clear='0')THEN q_temp<="0000000";
ELSE
CASE cnt+cnt1 IS
WHEN 0=>q_temp<="1111110";
WHEN 1=>q_temp<="0110000";
WHEN 2=>q_temp<="1101101";
WHEN 3=>q_temp<="1111001";
WHEN 4=>q_temp<="0110011";
WHEN 5=>q_temp<="1011011";
WHEN 6=>q_temp<="1111110";
WHEN 7=>q_temp<="0110000";
WHEN 8=>q_temp<="1101101";
WHEN 9=>q_temp<="1111001";
WHEN 10=>q_temp<="0110011";
WHEN 11=>q_temp<="1011011";
WHEN OTHERS =>q_temp<="0000000";
END CASE;
END IF;
END PROCESS p4;
q<=q_temp;
p5:PROCESS(cnt)
BEGIN
IF(clear='0')THEN count<="111111";
ELSE
CASE cnt IS
WHEN 0=>count<="011111";
WHEN 1=>count<="101111";
WHEN 2=>count<="110111";
WHEN 3=>count<="111011";
WHEN 4=>count<="111101";
WHEN 5=>count<="111110";
WHEN OTHERS =>count<="111111";
END CASE;
END IF;
END PROCESS p5;
countout<=count;
END behave;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY GKY07P14 IS
PORT( clk,clear:IN STD_LOGIC;
q:OUT STD_LOGIC_VECTOR(6 DOWNTO 0);
countout:OUT STD_LOGIC_VECTOR(5 DOWNTO 0));
END GKY07P14;
ARCHITECTURE behave OF GKY07P14 IS
SIGNAL q_temp:STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL count:STD_LOGIC_VECTOR(5 DOWNTO 0);
SIGNAL cnt,cnt1:INTEGER RANGE 0 TO 11;
SIGNAL tmp:INTEGER RANGE 0 TO 1999;
signal clk1:STD_LOGIC;
BEGIN
p0:PROCESS(clk,clear)
BEGIN
IF clear='0' THEN tmp<=0;
ELSIF clk'EVENT AND clk='1' THEN
IF tmp=1999 THEN
tmp<=0;
ELSE
tmp<=tmp+1;
END IF;
END IF;
END PROCESS p0;
p1:PROCESS(tmp)
BEGIN
IF clk'EVENT AND clk='1' THEN
IF tmp<1000 THEN
clk1<='0';
ELSE
clk1<='1';
END IF;
END IF;
END PROCESS p1;
p2:PROCESS(clk)
BEGIN
IF(clk'EVENT AND clk='1')THEN
IF(cnt=11)THEN cnt<=0;
ELSE
cnt<=cnt+1;
END IF;
END IF;
END PROCESS p2;
p3:PROCESS(clk1)
BEGIN
IF(clk1'EVENT AND clk1='1')THEN
IF(cnt1=11)THEN cnt1<=0;
ELSE
cnt1<=cnt1+1;
END IF;
END IF;
END PROCESS p3;
p4:PROCESS(cnt,cnt1)
BEGIN
IF(clear='0')THEN q_temp<="0000000";
ELSE
CASE cnt+cnt1 IS
WHEN 6=>q_temp<="1111110";
WHEN 7=>q_temp<="0110000";
WHEN 8=>q_temp<="1101101";
WHEN 9=>q_temp<="1111001";
WHEN 10=>q_temp<="0110011";
WHEN 11=>q_temp<="1011011";
WHEN OTHERS =>q_temp<="0000000";
END CASE;
END IF;
END PROCESS p4;
q<=q_temp;
p5:PROCESS(cnt)
BEGIN
IF(clear='0')THEN count<="111111";
ELSE
CASE cnt IS
WHEN 0=>count<="011111";
WHEN 1=>count<="101111";
WHEN 2=>count<="110111";
WHEN 3=>count<="111011";
WHEN 4=>count<="111101";
WHEN 5=>count<="111110";
WHEN OTHERS =>count<="111111";
END CASE;
END IF;
END PROCESS p5;
countout<=count;
END behave;
基本思路和串行显示类似,只是需要做到显示数字不断变化,因此先采用分频器得到一个频率稍低的时钟信号,控制另一个计数器技术状态的转换,这样使得数字变换的频率稍微不同于数码管接通的顺序,具体实现两种不同的滚动显示的时候计数器的状态个数也是有点区别的。其他步骤基本和串行显示相同。
3.程序运行结果
全加器:
函数F:
3位二进制数值比较器:
4选1数据选择器:
8421码转换为格雷码:
举重比赛裁判器:
D触发器:
4位二进制减计数器:
8421码十进制计数器:
4位环形计数器:
分频器:
数码管串行扫描电路:
数码管滚动显示电路:
4.总结
1.实验时出现的问题及解决办法:
实验一开始的上手步骤书上罗列的很详细,一步一步来几乎没有问题,一般都是在仿真的时候,有关输入信号的频率设置会出现一些小问题有时候自己调试,有时候询问老师,一般很容易就能解决。
第一次尝试直接写的程序是8421码转换为格雷码,按照老师和书上的要求是要考察WHEN语句的应用,但是鉴于8421码转换成格雷码的时候每位都有相应的关系式,我采用了后者,节省了不少的语句。仿真的时候出现了第一个比较难的问题,由于需要涵盖输入信号的所有情况,输入信号的设置要很巧妙,先是自己研究,又在老师的稍微帮助下,成功解决了。
最后一个小综合实验要求之前编好的程序用到了状态变量,和老师只用0~5六进制计数器的要求不同,于是在课堂上又把程序稍作修改。其中第二个要求是要滚动显示,一开始没有想到分频器,怎么都得不到实验结果,后来参考同学的程序使用了分频器,并适当增加计数器的位数,最终达到了实验的要求。
2.心得体会:
这学期第一次接触数电实验,感觉和前面电路实验很大的一点不同是:数电实验不需要我们一步一步去搭实验电路,一切都在电路板上完成,相比较电路的结构,我们更需要了解电路的功能,尤其是电路在工作状态下的各项参数。同时接触了一门新的编程语言VHDL和编程软件Quartus,感觉还是很新颖、很好奇的。三次实验的程序都是自己独立编写,有些可能参考了老师和同学的建议,所以总的来说收获很大。
3.下一步的改进:
大三应该还有数电实验,而且会涉及到编程,所以暑假有时间的话,要好好熟悉一下Quartus这个编程软件,争取大三的VHDL全部自己独立编写,尽量不询问老师和同学。