
千万不要 照抄
否则后果很严重
多写点自己在实验时遇到的问题
前四个实验报告详细
后四个报告可以适当简略
《EDA技术及应用》
实验报告
系 部: 电子通信工程系
**** ***
学 号: ___________
姓 名: _______
同 组 人: ______________
二О____年____月___日
实验一 点亮LED设计
一、实验目的
通过此试验可以让大家逐步了解,熟悉和掌握FPGA开发软件Quartus II的使用方法及VerilogHDL的编程方法。
二、实验内容
本实验是一个简单的点亮LED灯的实验,具体包括:
1)使用Quartus II建立一个工程;
2)Quartus II工程设计;
3)设置编译选项并编译硬件系统;
4)下载硬件设计到目标FPGA;
5)观察LED的状态;
三、实验原理
和单片机一样,向片子里写进数据,输出高电平(对于共阴极的),
或者输出低电平(对于共阳极)。根据Cyclone片子已经分配好的针脚设置好针脚。
四、实验步骤
建立-----个工程-----输入程序-----软件编译
------生成下载文件-----下载—调试。
五、实验程序
module led1(led); //模块名led1
output[7:0] led; //定义输出端口
reg[7:0] led; //定义寄存器
always //过程1
begin
led = 8'b10101010; //输出0xAA
end
endmodule
六、思考题
(1)写出使用QuartusII软件开发工程的完整的流程。
建立一个工程—输入程序—软件编译综合—生成下载文件—
下载—硬件调。
实验二流水灯实验
一、实验目的
通过此试验让大家进一步了解熟悉和掌握FPGA开发软件的使用方法及软件编程方法。学习简单的时序电路的设计和硬件测试。
二、实验内容
本实验的内容是建立用于控制LED流水灯的简单硬件电路,要求在SmartSOPC上实现LED1-LED8发光二极管流水灯的显示。
三、实验原理
这里的显示用分频模块(int_div)得到的较低的始终作为信号,在此时钟下,对输入数据进行移位,就得到了流水灯的效果。
四、实验步骤
建立工程—输入源程序—调用模块—生成符号—调用符号—连成电路图—编译—下载—调试
五、实验程序
原理图
六、思考题
1.本实验顶层采用了图形输入的方式,若采用文本输入方式,如何编写顶层文件?写出相应程序。
module led2(clock,led);
input clock;
output [7:0]led;
wire p;
int_div u1( .clock(clock),.clk_out(p));
ledwater u2(.clk(p),.led(led));
endmodule
实验三 键盘、LED发光实验
一、实验目的
本实验的主要目的是联系顶层模块的设计。学习和体会分支条件语句case的使用及FPGA的I/O控制。
二、实验内容
用跳线把key1-key8和指定的引脚连起来,以实现功能控制。
三、实验原理
FPGA的所有的I/O控制块允许每个引脚单独的配置为输入口。只要配置正确,则一暗淡几个键中有键输入,在检测到键盘输入的情况下,继续判断其键盘值并作出相应的处理。
四、实验步骤
1:按以前的步骤建立工程,并按说明书进行配置引脚,未用的按三态处理。2:对文件进行编译,并检错。3:按说明短接跳帽和连接跳线。4:观察输入情况。
五、实验程序
module keyled(key,led); //模块名keyled
input[7:0] key; //定义键盘输入口
output[7:0] led; //定义发光管输出口
reg[7:0] led_r; //定义寄存器
reg[7:0] buffer_r;
assign led = led_r; //输出键值
always@(key) //过程1
begin
buffer_r = key; //读取键值
case(buffer_r)
8'b11111110:led_r = 8'b11111110; //是键KEY1,则给寄存器赋值0xfe
8'b11111101:led_r = 8'b11111100; //是键KEY2,则给寄存器赋值0xfc
8'b11111011:led_r = 8'b11111000; //是键KEY3,则给寄存器赋值0xf8
8'b11110111:led_r = 8'b11110000; //是键KEY4,则给寄存器赋值0xf0
8'b11101111:led_r = 8'b11100000; //是键KEY5,则给寄存器赋值0xe0
8'b11011111:led_r = 8'b11000000; //是键KEY6,则给寄存器赋值0xc0
8'b10111111:led_r = 8'b10000000; //是键KEY7,则给寄存器赋值0x80
8'b01111111:led_r = 8'b00000000; //是键KEY8,则给寄存器赋值0x00
default: led_r = 8'b11111111; //否则给寄存器赋值0xff
endcase
end
endmodule
六、思考题
1.能否用if语句改写本实验程序?如果能,写出相应程序。
module keyled(key,led); //模块名keyled
input[7:0] key; //定义键盘输入口
output[7:0] led; //定义发光管输出口
reg[7:0] led_r; //定义寄存器
reg[7:0] buffer_r;
assign led = led_r; //输出键值
always@(key) //过程1
begin
buffer_r = key; //读取键值
if (buffer_r==8'b11111110) led_r = 8'b11111110;
else if (buffer_r==8'b11111101) led_r = 8'b11111100;
else if (buffer_r==8'b11111011) led_r = 8'b11111000;
else if (buffer_r==8'b11110111) led_r =8'b11110000;
else if (buffer_r==8'b11101111) led_r = 8'b11100000;
else if (buffer_r==8'b10111111) led_r = 8'b10000000;
else (buffer_r==8'b01111111) led_r = 8'b00000000;
end
endmodule
实验四 静态数码管显示实验
一、实验目的
学习LPM兆模块的调用。
二、实验内容
建立7段译码显示模块,用于控制LED数码管的静态显示。要求在实验箱上的数码管依显示0—9和A-F16个字符。
三、实验原理
本实验通过分频模块int_div 分频得到1HZ的频率信号,加载4位计数器的时钟输入端,计数循环输出0-9,A-F 16个数,最后通过七段译码后在数码显示出来。
四、实验步骤
1:立源程序文件dec17s.v,输入程序代码并保存,并对此生成符号。2:添加LPM模块并按需要生成相应的文件。
五、实验程序
六、思考题
1.本实验采用的是共阳极数码管,若采用共阴极数码管,有什么不同?
答:对应显示相同的数时,输入的不同。
2.如何显示HHHHHHHH和PPPPPPPP?
答:H 对应的h, P 对应的时73h;
实验五 动态数码管显示实验
一、实验目的
学习动态扫描显示的原理图及电路的设计。
二、实验内容
1:在SmartSOPC试验箱上完成LED数码管的动态显示“1-8”个数字。
2:放慢扫描速度演示动态显示的原理过程。
三、实验原理
虽然每次只有一个LED显示,但只要扫描显示速率够快,由于人的视觉余辉效应,使我们仍会感觉所有的数码管都在同时显示。
四、实验步骤
1:建立一个空白工程,并命名。
2:对该工程文件进行全程编译处理,若在编译过程中发现错误,则找出并更改,直至编译成功为止。
3:从设计文件创建模块。
4:将光盘中EDA目录文件拷贝到工程目录。
5:添加常量兆功能模块。
五、实验程序
module scan_led(clk_1k,d,dig,seg); //模块名scan_led
input clk_1k; //输入时钟
input[31:0] d; //输入要显示的数据
output[7:0] dig; //数码管选择输出引脚
output[7:0] seg; //数码管段输出引脚
reg[7:0] seg_r; //定义数码管输出寄存器
reg[7:0] dig_r; //定义数码管选择输出寄存器
reg[3:0] disp_dat; //定义显示数据寄存器
reg[2:0]count; //定义计数寄存器
assign dig = dig_r; //输出数码管选择
assign seg = seg_r; //输出数码管译码结果
always @(posedge clk_1k) //定义上升沿触发进程
begin
count <= count + 1'b1;
end
always @(posedge clk_1k)
begin
case(count) //选择扫描显示数据
3'd0:disp_dat = d[31:28]; //第一个数码管
3'd1:disp_dat = d[27:24]; //第二个数码管
3'd2:disp_dat = d[23:20]; //第三个数码管
3'd3:disp_dat = d[19:16]; //第四个数码管
3'd4:disp_dat = d[15:12]; //第五个数码管
3'd5:disp_dat = d[11:8]; //第六个数码管
3'd6:disp_dat = d[7:4]; //第七个数码管
3'd7:disp_dat = d[3:0]; //第八个数码管
endcase
case(count) //选择数码管显示位
3'd0:dig_r = 8'b01111111; //选择第一个数码管显示
3'd1:dig_r = 8'b10111111; //选择第二个数码管显示
3'd2:dig_r = 8'b11011111; //选择第三个数码管显示
3'd3:dig_r = 8'b11101111; //选择第四个数码管显示
3'd4:dig_r = 8'b11110111; //选择第五个数码管显示
3'd5:dig_r = 8'b11111011; //选择第六个数码管显示
3'd6:dig_r = 8'b11111101; //选择第七个数码管显示
3'd7:dig_r = 8'b11111110; //选择第八个数码管显示
endcase
end
always @(disp_dat)
begin
case(disp_dat) //七段译码
4'h0:seg_r = 8'hc0; //显示0
4'h1:seg_r = 8'hf9; //显示1
4'h2:seg_r = 8'ha4; //显示2
4'h3:seg_r = 8'hb0; //显示3
4'h4:seg_r = 8'h99; //显示4
4'h5:seg_r = 8'h92; //显示5
4'h6:seg_r = 8'h82; //显示6
4'h7:seg_r = 8'hf8; //显示7
4'h8:seg_r = 8'h80; //显示8
4'h9:seg_r = 8'h90; //显示9
4'ha:seg_r = 8'h88; //显示a
4'hb:seg_r = 8'h83; //显示b
4'hc:seg_r = 8'hc6; //显示c
4'hd:seg_r = 8'ha1; //显示d
4'he:seg_r = 8'h86; //显示e
4'hf:seg_r = 8'h8e; //显示f
endcase
end
endmodule
六、思考题
1.说出数码管动态显示的原理。
数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形。
实验六 按键去抖动实验
一、实验目的
学习按键去抖动电路的硬件设计。
二、实验内容
本实验的内容是建立按键消抖模块,对比有加消抖模块和没加消抖模块电路的区别。
三、实验原理
作为机械开关的键盘,在按键操作时,机械触点的弹性及电压突跳等原因,在触点或开启的瞬间会出现电压抖动。
四、实验步骤
1:启动QuartusII建立一个空白工程并命名。
2:将电路用Verilog VHDL语言描述出来,并扩展多个通道。
3:从设计文件创建模块,由debounce.v生成命名为debounce.vbsf。
4:其他步参考顶层模块原理图。
五、实验程序
module debounce(clk,key_in,key_out); //按键消抖模块
input clk; //系统时钟输入
input[KEY_WIDTH-1:0] key_in; //外部按键输入
output[KEY_WIDTH-1:0]key_out; //按键消抖输出
reg[KEY_WIDTH-1:0]dout1,dout2,dout3; //寄存器
parameter KEY_WIDTH = 8; //参数
assign key_out = (dout1 | dout2 | dout3); //按键消抖输出
always @(posedge clk)
begin
dout1 <= key_in;
dout2 <= dout1;
dout3 <= dout2;
end
endmodule
六、思考题
1.比较下面两段程序的异同,并画出电路结构图.
always@ ( posedge clk)
begin
dout1<=key_in; //非阻塞赋值
dout2<=dout1;
dout3<=dout2;
end
always@ ( posedge clk)
begin
dout1<=key_in; //阻塞赋值
dout2<=dout1;
dout3<=dout2;
End
电路图如下:
实验七 硬件电子琴实验
一、实验目的
学习利用蜂鸣器和按键设计硬件电子琴。
二、实验内容
在SmartSOPC实验箱上的实现一个简单的电子琴。
三、实验原理
由于组成乐曲的每个音符的频率值及其持续时间是乐曲演奏的2个基本数据,因此需要控制输出到扬声器的激励信号的频率高低和该频率信号持续的时间。
四、实验步骤
1:在QuartusII中建立一个工程项目文件,输入程序代码并保存。
2:选择目标器件并对相应的引脚进行锁定。
3:对该工程文件进行全程编译处理,若在编译过程中发现错误,则找出并更改,直至编译成功为止。
4:打开电源,执行下载命令。
五、实验程序
module beep1(clk,key,beep,led); 模块名称beep
input clk; 系统时钟48MHz
input[7:0]key; 按键输入
output beep; 蜂鸣器输出端
output[7:0]led; 输出
reg beep_r; 寄存器
reg[15:0]count,count_end;
reg[7:0]key_r;
always@(posedge clk)
begin
计数器加1
计数器清零
取反输出信号
end
always @(key)
begin
取键值
中音1的分频系数值
中音2的分频系数值
中音3的分频系数值
中音4的分频系数值
中音5的分频系数值
中音6的分频系数值
中音7的分频系数值
高音1的分频系数值
高音2的分频系数值
高音3的分频系数值
高音4的分频系数值
高音5的分频系数值
高音6的分频系数值
高音7的分频系数值
end
assign beep =beep_r; 输出音乐
assign led =key_r; 输出按键状态
endmodule
六、思考题
1. 举例说明产生不同音符的原理。
由于组成乐曲的每个音符的频率值及其持续时间是乐曲演奏的2个基本数据,因此需要控制输出到扬声器的激励信号的频率高低和该频率信号持续的时间。频率的高低决定了音调的高低,而乐曲的简谱与各音名的频率关系是对应的,只要求出对应的分频分数,这样利用程序可以很轻松的得到相应的乐声。
实验八 数字时钟设计
一、实验目的
学习数字时钟的硬件设计。
二、实验内容
在SmartSOPC试验箱上完成一个可以计时的数字时钟,其显示时间范围是00:00:00-23:59:59
三、实验原理
一个完整的时钟应由3部分组成,秒脉冲发生电路,计数显示部分和时钟调整部分。本实验的校时电路在此仅仅完成了暂停,清零的基本功能。
四、实验步骤
1:在QuartusII中建立一个工程项目文件。
2:选择目标器件并对相应的引脚进行锁定。
3:对该工程文件进行全程编译处理。
4:硬件连接,下载程序。
五、实验程序
module clock(clk,key,dig,seg); //模块名clock
input clk; //输入时钟
input[1:0] key; //输入按键
output[7:0] dig; //数码管选择输出引脚
output[7:0] seg; //数码管段输出引脚
reg[7:0] seg_r; //定义数码管输出寄存器
reg[7:0] dig_r; //定义数码管选择输出寄存器
reg[3:0] disp_dat; //定义显示数据寄存器
reg[24:0]count; //定义计数寄存器
reg[23:0]hour; //定义现在时刻寄存器
reg sec,keyen; //定义标志位
reg[1:0]dout1,dout2,dout3; //寄存器
wire[1:0]key_done; //按键消抖输出
assign dig = dig_r; //输出数码管选择
assign seg = seg_r; //输出数码管译码结果
//秒信号产生部分
always @(posedge clk) //定义clock上升沿触发
begin
count = count + 1'b1;
if(count == 25'd24000000) //0.5S到了吗?
begin
count = 25'd0; //计数器清零
sec = ~sec; //置位秒标志
end
end
//按键消抖处理部分
assign key_done = (dout1 | dout2 | dout3); //按键消抖输出
always @(posedge count[17])
begin
dout1 <= key;
dout2 <= dout1;
dout3 <= dout2;
end
always @(negedge key_done[0])
begin
keyen = ~keyen; //将琴键开关转换为乒乓开关
end
//数码管动态扫描显示部分
always @(posedge clk) //count[17:15]大约1ms改变一次
begin
case(count[17:15]) //选择扫描显示数据
3'd0:disp_dat = hour[3:0]; //秒个位
3'd1:disp_dat = hour[7:4]; //秒十位
3'd2:disp_dat = 4'ha; //显示"-"
3'd3:disp_dat = hour[11:8]; //分个位
3'd4:disp_dat = hour[15:12]; //分十位
3'd5:disp_dat = 4'ha; //显示"-"
3'd6:disp_dat = hour[19:16]; //时个位
3'd7:disp_dat = hour[23:20]; //时十位
endcase
case(count[17:15]) //选择数码管显示位
3'd0:dig_r = 8'b11111110; //选择第一个数码管显示
3'd1:dig_r = 8'b11111101; //选择第二个数码管显示
3'd2:dig_r = 8'b11111011; //选择第三个数码管显示
3'd3:dig_r = 8'b11110111; //选择第四个数码管显示
3'd4:dig_r = 8'b11101111; //选择第五个数码管显示
3'd5:dig_r = 8'b11011111; //选择第六个数码管显示
3'd6:dig_r = 8'b10111111; //选择第七个数码管显示
3'd7:dig_r = 8'b01111111; endcase
end
always @(posedge clk)
begin
case(disp_dat)
4'h0:seg_r = 8'hc0;
4'h1:seg_r = 8'hf9;
4'h2:seg_r = 8'ha4;
4'h3:seg_r = 8'hb0;
4'h4:seg_r = 8'h99;
4'h5:seg_r = 8'h92;
4'h6:seg_r = 8'h82;
4'h8:seg_r = 8'h80;
4'h9:seg_r = 8'h90; /
4'ha:seg_r = 8'hbf;
default:seg_r = 8'hff;
endcase
if((count[17:15]== 3'd2)&sec)
seg_r = 8'hff;
end
always @(negedge sec or negedge key_done[1])//
begin
if(!key_done[1])
begin
hour = 24'h0;
end
else if(!keyen)
begin
hour[3:0] = hour[3:0] + 1'b1;
if(hour[3:0] == 4'ha)
begin
hour[3:0] = 4'h0;
hour[7:4] = hour[7:4] + 1'b1;
if(hour[7:4] == 4'h6)
begin
hour[7:4] = 4'h0;
hour[11:8] = hour[11:8] + 1'b1;
if(hour[11:8] == 4'ha)
begin
hour[11:8] = 4'h0;
hour[15:12] = hour[15:12] + 1'b1;
if(hour[15:12] == 4'h6)
begin
hour[15:12] = 4'h0;
hour[19:16] = hour[19:16] + 1'b1;
if(hour[19:16] == 4'ha)
begin
hour[19:16] = 4'h0;
hour[23:20] = hour[23:20] + 1'b1;
end
if(hour[23:16] == 8'h24)
hour[23:16] = 8'h0;
end
end
end
end
end
end
endmodule
六、思考题
1. 自己动手添加校时程序,写出相应程序。
module clock(clk,key,dig,seg); //模块名clock
input clk; //输入时钟
input[1:0] key; //输入按键
output[7:0] dig; //数码管选择输出引脚
output[7:0] seg; //数码管段输出引脚
reg[7:0] seg_r; //定义数码管输出寄存器
reg[7:0] dig_r; //定义数码管选择输出寄存器
reg[3:0] disp_dat; //定义显示数据寄存器
reg[24:0]count; //定义计数寄存器
reg[23:0]hour; //定义现在时刻寄存器
reg sec,keyen; //定义标志位
reg[1:0]dout1,dout2,dout3; //寄存器
wire[1:0]key_done; //按键消抖输出
assign dig = dig_r; //输出数码管选择
assign seg = seg_r; //输出数码管译码结果
//秒信号产生部分
always @(posedge clk) //定义clock上升沿触发
begin
count = count + 1'b1;
if(count == 25'd24000000) //0.5S到了吗?
begin
count = 25'd0; //计数器清零
sec = ~sec; //置位秒标志
end
end
//按键消抖处理部分
assign key_done = (dout1 | dout2 | dout3); //按键消抖输出
always @(posedge count[17])
begin
dout1 <= key;
dout2 <= dout1;
dout3 <= dout2;
end
always @(negedge key_done[0])
begin
keyen = ~keyen; //将琴键开关转换为乒乓开关
end
//数码管动态扫描显示部分
always @(posedge clk) //count[17:15]大约1ms改变一次
begin
case(count[17:15]) //选择扫描显示数据
3'd0:disp_dat = hour[3:0]; //秒个位
3'd1:disp_dat = hour[7:4]; //秒十位
3'd2:disp_dat = 4'ha; //显示"-"
3'd3:disp_dat = hour[11:8]; //分个位
3'd4:disp_dat = hour[15:12]; //分十位
3'd5:disp_dat = 4'ha; //显示"-"
3'd6:disp_dat = hour[19:16]; //时个位
3'd7:disp_dat = hour[23:20]; //时十位
endcase
case(count[17:15])
3'd0:dig_r = 8'b11111110;
3'd1:dig_r = 8'b11111101;
3'd2:dig_r = 8'b11111011;
3'd3:dig_r = 8'b11110111;
3'd4:dig_r = 8'b11101111;
3'd5:dig_r = 8'b11011111;
3'd6:dig_r = 8'b10111111; /
3'd7:dig_r = 8'b01111111;
endcase
end
always @(posedge clk)
begin
case(disp_dat)
4'h0:seg_r = 8'hc0;
4'h1:seg_r = 8'hf9;
4'h2:seg_r = 8'ha4;
4'h3:seg_r = 8'hb0;
4'h4:seg_r = 8'h99;
4'h5:seg_r = 8'h92;
4'h6:seg_r = 8'h82;
4'h8:seg_r = 8'h80;
4'h9:seg_r = 8'h90; /
4'ha:seg_r = 8'hbf;
default:seg_r = 8'hff;
endcase
if((count[17:15]== 3'd2)&sec)
seg_r = 8'hff;
end
always @(negedge sec or negedge key_done[1])//
begin
if(!key_done[1])
begin
hour = 24'h0;
end
else if(!keyen)
begin
hour[3:0] = hour[3:0] + 1'b1;
if(hour[3:0] == 4'ha)
begin
hour[3:0] = 4'h0;
hour[7:4] = hour[7:4] + 1'b1;
if(hour[7:4] == 4'h6)
begin
hour[7:4] = 4'h0;
hour[11:8] = hour[11:8] + 1'b1;
if(hour[11:8] == 4'ha)
begin
hour[11:8] = 4'h0;
hour[15:12] = hour[15:12] + 1'b1;
if(hour[15:
end
if(hour[23:16] == 8'h24)
hour[23:16] = 8'h0;
end
end
end
end
endmodule
