声明:代码部分使用了AI工具
实验六 综合考核
Quartus 18.0
FPGA 5CSXFC6D6F31C6N
1. 实验项目
要求利用硬件描述语言Verilog(或VHDL)、图形描述方式、IP核,结合数字系统设计方法,在Quartus开发环境下,2人1组本班内自由组队,从下列3个实验项目中任选1项(3选1)进行实现。因材料限制,每个项目每个班级最多6组选择,第一次实验时填表选定,不得变更。
实验分为2部分内容,基础实验12学时,使用FPGA开发板实现。拓展实验需要搭建外围电路与开发板连接实现相关功能,可利用课余时间进行开放实验,第二次实验时进行集中实验验收(4学时)。
注意事项:需自带计算机(安装有Quartus、multisim等软件);还需带烙铁、焊锡焊接工具和万用表等,实验室提供相关元器件。
实验项目名称 | 基础实验内容(12学时) | 拓展实验内容 (开放实验+4学时验收实验) |
项目1:简易频率计的设计与实现 | 利用硬件描述语言或图形描述方式,结合数字电路设计方法,实现以下功能: 1.对1kHz-1MHz方波信号的频率测量功能,进行quartus/modelsim仿真验证;(60分) 2.使用实验室提供开发板完成对1kHz-1MHz方波信号的频率测量功能,控制数码管实时显示测量结果。(20分) 3.可通过开发板上的USB-Uart接口,将测量频率结果传送至计算机上的串口调试助手显示。(20分) | 在基础实验内容的基础上,使用元器件搭建外围电路,经multisim/proteus仿真验证后,制作实物电路与开发板连接,实现以下功能: 1.可对幅度0.1V-4V,频率1kHz-10kHz范围的正弦信号进行频率测量;(60分) 2.对输入正弦信号同时进行幅度和频率测量,并将测量结果实时显示并发送至计算机。(40分) |
项目2:简易信号发生器的设计与实现 | 利用硬件描述语言或图形描述方式,结合数字电路设计方法,实现以下功能: 1.产生1kHz-1MHz范围内的方波信号,信号频率可由按键调节,步进间隔1kHz,进行quartus/modelsim仿真验证;(60分) 2.使用实验室提供开发板输出1kHz-1MHz方波信号,信号频率可由按键调节,控制数码管实时显示当前频率值。(20分) 3.实现用计算机调节开发板输出方波信号频率的功能。(20分) | 在基础实验内容的基础上,使用元器件搭建外围电路,经multisim/proteus仿真验证后,制作实物电路与开发板连接,实现以下功能: 1.产生1kHz-10kHz范围内的三角波信号,频率可由按键和计算机进行调节;(60分) 2.产生7kHz-10kHz范围内的正弦波信号,频率可由按键和计算机进行调节。(40分) |
项目3:电压电流表的设计与实现 | 利用硬件描述语言或图形描述方式,结合数字电路设计方法,实现以下功能: 1.使用实验室提供开发板对介于0-4V之间的直流电压值进行测量,分辨率1mV,测量结果在数码管上显示,每秒至少刷新1次;(60分) 2.对两路0-4V之间的直流电压值同时进行测量,测量结果交替显示。(20分) 3.可通过开发板上的USB-Uart接口,将测量电压结果传送至计算机上的串口调试助手显示。(20分) | 在基础实验内容的基础上,使用元器件搭建外围电路,经multisim/proteus仿真验证后,制作实物电路与开发板连接,实现以下功能: 1.对直流电源输出到负载上的电压和电流进行测量,并将测量结果实时显示并发送至计算机;(60分) 2.使用电压电流测量结果计算负载实时功率和耗电量,将计算结果发送至计算机。(40分) |
2. 实验要求
(1)每人对于所选择完成的实验项目,通过查阅资料理解实验原理,设计实验方案,并将实验原理和方案写于实验报告中。
(2)按照实验要求,完成电路设计、通过编译无误后,完成测试代码编写,实现功能仿真,记录仿真波形并写于实验报告。
(3)编译的输出文件下载到FPGA电路板,完成指定功能,进行拍照和结果分析,写入实验报告。
(4)基础实验内容完成后由老师验收并记录实验成绩。
(5)设计外围电路完成相关功能,使用Multisim、Proteus对外围电路功能进行验证,截图写入实验报告。
(6)利用开放实验时间搭建外围电路实物,进行测试验证,对测试结果进行拍照和分析,写入实验报告。
(7)集中验收实验时经老师检查电路无误后,将搭建电路与FPGA开发板连接,进行测试。测试完成后由老师验收并记录实验成绩,认真撰写实验报告,按时上交实验报告。
(8)实验六实验报告使用智慧树平台网上填写提交,每组仅需提交1份,按自己选择题目提交相应作业,截止时间为第二次实验当晚23:59前。建议边做实验边拍照记录,减少实验报告撰写时间。
3. 实验器材清单
(1)FPGA开发板,有DE1SOC和DE10-Standard这2种,随机领用,看准自己开发板型号,查找相关资料。
(2)直流电源、信号源、示波器、万用表(需自备)。
(3)直插1/4W电阻
阻值:10Ω, 22Ω, 47Ω, 100Ω , 150Ω , 200Ω , 220Ω , 270Ω , 330Ω, 470Ω, 510Ω, 680Ω, 1kΩ, 2kΩ, 2.2kΩ, 3.3kΩ, 4.7kΩ, 5.1kΩ, 6.8kΩ, 10kΩ, 20kΩ, 47kΩ, 51kΩ, 68kΩ, 100kΩ, 220kΩ, 300kΩ, 470kΩ, 680kΩ, 1MΩ
(4)瓷片电容
容值:2pF, 3pF, 5pF, 10pF, 15pF, 22pF, 30pF, 47pF, 68pF, 75pF, 82pF, 100pF, 150pF, 220pF, 330pF, 470pF, 680pF, 1npF, 1.5nF, 2.2nF, 3.3nF, 4.7nF, 6.8nF, 10nF, 15nF, 22nF, 47nF, 68nF, 100nF
3. 实验器材清单
(5)电解电容(焊接务必注意正负极)
50V0.22uF, 50V0.47uF, 50V1uF, 50V2.2uF, 50V4.7uF, 25V10uF, 25V22uF, 16V33uF, 16V47uF, 16V100uF, 10V220uF, 10V470uF
(6)二极管
1N4148, 1N4007, 1N5819, 1N5399, FR107, FR207, 1N5408, 1N5822
(7)运算放大器LM324及芯片座
(8)比较器LM393及芯片座
(9)USB转TTL转换器(计算机和开发板通信用,用后需归还)
驱动及安装说明: https://zhuanlan.zhihu.com/p/370245114
(10)万用板5*7cm单面(每组一块), 杜邦线。
声明:我们选择的是项目二;隔得时间太久,有的照片找不着了;分频器部分,由于采用了除法,受限于有限字长,得到的实际频率有一定误差,虽然人为进行了修正,但在高频时仍比较明显,可以考虑其他算法改进;正弦波部分的带通滤波器没有问题;但三角波部分的积分器需要改进,现在的问题是频率较高时幅值衰减较明显。
考核内容
1.1.【问答题】(10分)
产生1kHz-1MHz范围内的方波信号,信号频率可由按键调节,步进间隔1kHz,进行
quartus,/modelsim仿真验证;简述该设计的主要功能和原理?
主要功能:
可以通过按钮调节输出1kHz-1MHz的方波、7kHz-10kHz正弦波、1kHz-10kHz三角波(步进均为1kHz);可以通过串口从电脑上控制输出1kHz-1MHz的方波、7kHz-10kHz正弦波、1kHz-10kHz三角波(步进均为1kHz)。
不过,串口控制功能只能输入十六进制数,所以在测试时需要先把想输入的十进制数转换为十六进制,允许输入范围为0x0001~0x03E8(注意,1MHz即为1000kHz,我们这里使用三位数码管,故显示为000)。比如,我想通过串口控制输出726kHz方波,只需在电脑串口助手上输入02D6再发送即可。
原理:时钟脉冲信号经过可调分频器后得到可控频率的矩形脉冲信号,矩形脉冲信号分别经过滤波器和积分器后可得到正弦波和三角波。编写一个调节模块用以传递输入的指令,并联系输入部分和输出部分。
1.2.【问答题】(5分)
上传设计框图、源程序等截图:
1.3.【问答题】(5分)
上传仿真结果截图,描述图中结果:
引脚分配:
quartus/modelsim联合仿真:
1.4.【问答题】(5分)
使用实验室提供开发板输出1kHz-1MHz方波信号,信号频率可由按键调节,控制数码管实时显示
当前频率值。上传输出最低频率方波的照片,照片中需包含设置频率和示波器测量波形。
实验六项目二按钮演示
实验六项目二串口演示
1.5.【问答题】(5分)
上传输出最高频率方波的照片,照片中需包含设置频率和示波器测量波形。
找不着照片了
1.6.【问答题】(5分)
你最终实现了多少范围内的频率输出功能?误差是多少?
范围达到了题目要求,这里误差不是我算的,不知道。
1.7.【问答题】(10分)
在基础实验内容的基础上,使用元器件搭建外围电路,简述外围电路原理?
带通滤波器设计:
1.8.【问答题】(10分)
上传外围电路图及仿真测试结果,并说明仿真情况
带通滤波器:
积分器:
1.9.【问答题】(10分)
制作实物电路与开发板连接,实现以下功能:
产生1kHz-10kHz范围内的三角波信号,频率可由按键和计算机进行调节;上传最低频率和最高频
率时输出三角波的测量结果照片。
1.10.【问答题】(10分)
产生7kHz-10kHz范围内的正弦波信号,频率可由按键和计算机进行调节。上传最低频率和最高频
率时输出正弦波的测量结果照片。
2.【问答题】(10分)
上传搭建的外围电路与开发板连接的实物照片。
3.【问答题】(10分)
你在实验调试过程中出现了哪些问题?如何解决的?有何实验心得体会?
(1)有时会出现不明原因的报错,报错中会出现“License”相关字眼,这是在程序运行途中发生了破解失效,需要妥善保存工程后再一次进行破解。
(2)在仿真过程中,程序选择的文件保存路径经常会出现问题,“.vwf”文件与“.vt"文件可能会被写入不同路径,这会导致报错并且仿真错误。摸索出来的解决方法是在可能的路径中分别复制一份对应文件。
(3)可以通过给FPGA断电后再上电来清除上一次下载到FPGA中的程序。
(4)遇到报错,可将报错信息输送给一些大语言模型,往往会得到不错的改进建议,适时适量使用AI工具并非坏事。
附录(代码及资源)
代码
dds.v
//主程序
module dds(
input wire clk, // FPGA主时钟
input wire rst_n, // 复位信号
input wire button_up, // 增加频率按钮
input wire button_down, // 减少频率按钮
input wire uart_rx, // 计算机控制的UART输入
input wire select_control,// 选择控制信号:0为按键控制,1为UART控制
output wire wave_out, // 输出方波信号
output wire [6:0] hex0, // 数码管显示
output wire [6:0] hex1,
output wire [6:0] hex2
);
wire [19:0] freq_from_button; // 来自按键控制的频率选择
wire [19:0] freq_from_uart; // 来自UART控制的频率选择
reg [19:0] freq_sel; // 实际选择的频率
// 按键控制模块
button_control btn_ctrl (
.clk(clk),
.rst_n(rst_n),
.button_up(button_up),
.button_down(button_down),
.freq_sel(freq_from_button)
);
// 方波信号生成模块
clock_divider clk_div (
.clk(clk),
.rst_n(rst_n),
.freq_sel(freq_sel),
.wave_out(wave_out)
);
// 数码管显示模块
seven_segment_display display (
.clk(clk),
.rst_n(rst_n),
.freq_sel(freq_sel),
.hex0(hex0),
.hex1(hex1),
.hex2(hex2)
);
// 计算机调节模块
uart_control uart_ctrl (
.clk(clk),
.rst_n(rst_n),
.uart_rx(uart_rx),
.freq_sel(freq_from_uart)
);
// 多路选择器
always @(*) begin
if (select_control)
freq_sel = freq_from_uart; // 如果select_control为1,用UART控制频率
else
freq_sel = freq_from_button; // 否则用按键控制频率
end
endmodule
clock_divider.v
// 时钟分频器模块
module clock_divider(
input wire clk, // FPGA主时钟,例如50MHz
input wire rst_n, // 复位信号
input wire [31:0] freq_sel, // 选择的频率(步进为1kHz)
output reg wave_out // 输出方波信号
);
reg [31:0] counter;
reg [31:0] threshold;
always @(posedge clk or negedge rst_n)
begin
threshold = 85899*freq_sel;
if(!rst_n)
counter <= 0;
else
counter <= counter + threshold;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
wave_out <= 0;
else if(counter < 32'h7FFF_FFFF)
wave_out <= 0;
else
wave_out <= 1;
end
endmodule
button_control.v
module button_control(
input wire clk,
input wire rst_n,
input wire button_up, // 增加频率按钮
input wire button_down, // 减少频率按钮
output reg [19:0] freq_sel // 输出选择的频率
);
reg [19:0] freq_max = 20'd1000; // 最大频率 1 MHz (1000 kHz)
reg [19:0] freq_min = 20'd1; // 最小频率 1 kHz
reg button_up_last;
reg button_down_last;
// 检测下降沿
wire button_up_fall = (button_up_last == 1) && (button_up == 0);
wire button_down_fall = (button_down_last == 1) && (button_down == 0);
always @(posedge clk) begin
if (!rst_n) begin
freq_sel <= 20'd1;
button_up_last <= 1'b1;
button_down_last <= 1'b1; // 默认频率1 kHz
end else begin
// 更新按键的上一个状态
button_up_last <= button_up;
button_down_last <= button_down;
// 处理按键下降沿
if (button_up_fall && freq_sel < freq_max)
freq_sel <= freq_sel + 1;
else if (button_down_fall && freq_sel > freq_min)
freq_sel <= freq_sel - 1;
end
end
endmodule
seven_segment_display.v
// 数码管显示模块
module seven_segment_display(
input wire clk,
input wire rst_n,
input wire [19:0] freq_sel, // 当前选择的频率值(单位kHz)
output reg [6:0] hex0, // 数码管显示频率的最低位
output reg [6:0] hex1, // 数码管显示频率的中间位
output reg [6:0] hex2 // 数码管显示频率的最高位
);
wire [3:0] digit0 = freq_sel % 10; // 频率个位
wire [3:0] digit1 = (freq_sel / 10) % 10; // 频率十位
wire [3:0] digit2 = (freq_sel / 100) % 10; // 频率百位
always @(*) begin
hex0 = digit_to_segment(digit0);
hex1 = digit_to_segment(digit1);
hex2 = digit_to_segment(digit2);
end
function [6:0] digit_to_segment;
input [3:0] digit;
case (digit)
4'd0: digit_to_segment = 7'b1000000; // 显示0
4'd1: digit_to_segment = 7'b1111001; // 显示1
4'd2: digit_to_segment = 7'b0100100; // 显示2
4'd3: digit_to_segment = 7'b0110000; // 显示3
4'd4: digit_to_segment = 7'b0011001; // 显示4
4'd5: digit_to_segment = 7'b0010010; // 显示5
4'd6: digit_to_segment = 7'b0000010; // 显示6
4'd7: digit_to_segment = 7'b1111000; // 显示7
4'd8: digit_to_segment = 7'b0000000; // 显示8
4'd9: digit_to_segment = 7'b0010000; // 显示9
default: digit_to_segment = 7'b1111111; // 默认不显示
endcase
endfunction
endmodule
uart_control.v
module uart_control(
input wire clk, // FPGA主时钟
input wire rst_n, // 复位信号
input wire uart_rx, // 接收来自计算机的UART信号
output reg [19:0] freq_sel // 输出设置的频率值
);
wire [7:0] uart_data; // 单字节UART数据
wire uart_data_ready; // 数据是否接收完成的标志
reg [15:0] received_data; // 两字节拼接后的数据
reg [1:0] byte_counter; // 字节计数器,跟踪接收的字节数
reg data_processed; // 数据是否已处理标志
// 实例化UART接收器
uart_receiver uart_rx_inst (
.clk(clk),
.rst_n(rst_n),
.rx(uart_rx),
.data(uart_data),
.data_ready(uart_data_ready)
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
freq_sel <= 20'd1; // 默认频率1 kHz
received_data <= 16'd0;
byte_counter <= 2'd0;
data_processed <= 1'b0;
end else begin
// 当UART数据接收完成且尚未处理时
if (uart_data_ready && !data_processed) begin
// 处理接收到的第一个或第二个字节
if (byte_counter == 2'd0) begin
received_data[7:0] <= uart_data; // 保存第一个字节
byte_counter <= byte_counter + 1;
end else if (byte_counter == 2'd1) begin
received_data[15:8] <= uart_data; // 保存第二个字节
byte_counter <= 2'd0; // 重置字节计数器
// 检查拼接后的频率是否在有效范围内
if (received_data >= 16'd1 && received_data <= 16'd1000) begin
freq_sel <= {4'd0, received_data}; // 将16位数据扩展为20位
end
data_processed <= 1'b1; // 标记数据已处理
end
end
// 当数据未准备好时,重置标志以等待下一个数据
if (!uart_data_ready) begin
data_processed <= 1'b0;
end
end
end
endmodule
uart_receiver.v
module uart_receiver (
input wire clk, // FPGA主时钟
input wire rst_n, // 复位信号
input wire rx, // UART接收信号
output reg [7:0] data, // 接收到的数据
output reg data_ready // 数据接收完成标志
);
parameter CLK_FREQ = 50000000; // FPGA主时钟频率(例如50MHz)
parameter BAUD_RATE = 9600; // UART波特率(例如9600)
localparam BIT_PERIOD = CLK_FREQ / BAUD_RATE; // 每个位的时钟周期数
reg [15:0] clk_counter; // 时钟计数器
reg [3:0] bit_index; // 当前位索引
reg [7:0] rx_shift_reg; // 接收移位寄存器
reg receiving; // 接收状态标志
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_counter <= 16'd0;
bit_index <= 4'd0;
rx_shift_reg <= 8'd0;
data_ready <= 1'b0;
receiving <= 1'b0;
end else begin
// 开始接收:检测到起始位(rx == 0)
if (!receiving && rx == 1'b0) begin
receiving <= 1'b1;
clk_counter <= 16'd0;
bit_index <= 4'd0;
data_ready <= 1'b0;
end
// 接收状态:按波特率接收位
if (receiving) begin
if (clk_counter == BIT_PERIOD - 1) begin
clk_counter <= 16'd0;
if (bit_index == 4'd8) begin
// 停止位接收完成,数据完整
receiving <= 1'b0;
data <= rx_shift_reg; // 将移位寄存器中的数据存入data
data_ready <= 1'b1; // 设置数据接收完成标志
end else begin
// 继续接收数据位,移位存储
rx_shift_reg <= {rx, rx_shift_reg[7:1]};
bit_index <= bit_index + 1;
end
end else begin
clk_counter <= clk_counter + 1;
end
end else begin
data_ready <= 1'b0; // 重置data_ready标志
end
end
end
endmodule
资源
3.AI工具ChatGPThttps://chat.openai.com/https://chat.openai.com/
豆包https://www.doubao.com/chat/2377401https://www.doubao.com/chat/2377401
DeepSeekhttps://chat.deepseek.com/https://chat.deepseek.com/