系列文章目录
FPGA一键测距仪之数码管篇
FPGA一键测距仪之[按键+控制+蜂鸣器]篇
FPGA一键测距仪之超声波模块篇
第一个FPGA小项目:基于BASYS3的超声波一键测距仪
前言
在本篇中我们利用Vivado工具来添加工程代码、编译综合、行为仿真、布线以及管脚规划,进而可以烧到板子中跑。
工程项目网盘:
链接:https://pan.baidu.com/s/14CchcLltGgRJ8tUFpD0XHA
提取码:he42
一、项目总设计文件(vlg_design.v)的代码实现
下面为“一键测距”总工程vlg_design.v文件的例化声明,将按键模块、超声波模块、数码管显示模块、控制模块、蜂鸣器模块互相连接、组合成总工程。
`timescale 1ns/1ps
module vlg_design(
input i_clk, //100MHz系统时钟输入
input i_rst, //复位信号输入
input i_btn, //按键输入
input i_echo, //接超声波测距传感器的echo引脚,测距传感器回响脉冲输入
output o_trig, //接超声波测距传感器的trig引脚,输出测距传感器的触发信号
output o_beep, //接蜂鸣器+极
output [3:0] o_sel, //接板载数码管的位选引脚,输出位选信号给数码管
output [6:0] o_seg, //接板载数码管的段选引脚,输出段选信号给数码管
output o_dot //接数码管小数点段选引脚,输出小数点给数码管
);
wire [15:0] w_distance_data;
wire w_btn_pos,w_check_pos,w_en;
/******************按键模块******************/
vlg_key uut_vlg_key(
.i_clk(i_clk),
.i_rst(i_rst),
.i_key(i_btn),
.o_key_posedge(w_btn_pos)
);
/********************************************/
/******************超声波模块******************/
vlg_ultrawave uut_vlg_ultrawave(
.i_clk(i_clk),
.i_rst(i_rst),
.i_en(w_en),
.i_echo(i_echo),
.o_trig(o_trig),
.o_s_mm(w_distance_data),
.o_check_posedge(w_check_pos)
);
/**********************************************/
/******************数码管显示模块******************/
vlg_display uut_vlg_display(
.i_clk(i_clk),
.i_rst(i_rst),
.i_data(w_distance_data),
.o_sel(o_sel),
.o_seg(o_seg),
.o_dot(o_dot)
);
/**************************************************/
/******************控制模块******************/
vlg_ctrl uut_vlg_ctrl(
.i_clk(i_clk),
.i_rst(i_rst),
.i_key_pulse(w_btn_pos),
.i_check_pulse(w_check_pos),
.o_en(w_en)
);
/********************************************/
/******************蜂鸣器模块******************/
vlg_beep uut_vlg_beep(
.i_clk(i_clk),
.i_rst(i_rst),
.i_check_pulse(w_check_pos),
.o_beep(o_beep)
);
/**********************************************/
endmodule
二、加载工程到Vivado中并编译综合
新建Vivado工程,下图为选择器件的过程,我们的开发板用到的FPGA芯片型号为xc7a35tcpg236-1。
我们需要把下图文件夹下的verilog设计文件全部添加到Vivado的Design Sources下。
下图为手动添加的过程,一共16份verilog文件。
添加完后形成下图的文件结构。
点击绿色的播放按钮,即可进行编译综合,下图为编译后生成的原理图,可以看到5个模块都在总工程中。
三、仿真分析
下面写一个总的仿真程序来对整个工程的时序进行测试,在程序中人为操控i_btn的电平变化来模拟按键按下的过程,并且人为产生i_echo回响脉冲让它的高电平时长每隔一段时间不断变大,直到为348us后不变,用来模拟实际测距的变化过程。
`timescale 1ns/1ps
module testbench_top();
//参数定义
`define CLK_PERIORD 10 //时钟周期设置为10ns(100MHz)
//接口申明
reg clk;
reg rst;
reg i_btn;
reg i_echo;
wire o_trig;
wire o_beep;
wire [3:0] o_sel;
wire [6:0] o_seg;
wire o_dot;
//对被测试的设计进行例化
vlg_design uut_vlg_design(
.i_clk(clk),
.i_rst(rst),
.i_btn(i_btn),
.i_echo(i_echo),
.o_trig(o_trig),
.o_beep(o_beep),
.o_sel(o_sel),
.o_seg(o_seg),
.o_dot(o_dot)
);
//复位和时钟产生
//时钟和复位初始化、复位产生
initial begin
clk <= 0;
rst <= 1;
#1000;
rst <= 0;
end
//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;
//测试激励产生
initial begin
i_echo = 0;
@(negedge rst); //等待复位完成
i_btn = 0;
@(posedge clk);
#180_000; //延时180us
i_btn = 1;
#30_000_000; //延时30ms
i_btn = 0;
end
integer dly_time = 0;
integer target_distance = 0;
always @(posedge o_trig)
begin
#20_000;
i_echo = 1;
if(dly_time==348) dly_time = 348;
else
begin
dly_time = dly_time + 58;
end
target_distance = function_t2s(dly_time); //目标理想距离,测试值60mm
#(dly_time*1000);
i_echo = 0;
end
//函数实现运算s=t*0.173
function real function_t2s;
input real t;
begin
function_t2s = 0.173*t;
end
endfunction
endmodule
下图将仿真测试程序添加到工程中。
总仿真图如下所示,在模拟的i_btn和i_echo激励输入下,o_trig输出正常,周期为100ms;o_beep输出正常,当数据稳定后o_beep会输出3个时长500ms的高电平;在目标距离target_distance到达60mm后,经过大约16个i_echo周期后测量数据进入+/-3mm的测量误差指标范围内,为59mm(在图中黄色旗帜的时刻),再经过4~5个i_echo周期检测到数据稳定,输出在数码管上。
下面我们再研究一下黄色旗帜时刻前后的数据变化和数码管显示是否有误,具体如下图所示。根据输出的位选、段选的码组可以得到,黄色旗帜前的数据显示为5.0,黄色旗帜后显示为5.9,数据单位为厘米,可见5.9cm已经在实际数据6.0cm的+/-3mm误差指标之中,虽然没有到6.0但也满足了测试需求。
四、布线及管脚规划
下面的原理图可知BASYS3开发板的时钟引脚为W5。
我们的复位和触发按键接BTNC(U18)和BTNR(T17)引脚,按键原理图如下图所示。
我们的超声波测距传感器和蜂鸣器通过开发板右上侧的PmodB排母接入,下图为板子上的PmodB排母接口电路。o_beep引脚接JB2,JB2连板子内部的A16;i_echo接JB3,JB3连板子内部的B15;o_trig引脚接JB4,JB4连板子内部的B16。
数码管原理图如下所示,其中位选组合(AN3,AN2,AN1,AN0)接(W4,V4,U4,U2)引脚,段选组合(DP,CG,CF,CE,CD,CC,CB,CA)接(V7,U7,V5,U5,V8,U8,W6,W7)引脚。
针对以上的管脚匹配,我们可以通过在原理图的查找的方法来锁定,原理图资料已在网盘中。下面为所有的管脚匹配列表。
转化为代码就是如下所示,在这代码中包含了上图那张表的管脚、电平要求信息。
set_property PACKAGE_PIN W5 [get_ports i_clk]
set_property IOSTANDARD LVCMOS33 [get_ports i_clk]
set_property IOSTANDARD LVCMOS33 [get_ports i_echo]
set_property IOSTANDARD LVCMOS33 [get_ports i_rst]
set_property IOSTANDARD LVCMOS33 [get_ports o_trig]
set_property PACKAGE_PIN B15 [get_ports i_echo]
set_property PACKAGE_PIN U18 [get_ports i_rst]
set_property PACKAGE_PIN B16 [get_ports o_trig]
set_property IOSTANDARD LVCMOS33 [get_ports {o_sel[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_sel[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_sel[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_sel[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {o_seg[0]}]
set_property PACKAGE_PIN U2 [get_ports {o_sel[0]}]
set_property PACKAGE_PIN U4 [get_ports {o_sel[1]}]
set_property PACKAGE_PIN V4 [get_ports {o_sel[2]}]
set_property PACKAGE_PIN W4 [get_ports {o_sel[3]}]
set_property PACKAGE_PIN W7 [get_ports {o_seg[0]}]
set_property PACKAGE_PIN W6 [get_ports {o_seg[1]}]
set_property PACKAGE_PIN U8 [get_ports {o_seg[2]}]
set_property PACKAGE_PIN V8 [get_ports {o_seg[3]}]
set_property PACKAGE_PIN U5 [get_ports {o_seg[4]}]
set_property PACKAGE_PIN V5 [get_ports {o_seg[5]}]
set_property PACKAGE_PIN U7 [get_ports {o_seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports i_btn]
set_property PACKAGE_PIN T17 [get_ports i_btn]
set_property IOSTANDARD LVCMOS33 [get_ports o_beep]
set_property PACKAGE_PIN A16 [get_ports o_beep]
set_property PACKAGE_PIN V7 [get_ports o_dot]
set_property IOSTANDARD LVCMOS33 [get_ports o_dot]
我们把它命名成pin_ctrl.xdc文件,并且添加到Vivado工程中,如下图所示。
然后点击Run Implementation按钮进行综合、布局布线,下图为Floorplanning的结果。
下图为布线后,结合FPGA器件所综合出来的电路图。
五、上电演示
下面3张图皆为上电的测试效果,纸盒子距超声波探头分别为4cm、7cm、12cm,实际测得距离为4.1cm、7.0cm和11.9cm,都满足要求。
总结
“FPGA一键测距仪”项目讲解完毕!