北航FPGA实验报告
电气技术实践
可编程逻辑器件FPGA应用开发
实验报告
姓名
班级
学号
2016年12月
目录
二、实验要求
三、实验内容
四、实验代码及实验结果
1、4位二进制加法计数器......................................
2、半加器....................................................
3、RS触发器.................................................
4、数码管十六进制计数器......................................
5、跑马灯....................................................
6、键盘电路..................................................
7、LED点阵显示..............................................
8、多人抢答器................................................
五、实验感想
一、实验目的
1、熟悉使用可编程逻辑器件(Altera公司FPGACyclone系列EP1C6Q)。
2、熟悉使用硬件描述语言VHDL。
3、掌握FPGA集成环境(Altera公司FPGAQuartusII9.0)开发流程。
4、熟悉使用核心目标系统板与接口电路等工作原理及其功能模块绑定信息。
5、熟悉并掌握下载线方式和下载文件的选择。
二、实验要求
1、学习并掌握文本、图形等输入和时序、功能仿真方法。
2、学习并熟悉门电路、组合电路、时序电路等单一模块功能。
3、学习并设计各种不同状态机逻辑功能。
4、学习并设计由单一模块→较多功能模块集成→系统集成方法。
5、学习并选择多种模式显示(发光二极管显示、米字型数码管显示、七段数码管→动
态扫描或静态扫描显示、LED点阵显示各种字符和图形或静止或移动等方式、LCD液晶显示各种字符和图形或静止或移动等方式)。
6、根据自已的兴趣和愿望,可从以下给定的实验目录中选取或自已设定功能题目。
7、实验数目没有要求,关键是看质量,是否是自已编写、调试、实现。
三、实验内容
1、按指导书集成开发环境章节操作实现文本编程实例1和图形编程实例2全过程。
2、任选门电路、组合电路、时序电路实验各完成一个其逻辑功能,其实现方案自已规
定。在进行FPGA目标器件输入和输出引脚绑定时,输入引脚绑定高/低电平、单脉冲、各种分频连续脉冲等多种信号,输出引脚可绑定发光二极管、七段数码管、LED点阵等显示模式。
3、在完成1位十进制计数器的基础上,可增加完成2或3等多位十进制计数器逻辑功
能并用多位七段数码管来显示。
4、用LED点阵显示任意字符、图形等信息。
四、实验代码及实验结果
1、4位二进制加法计数器
(1)实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityerjinzhiis
port(clk,
rst:instd_logic;
q:outstd_logic_vector(3downto0));
endentityerjinzhi;
architecturebhvoferjinzhiis
signalq1:std_logic_vector(3downto0);
begin
process(rst,clk)
begin
if(rst='0')then
q1<="0000";
elsif(clk'eventandclk='1')then
q1<=q1+1;
endif;
endprocess;
q<=q1;
endarchitecturebhv;
(2)管脚分配
(3)实验操作
①输入信号clk时钟→把FPGA_EA2_P6(Pin_P20)用导线与(FRQ_Q211Hz)连接、rst清零
→N18(SW-1)、输出信号q3→U12(LED1)、q2→V12(LED2);q1→V15(LED3);q0→W13(LED4)。
②把输入信号rst设为“1”、clk时钟(FRQ_Q211Hz)用导线与(FRQ_Q211Hz)连接。(4)实验现象
输出结果信息为第一、二、三、四个发光二极管按照0000→0001→……→1111循环显示,符合实验要求。(该实验板上低电平为“1”)
2、半加器
(1)实验原理图
(2)管脚分配
(3)实验操作
逻辑分析:输入信号a、b;输出信号分别为sum(和)、carry(进位)。
逻辑方程:sum=a⊕b;carry=a*b。
输入信号a→N18(SW-1)、b→M20(SW-2)、输出信号sum(和)→U12(LED1)、carry(进位)→V12(LED2)
(4)实验现象
ⅰ输入信号a、b都为“0”,输出结果信息为两个发光二极管均为“灭”,说明和和进位都为0;ⅱ输入信号a为“1”,b为“0”,输出结果信息为第一个发光二极管“灭”,第二个发光二极管“亮”,说明和为“1”,进位为0;ⅲ输入信号a为“0”,b为“1”,输出结果信息为第一个发光二极管“灭”,第二个发光二极管“亮”。说明和为“1”,进位为
“0”;ⅳ输入信号a、b都为“1”,输出结果信息为第一个发光二极管“亮”第二个发光二极管“灭”,说明和为“0”,进位为“1”.均符合设计要求
3、RS触发器
(1)实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityrs_clkis
port(s,r,res:instd_logic;
q,not_q:outstd_logic);
endrs_clk;
architecturebehavofrs_clkis
signalsel1,sel2:std_logic;
begin
process(res,sel1,sel2)
begin
ifres='0'thensel1<='0';
sel2<='1';
elsif(S='1'andR='0')thensel1<='1';
sel2<='0';
elsif(S='0'andR='1')thensel1<='0';
sel2<='1';
elsif(S='0'andR='0')thensel1<=sel1;
sel2<=sel2;
endif;
Q<=sel1;
not_q<=sel2;
endprocess;
endbehav;
(2)管脚分配
(3)实验操作
(3)实验现象
将实验现象总结为RS触发器特性表,其中X指0或1均可;输入为”1”指SW 输入为高,输入为”0”指SW输入为低;输出为”1”指对应LED灯灭(实验台
CLK触发输入S 输入R 原来的Q 新的输出Q*
(1)实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all; entitymotoris
port(
clk:instd_logic;
rst:instd_logic;
sel:outstd_logic;
q:outstd_logic_vector(3downto0);
d:outstd_logic_vector(7downto0)
);
endentity;
architectureb1ofmotoris
signalq1,q2:std_logic_vector(3downto0); begin
process(clk,rst)
begin
ifclk'eventandclk='1'then
q1<=q1+1;
q2<="0010";
endif;
endprocess;
q<=q2;
process(q1)
begin
if(rst='1')thensel<='0';
caseq1is
when
when"0001"=>d<="01100000";
when
when
when"0100"=>d<="01100110";
when
when
when
when
when
when
when"1011"=>d<="00111110";
when
when"1101"=>d<="01111010";
when
when
endcase;
endif;
endprocess;
end;
(2)管脚分配
(3)实验现象
将CLK接入较低频率,这样可以清晰地观察数码管从0—F(16进制数)的转变,完成一个循环之后,自动重新从0开始显示,进入下一个循环
5、跑马灯
(1)实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityledis
port(clk:instd_logic;
rst:instd_logic;
q:outstd_logic_vector(7downto0));
end;
architectureledofledis
constants0:std_logic_vector(1downto0):="00";
constants1:std_logic_vector(1downto0):="01";
constants2:std_logic_vector(1downto0):="10";
constants3:std_logic_vector(1downto0):="11";
signalpresent:std_logic_vector(1downto0);
signalq1:std_logic_vector(7downto0);
signalcount:std_logic_vector(3downto0);
begin
process(rst,clk)
begin
if(rst='0')then
present<=s0;
q1<=(others=>'0');
elsif(clk'eventandclk='1')then casepresentis
whens0=>if(q1="00000000")then
elseif(count="0111")then
count<=(others=>'0');
q1<="00000001";
present<=s1;
elseq1<=q1(0)&q1(7downto1);
count<=count+1;
present<=s0;
endif;
endif;
whens1=>if(count="0111")then
count<=(others=>'0');
present<=s2;
elseq1<=q1(6downto0)&q1(7);
count<=count+1;
present<=s1;
endif;
whens2=>if(count="0011")then
count<=(others=>'0');
q1<="00011000";
present<=s3;
elseq1(7downto4)<=q1(4)&q1(7downto5); q1(3downto0)<=q1(2downto0)&q1(3); count<=count+1;
present<=s2;
endif;
whens3=>if(count="0011")then
count<=(others=>'0');
present<=s0;
elseq1(7downto4)<=q1(6downto4)&q1(7); q1(3downto0)<=q1(0)&q1(3downto1); count<=count+1;
present<=s3;
endif;
endcase;
endif;
endprocess;
q<=q1;
end;
(2)管脚分配
(3)实验现象
实验开始,除了最左边的LED灯,其余实验箱上一排LED显示器全都点亮;然后随着接入CLK触发信号的频率,每一个触发脉冲,灭的灯往右移动一位(原来灭的灯的右边一位灯灭),而原来灭的灯重新点亮;当最右边一个灯灭了之后,下一个触发脉冲会重置循环,即又开始最左边的灯灭,其余的灯亮。
这样从视觉上就是一个黑点从左侧往右侧不断平移,一次移动一位,到达右侧终端后,黑点再次回到左侧,进入下一个周期。
6、键盘电路
(1)实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitykeyboardis
port(clk:instd_logic;
start:instd_logic;
KBCol:instd_logic_vector(3downto0);
KBRow:outstd_logic_vector(3downto0);
seg7:outstd_logic_vector(6downto0);
scan:outstd_logic_vector(7downto0));
endkeyboard;
architecturebevofkeyboardis
signalcount:std_logic_vector(1downto0);
signalsta:std_logic_vector(1downto0);
begin
scan<="00000001";
a:
process(clk)
begin
if(clk'eventandclk='1')then
count<=count+1;
endif;
endprocessa;
b:
process(clk)
begin
if(clk'eventandclk='1')then casecount(1downto0)is when"00"=>KBRow<="0111"; sta<="00";
when"01"=>KBRow<="1011"; sta<="01";
when"10"=>KBRow<="1101"; sta<="10";
when"11"=>KBRow<="1110"; sta<="11";
whenothers=>KBRow<="1111"; endcase;
endif;
endprocessb;
process(clk,start)
begin
ifstart='0'then
seg7<="0000000";
elseif(clk'eventandclk='1')then casestais
when"00"=>
caseKBColis when"1110"=>seg7<="1001110"; When"1101"=>seg7<="0111101"; When"1011"=>seg7<="1001111"; When"0111"=>seg7<="1000111"; Whenothers=>seg7<="0000000"; endcase;
when"01"=>
caseKBColis when"1110"=>seg7<="1111111"; when"1101"=>seg7<="1110011"; when"1011"=>seg7<="1110111"; when"0111"=>seg7<="0011111"; Whenothers=>seg7<="0000000"; endcase;
when"10"=>
caseKBColis
when"1110"=>seg7<="0110011";
when"1101"=>seg7<="1011011";
when"1011"=>seg7<="1011111";
when"0111"=>seg7<="1110000";
whenothers=>seg7<="0000000";
endcase;
when"11"=>
caseKBColis
when"1110"=>seg7<="1111110";
when"1101"=>seg7<="0110000";
when"1011"=>seg7<="1101101";
when"0111"=>seg7<="1111001";
whenothers=>seg7<="0000000";
endcase;
whenothers=>seg7<="0000000";
endcase;
endif;
endif;
endprocessc;
endbev;
(2)管脚分配
(3)实验操作
将SW1拨到1,按下键盘上相应的按键,如按下5 (4)实验现象
LED显示按下键位对应的数字
7、LED点阵显示
(1)实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_Unsigned.all;
useieee.std_logic_ARITH.all;
ENTITYdianzhenis
port(clk:instd_logic;
en:instd_logic;
hang:outstd_logic_vector(15downto0);
count:outstd_logic_vector(3downto0));
Enddianzhen;
Architecturedianzhenofdianzhenis
signalosc:std_logic;
signalx:std_logic_vector(0downto0);
signaly:std_logic_vector(1downto0);
signalcount1:std_logic_vector(3downto0);
signalcount2:std_logic_vector(25downto0);
signaldata:std_logic_vector(15downto0);
signald0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15:std_logic_vector(15downto0); signala0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15:std_logic_vector(15downto0); signalc0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15:std_logic_vector(15downto0); signalb0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15:std_logic_vector(15downto0); Begin
hang<=data;
a0<="0000000000000000";
a1<="0000000000000000";
a13<="0000000000000000";
a14<="0000000000000000";
a15<="0000000000000000";
c0<="0000000000000000";
c1<="0000000000000000";
c15<="0000000000000000";
b0<="0000000000000000";
b14<="0000000000000000";
a15<="0000000000000000";
process(osc,en,clk,x,y,count2)
begin
osc<=notclk;
x<="1";
if(osc='1'andosc'event)then
count2<=count2+1;
if(count2=100000)then
y<=y+1;
count2<=(others=>'0');
IF(y="10")then
y<="00";
endif;
endif;
if(x="0")then
if(en='1')then
ifcount1<="0000"then
data<=d0;count1<="0001";
elsifcount1<="0001"then
data<=d1;count1<="0010";
elsifcount1<="0010"then
data<=d2;count1<="0011";
elsifcount1<="0011"then
data<=d3;count1<="0100";
elsifcount1<="0100"then
data<=d4;count1<="0101";
elsifcount1<="0101"then
data<=d5;count1<="0110"; elsifcount1<="0110"then data<=d6;count1<="0111"; elsifcount1<="0111"then data<=d7;count1<="1000"; elsifcount1<="1000"then data<=d8;count1<="1001"; elsifcount1<="1001"then data<=d9;count1<="1010"; elsifcount1<="1010"then data<=d10;count1<="1011"; elsifcount1<="1011"then data<=d11;count1<="1100"; elsifcount1<="1100"then data<=d12;count1<="1101"; elsifcount1<="1101"then data<=d13;count1<="1110"; elsifcount1<="1110"then data<=d14;count1<="1111"; elsifcount1<="1111"then data<=d15;count1<="0000"; endif;
endif;
elsif(x="1")then
if(en='1')then
if(y="01")then
ifcount1<="0000"then
data<=c0;count1<="0001"; elsifcount1<="0001"then data<=c1;count1<="0010"; elsifcount1<="0010"then data<=c2;count1<="0011"; elsifcount1<="0011"then data<=c3;count1<="0100"; elsifcount1<="0100"then data<=c4;count1<="0101"; elsifcount1<="0101"then data<=c5;count1<="0110"; elsifcount1<="0110"then data<=c6;count1<="0111"; elsifcount1<="0111"then data<=c7;count1<="1000"; elsifcount1<="1000"then data<=c8;count1<="1001";
data<=c9;count1<="1010"; elsifcount1<="1010"then data<=c10;count1<="1011"; elsifcount1<="1011"then data<=c11;count1<="1100"; elsifcount1<="1100"then data<=c12;count1<="1101"; elsifcount1<="1101"then data<=c13;count1<="1110"; elsifcount1<="1110"then data<=c14;count1<="1111"; elsifcount1<="1111"then data<=c15;count1<="0000"; endif;
elsif(y="00")then
ifcount1<="0000"then
data<=b0;count1<="0001"; elsifcount1<="0001"then data<=b1;count1<="0010"; elsifcount1<="0010"then data<=b2;count1<="0011"; elsifcount1<="0011"then data<=b3;count1<="0100"; elsifcount1<="0100"then data<=b4;count1<="0101"; elsifcount1<="0101"then data<=b5;count1<="0110"; elsifcount1<="0110"then data<=b6;count1<="0111"; elsifcount1<="0111"then data<=b7;count1<="1000"; elsifcount1<="1000"then data<=b8;count1<="1001"; elsifcount1<="1001"then data<=b9;count1<="1010"; elsifcount1<="1010"then data<=b10;count1<="1011"; elsifcount1<="1011"then data<=b11;count1<="1100"; elsifcount1<="1100"then data<=b12;count1<="1101"; elsifcount1<="1101"then data<=b13;count1<="1110";
data<=b14;count1<="1111"; elsifcount1<="1111"then data<=b15;count1<="0000"; endif;
elsif(y="10")then
ifcount1<="0000"then
data<=a0;count1<="0001"; elsifcount1<="0001"then data<=a1;count1<="0010"; elsifcount1<="0010"then data<=a2;count1<="0011"; elsifcount1<="0011"then data<=a3;count1<="0100"; elsifcount1<="0100"then data<=a4;count1<="0101"; elsifcount1<="0101"then data<=a5;count1<="0110"; elsifcount1<="0110"then data<=a6;count1<="0111"; elsifcount1<="0111"then data<=a7;count1<="1000"; elsifcount1<="1000"then data<=a8;count1<="1001"; elsifcount1<="1001"then data<=a9;count1<="1010"; elsifcount1<="1010"then data<=a10;count1<="1011"; elsifcount1<="1011"then data<=a11;count1<="1100"; elsifcount1<="1100"then data<=a12;count1<="1101"; elsifcount1<="1101"then data<=a13;count1<="1110"; elsifcount1<="1110"then data<=a14;count1<="1111"; elsifcount1<="1111"then data<=a15;count1<="0000"; endif;
endif;
endif;
endif;
endif;
endprocess;
count<=count1;
end;
(2)管脚分配
(3)实验操作
把FPGA_EA2_P6(Pin_P20)用导线与(FRQ_Q632768Hz)连接(4)实验现象
可看到点阵依次清晰显示“中国人”三个汉字
8、多人抢答器
(1)实验代码
抢答模块:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityxuanshouis
port(rst,clk2:instd_logic;
s0,s1,s2,s3:instd_logic;
states:bufferstd_logic_vector(3downto0);
light:bufferstd_logic_vector(3downto0);
warm:outstd_logic);
endxuanshou;
architectureoneofxuanshouis
signalst:std_logic_vector(3downto0);
begin
p1:process(s0,rst,s1,s2,s3,clk2)
begin
ifrst='0'then
warm<='0';st<="0000";
elsifclk2'eventandclk2='1'then
if(s0='1'orst(0)='1')andnot(st(1)='1'orst(2)='1'orst(3)='1')
thenst(0)<='1';
endif;
if(s1='1'orst(1)='1')andnot(st(0)='1'orst(2)='1'orst(3)='1')
thenst(1)<='1';
endif;
if(s2='1'orst(2)='1')andnot(st(0)='1'orst(1)='1'orst(3)='1')
thenst(2)<='1';
endif;
if(s3='1'orst(3)='1')andnot(st(0)='1'orst(1)='1'orst(2)='1') thenst(3)<='1';
endif;
warm<=st(0)orst(1)orst(2)orst(3);
endif;
endprocessp1;
p2:process(states(0),states(1),states(2),states(3),light) begin
if(st="0000")thenstates<="0000";
elsif(st<="0001")thenstates<="0001";
elsif(st<="0010")thenstates<="0010";
elsif(st<="0100")thenstates<="0011";
elsif(st<="1000")thenstates<="0100";
endif;
light<=st;
endprocessp2;
endone;
倒计时模块:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entityJSis
port(clk1,rst,start,stop:instd_logic;
ta,tb:bufferstd_logic_vector(3downto0));
endJS;
architectureoneofJSis
signalco:std_logic;
begin
p1:process(clk1,rst,start,stop,ta)
begin
ifrst='0'orstop='1'then
ta<="0000";
elsifclk1'eventandclk1='1'then
co<='0';
ifstart='1'then
ifta="0000"then
ta<="1001";co<='1';
elseta<=ta-1;
endif;
endif;
endif;
endprocessp1;
p2:process(co,rst,start,stop,tb)
begin
ifrst='0'orstop='1'then
tb<="0010";
elsifco'eventandco='1'then
ifstart='1'then
iftb="0000"thentb<="0011";
elsetb<=tb-1;
endif;
endif;
endif;
endprocessp2;
endone;
(2)管脚分配
(3)实验现象
开始之后,先按清零键,计数器开始倒计时。有四个开关,先按下的开关,其对应的二极管会亮且保持亮的状态。这时候其他开关无论是否按下,对应的二极管均不亮。
五、实验感想
FPGA(Field-ProgrammableGateArray),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
这两节课的FPGA实验,让我初步了解了FPGA的大致设计流程。从一开始的对FPGA一无所知,到不断查阅相关资料和实验指导书,一步步按照教程学VHDL语法、进行编程仿真、分配管脚、将程序下载到实验板观察现象,完成一个完整的FPGA程序设计和调试流程。在一开始,自然不会一帆风顺。特别是程序调试和引脚分配环节会出现各种各样的问题。比如在写程序时,由于VHDL 语言的严谨性,整个程序运行报错很可能就是因为少了一个括号、多了一个分号这种看似不起眼的小错误,但就是这种小错误会使整个程序无法编译通过,影响到后续的仿真和烧录。因此对于编程这个环节一定要做到缜密细心。而对于管脚分配也是如此,密密麻麻的管脚对应图容不得有丝毫马虎,一个开关位置分配的错误,会直接导致程序结果不正确。不过,当解决一个又一个问题后,看到实验板上的数码管或者LED灯依次亮起的时候,心里还是很有成就感的。
我相信这两节课只是FPGA学习的一个开始。在日后的学习和工作中,我相信一定会时常用到FPGA的,所以应该在假期或者课余时间深入学习,将FPGA 的强大之处发挥出来!