提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
1. 实验平台与目
的
DE2-E115 FPGA开发板 + Quartus + Modelsim
学习并掌握HC_SR04模块的使用
2. 实验要求
使用DE2开发板驱动HC_SR04模块,并将所测得数据显示到开发板上的数码管。
3. 实验原理
3.1. 理论原理
超声波原理:
HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为HC-SR04外观,其基本工作原理为给予此超声波测距模块触发信号后模块发射超声波,当超声波投射到物体而反射回来时,模块输出回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。
3.2. 硬件模块时序图
4. 系统架构设计
顶层文件top_wave
module top_wave(
input s_clk ,
input s_rst_n ,
//supersonic wave module singnals
input Echo ,
output trig ,
//Nixie tube display
output [6:0] Y ,
output [3:0] an ,
output dp
);
wire [15:0] data;
measurement measurement_0 (
.s_clk (s_clk ),
.s_rst_n (s_rst_n ),
.Echo (Echo ),
.trig (trig ),
.data (data )
);
xianshi xianshi_0 (
.s_clk (s_clk ),
.s_rst_n (s_rst_n ),
.A0 (data[3:0] ),
.A1 (data[7:4] ),
.A2 (data[11:8] ),
.A3 (data[15:12]),
.Y (Y ),
.an (an ),
.dp (dp )
);
endmodule
数码管显示文件xianshi
module xianshi(
input s_clk,
input s_rst_n,
input [3:0] A0,
input [3:0] A1,
input [3:0] A2,
input [3:0] A3,
output reg [6:0]Y,//显示器段选
output reg [3:0]an,//显示器位选
output reg dp
);
parameter AB=18'd300000;
reg[17:0] cnt;//动态扫描计数器
//这个时间其实可以自己控制,只要在人眼不能观察到间隔就行
always@(posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
cnt<=1'b0;
else
if(cnt == (AB-1) )
cnt<=1'b0;
else
cnt<=cnt+1;
end
/*动态扫描 选择要显示的数码管(第一个要显示),当速度快到人眼无法区分的时候就是“所有”数码管一//起显示了*/
reg[3:0]digit;//定义一个储存要显示数据的寄存器
always@(posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
begin
an <= 4'b0111;
dp <= 0;
end
else
if(cnt==AB-1)
begin
an <= {an[0],an[3:1]};
dp <= 1'b1;
end
else
begin
an <= an;
dp <= dp;
end
end
//当某一个数码管被点亮的时候,赋予其对应位置的数据
always@(posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
digit<=4'b1111;
else
case(an)
4'b1110:digit <= A0 ;
4'b1101:digit <= A1 ;
4'b1011:digit <= A2 ;
4'b0111:digit <= A3 ;
default:digit <= digit ;
endcase
end
//七段译码器(显示器)
always@(*)
begin
case(digit)
4'b0000:Y<=7'b0000001;
4'b0001:Y<=7'b1001111;
4'b0010:Y<=7'b0010010;
4'b0011:Y<=7'b0000110;
4'b0100:Y<=7'b1001100;
4'b0101:Y<=7'b0100100;
4'b0110:Y<=7'b0100000;
4'b0111:Y<=7'b0001111;
4'b1000:Y<=7'b0000000;
4'b1001:Y<=7'b0000100;
default Y<=7'b0000001;
endcase
end
endmodule
倒车模块measurement
module measurement(
//system singnals
input s_clk ,
input s_rst_n ,
//supersonic wave module singnals
input Echo ,
output reg trig ,
//connect with Nixie tube display
output reg [15:0] data
);
//
//generate cnt_17M_en
//单比特跨时钟域处理,延时两拍
reg [2:0] Echo_delay;
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
begin
Echo_delay <= 'd0;
end
else
begin
Echo_delay <= {Echo_delay[1:0],Echo};
end
end
//检测上升沿下降沿
wire nege_Echo;
wire pose_Echo;
assign pose_Echo = (~Echo_delay[2])&&Echo_delay[1];
assign nege_Echo = Echo_delay[2]&&(!Echo_delay[1]);
//产生计数使能信号
reg cnt_17M_en;
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
cnt_17M_en <= 'd0;
else
if(pose_Echo)
cnt_17M_en <= 1'b1;
else
if(nege_Echo)
cnt_17M_en <= 1'b0;
else
cnt_17M_en <= cnt_17M_en;
end
//
//div_clk_17Mhz
reg [11:0] cnt_17M;
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
cnt_17M <= 'd0;
else
if(cnt_17M_en)
begin
if(cnt_17M == 'd2942)
cnt_17M <= 'd0;
else
cnt_17M <= cnt_17M + 1'b1;
end
else
cnt_17M <= 'd0;
end
reg clk_17M;
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
clk_17M <= 1'b0;
else
if(cnt_17M == 'd2942)
clk_17M <= 1'b1;
else
clk_17M <= 1'b0;
end
//
//generate trig
reg [25:0] cnt_500Ms;
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
cnt_500Ms <= 1'b0;
else
if(cnt_500Ms == 'd12_500_000)
cnt_500Ms <= 'd0;
else
cnt_500Ms <= cnt_500Ms + 1'b1;
end
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
trig <= 1'b0;
else
if(cnt_500Ms <= 'd500)
trig <= 1'b1;
else
trig <= 1'b0;
end
//显示部分,使用计数器进行计数(17MHz)
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
data <= 'd0;
else
if(clk_17M == 1'b1)
begin
if(data[3 :0 ] == 'd9)
begin
data[7 :4 ] <= 1'b1 + data[7 :4 ];
data[3 :0 ] <= 'd0;
end
else
if(data[7 :4 ] == 'd9)
begin
data[11:8 ] <= 1'b1 + data[11:8 ];
data[7 :4 ] <= 'd0;
end
else
if(data[11:8 ] == 'd9)
begin
data[15:12] <= 1'b1 + data[15:12];
data[11:8 ] <= 'd0;
end
else
data <= data + 1'b1;
end
else
if(cnt_500Ms == 'd12_500_000)
data <= 'd0;
else
data <= data;
end
endmodule
总结
基本实现了倒车模块和在数码管上显示距离,但是存在一定的问题,传输过来的信号不大稳定,使数码管上显示的距离会波动。