使用System-Verilog实现FPGA基于DE2-115开发板驱动HC_SR04超声波测距模块|集成蜂鸣器,led和vga提示功能

文章目录

  • 前言
  • 一、实验原理
    • 1.1 传感器概述:
    • 1.2 传感器引脚
    • 1.3 传感器工作原理
    • 1.4 整体测距原理及编写思路
  • 二、System-Verilog文件
    • 2.1 时钟分频
    • (1)clk_div.sv
    • 2.2 超声波测距
    • (1)hc_sr_trig.sv
    • (2)hc_sr_echo.sv
    • 2.3 数码管驱动
    • (1)seg_driver.sv
    • 2.4 VGA驱动
    • (1)vga_dirve.sv
  • 三、实现过程
    • 3.1 模块说明
    • 3.2 引脚分配
  • 三、演示视频
  • 总结
  • 参考


前言

环境

  1. 硬件 DE2-115 HC-SR04超声波传感器

  2. 软件 Quartus 18.1

目标结果

使用DE2-115开发板驱动HC-SR04模块,并将所测得数据显示到开发板上的数码管。

模拟倒车雷达,集成蜂鸣器,led和vga提示功能

  1. 蜂鸣器提示小于20cm1s一响小于10cm0.5s一响
  2. LED提示小于20cm全亮提示
  3. VGA提示小于20cm ,显示 警告warning 图片

小tips:
VSCODE插件安装一波
在这里插入图片描述


一、实验原理

1.1 传感器概述:

HC-SR04超声波距离传感器的核心是两个超声波传感器。一个用作发射器,将电信号转换为40 KHz超声波脉冲。接收器监听发射的脉冲。如果接收到它们,它将产生一个输出脉冲,其宽度可用于确定脉冲传播的距离。就是如此简单!该传感器体积小,易于在任何机器人项目中使用,并提供2厘米至400厘米(约1英寸至13英尺)之间出色的非接触范围检测,精度为3mm。

在这里插入图片描述

1.2 传感器引脚

在这里插入图片描述

  • VCC 是HC-SR04超声波距离传感器的电源

  • Trig 引脚用于触发超声波脉冲

  • Echo 回声当接收到反射信号时,引脚产生一个脉冲。脉冲的长度与检测发射信号所需的时间成正比

  • GND 用于接地

1.3 传感器工作原理

当持续时间至少为10 µS(10微秒)的脉冲施加到触发引脚时,一切就开始了。响应于此,传感器以40 KHz发射八个脉冲的声音脉冲。这种8脉冲模式使设备的“超声特征”变得独一无二,从而使接收器能够将发射模式与环境超声噪声区分开。八个超声波脉冲通过空气传播,远离发射器。同时,回声引脚变为高电平,开始形成回声信号的开始。如果这些脉冲没有被反射回来,则回波信号将在38毫秒后超时并返回低电平。因此38 ms的脉冲表示在传感器范围内没有阻塞。
在这里插入图片描述如果这些脉冲被反射回去,则在收到信号后,Echo引脚就会变低。这会产生一个脉冲,其宽度在150 µS至25 mS之间变化,具体取决于接收信号所花费时间。

在这里插入图片描述

HC-SR04的时序图如下:
在这里插入图片描述

通过时序图我们可以知道,我们给HC-SR04发送长达 10us 的TTL脉冲,然后模块就会进行测距,测距的结果通过回响信号传达,回响的TTL电平信号时间即是超声波从HC-SR04模块发出,触碰到障碍物后返回到HC-SR04模块的时间总和。

TTL是逻辑电平标准,当电压达到2.4V-5V之间,那么为逻辑1(高电平),电压在0V~0.4V之间,那么为逻辑0(低电平)。所以我们可以直接通过GPIO口来输出以及输入时序所需的电平信号。

然后,将接收到的脉冲的宽度用于计算到反射物体的距离。这可以通过我们在初中学到的简单的距离-速度-时间方程来解决。

距离=速度x时间 ,当然温度,以及环境噪声等对实验结果都有影响,因此公式应在不同环境下进行修改

总所周知,声音的速度为340m/s,因此我们将回响电平的时间除340再除2之后得到的就是单位为米的测距结果。

1.4 整体测距原理及编写思路

在这里插入图片描述
编写思路:

以上时序图表明我们只需要提供一个10uS以上脉冲触发信号,该模块内部将发出8个40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。
回响信号的脉冲宽度与所测的距离成正比。此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式:uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2:建议测量周期为60ms以上,以防止发射信号对回响信号的影响。

结合说明书我们可以知道,我们仅需提供10us的高电平给Trig口即可。然后HC-SR04在测量完毕之后会将结果通过Echo回响回来。

所以我们只需要将Trig口拉高,等待10us(最好再延长一些,代码中用的是15us)后再拉低即可。

接着就只需要等待Echo将数据传输回来,通过时序图我们可以得知回响信号是拉高Echo口,再拉低,中间持续的时间就是测距的结果。

所以我们给Echo口配置一个中断事件,设置为上跳变下跳变都触发,另外再用一个变量记录Echo口到底是拉高还是拉低即可。

如果是拉高,那么我们需要记录下持续的时间,这时候我们需要用定时器计时,所以需要在一开始的时候就配置好定时器的初始化。唯一的问题就是该如何配置定时器的预分频器和自动重装器了。

根据说明书我们可以知道HC-SR04的精度为3mm,而测距的公式为 us/58-cm,稍加计算可知,如果我们需要测量3mm,那么得到的时间为17.4us,以此为一个刻度,那么定时器的频率应该为57471Hz。然而这样太麻烦了,而且也不好用,因此我们可以随意一些,我在代码中使用的是预分频器为72,自动重装器为100,那么得到的频率为72MHz/72/100=1000Hz,也就是一次定时器中断的时间为100us,而自动重装器里的每一个值就是1us,所以每次外部中断的下降沿触发之后只需要将定时器触发的次数*100再加上自动重装器里的值就可以得到回响信号的持续时间了,单位是us。

二、System-Verilog文件

2.1 时钟分频

(1)clk_div.sv

定义时钟分频模块,产生周期为1us的时钟信号
clk_div.sv

// //产生一个以微秒为周期的时钟信号clk_us,该信号可用于驱动一些需要精确时间控制的电路
module clk_div(
    input logic Clk,           // 输入系统时钟,50MHz
    input logic Rst_n,         // 输入复位信号,低电平有效
    
    output logic clk_us        // 输出微秒级时钟信号
);

    // 参数声明 1us = 1000ns = 50个时钟周期
    parameter int CNT_MAX = 19'd50;  //1us的计数值为 50 * Tclk(20ns)

    // 内部线网/寄存器声明
    logic [18:0] cnt;          // 定义一个19位的计数器
    logic add_cnt;             // 计数器使能信号
    logic end_cnt;             // 计数器结束信号,达到最大值时有效

    // 计数器的寄存器逻辑
    always_ff @(posedge Clk, negedge Rst_n) begin
        if (!Rst_n) begin       // 如果复位信号有效,则计数器清零
            cnt <= '0; 
        end
        else if (add_cnt) begin // 如果计数器达到最大值,则计数器重置
            if (end_cnt) begin
                cnt <= '0; 
            end
            else begin          // 否则计数器继续计数
                cnt <= cnt + 1'b1; 
            end
        end
        else begin
            cnt <= cnt;         // 如果计数器未使能,则保持当前值
        end
    end

    // 赋值计数器使能信号,始终使计数器有效
    assign add_cnt = 1'b1; 
    // 赋值计数器结束信号,当计数器使能并且计数值达到CNT_MAX - 1时有效
    assign end_cnt = add_cnt && cnt >= CNT_MAX - 19'd1;
    // 赋值输出时钟信号,当计数器达到最大值时输出一个脉冲
    assign clk_us = end_cnt;

endmodule

2.2 超声波测距

  • 实现HC-SR04超声波传感器的触发模块,用于生成触发测距信号(trig)
  • 定义HC-SR04超声波传感器的回声模块,用于测量距离并输出检测距离数据(data_o)

(1)hc_sr_trig.sv

hc_sr_trig.sv:

// hc_sr_trig 模块定义开始,用于生成超声波触发信号
//   Description  ﹕超声波触发测距模块
// 波形周期 300ms,前 15us 高电平
module hc_sr_trig (
    input logic clk_us,    // 输入 1MHz 系统时钟
    input logic Rst_n,     // 输入复位信号,低电平有效
    
    output logic trig      // 输出触发测距信号
);

    // 参数声明 300_000*1_000ns = 3 *10^8ns = 0.3s = 300ms
    // 波形周期 300ms,前 10us 高电平
    // 建议测量周期为 60ms 以上,以防止发射信号对回响信号的影响。
    parameter int CYCLE_MAX = 19'd300_000; // 定义触发信号的一个周期计数,基于 1MHz 时钟

    // 内部线网/寄存器声明
    logic [18:0] cnt;       // 计数器,用于生成触发信号的时间控制
    logic add_cnt;          // 计数器使能信号
    logic end_cnt;          // 计数器结束信号,达到预定义周期时有效

    // 计数器逻辑,用于控制触发信号的产生
    always_ff @(posedge clk_us, negedge Rst_n) begin
        if (!Rst_n) begin    // 如果复位信号有效,则计数器清零
            cnt <= '0;
        end else if (add_cnt) begin  // 如果计数器使能
            if (end_cnt) begin       // 如果计数器达到预定义的最大周期
                cnt <= '0;           // 计数器重置
            end else begin
                cnt <= cnt + 1'b1;   // 否则计数器递增
            end
        end else begin
            cnt <= cnt;              // 如果计数器未使能,则保持当前值
        end
    end

    assign add_cnt = 1'b1;           // 赋值计数器使能信号,始终使计数器有效
    assign end_cnt = add_cnt && (cnt == CYCLE_MAX - 9'd1); // 赋值计数器结束信号,当计数器值达到 CYCLE_MAX - 1 时有效

    // 赋值触发信号,当计数器值小于 15 时,输出高电平,作为触发
    // cnt < 15 置为高电平,表示前 15us 为高电平,作为触发信号
    // 此逻辑基于 HC-SR04 模块的触发信号需求,通常为 10 微秒的高电平
    assign trig = (cnt < 15) ? 1'b1 : 1'b0;

    /*
        计数器 cnt 用于生成持续一定时间的触发信号 trig。当计数器小于 15 时,trig 为高电平,表示触发信号是活跃的。
        计数器在每个 1MHz 时钟的上升沿递增,当计数器达到设定的最大周期 CYCLE_MAX 时,计数器重置,重新开始计数。
        这样,trig 信号就会周期性地输出高电平脉冲,以满足 HC-SR04 超声波传感器的触发需求。
    */

endmodule

(2)hc_sr_echo.sv

hc_sr_echo.sv

// 处理HC-SR04超声波传感器的回声信号,并计算距离
//   Description  ﹕超声波检测距离模块
// 本模块理论测试距离 2cm~510cm
// 输出结果保留两位小数
module hc_sr_echo
(
    input logic Clk,        // 输入50MHz时钟信号
    input logic clk_us,     // 输入1MHz系统时钟信号
    input logic Rst_n,      // 输入复位信号,低电平有效
    
    input logic echo,       // 输入超声波回声信号
    output logic [18:0] data_o  // 输出检测到的距离,以厘米为单位,保留三位小数
);

/* 		S(um) = 17 * t 		-->  x.abc cm	*/
//Parameter Declarations
    parameter T_MAX = 16'd60_000; // 定义计数器的最大值,对应510厘米

    logic r1_echo, r2_echo;  // 用于边沿检测的寄存器
    logic echo_pos, echo_neg;  // 回声信号的上升沿和下降

    logic [15:0] cnt;  // 1MHz时钟下的计数器,用于测量回声脉冲宽度
    logic add_cnt;  // 计数器使能信号
    logic end_cnt;  // 计数器结束信号
    
    logic [18:0] data_r;  // 距离数据的中间寄存器

    // 逻辑描述
    // 使用50MHz时钟检测回声信号的边沿,以避免使用1MHz时钟导致的2us延时
    always_ff @(posedge Clk or negedge Rst_n) begin
        if (!Rst_n) begin
            r1_echo <= 1'b0;
            r2_echo <= 1'b0;
        end
        else begin
            r1_echo <= echo;
            r2_echo <= r1_echo;
        end
    end

    // 产生上升沿和下降沿信号
    assign echo_pos = r1_echo & ~r2_echo;  // 回声信号上升沿
    assign echo_neg = ~r1_echo & r2_echo;  // 回声信号下降沿
    
    // 计数器逻辑,用于测量回声脉冲宽度
    always_ff @(posedge clk_us or negedge Rst_n) begin
        if (!Rst_n) begin
            cnt <= '0; 
        end
        else if (add_cnt) begin
            if (end_cnt) begin
                cnt <= cnt;  // 如果达到最大测量范围,则保持当前计数值
            end
            else begin
                cnt <= cnt + 1'b1; // 否则计数器递增
            end
        end
        else begin  // 如果回声信号低电平,计数器归零
            cnt <= '0;
        end
    end
    
    assign add_cnt = echo; // 赋值计数器使能信号,当回声信号为高电平时使能计数器
    assign end_cnt = add_cnt && cnt >= T_MAX - 1; //赋值计数器结束信号,当计数器达到最大值T_MAX时有效 超出最大测量范围则保持不变,极限

    // 测试距离=(高电平时间*声速(340M/S))/2;
    // 距离数据处理逻辑,将计数值转换为距离
    always_ff @(posedge Clk or negedge Rst_n) begin
        if (!Rst_n) begin
            data_r <= 'd2;  // 复位时中间寄存器置为2,用于小数点后三位的计算
        end
        else if (echo_neg) begin
            // 当回声信号下降沿到来时,将计数值左移四位并加上自身,实现小数点后三位的计算
            //t = cnt*1000ns = cnt*10-6s
            //s = 340*t m
            data_r <= (cnt << 4) + cnt;
        end
        else begin
            data_r <= data_r;  // 否则保持当前值
        end
    end

    // 将中间寄存器的数据右移一位,实现除以2的操作,得到最终的距离数据
    assign data_o = data_r >> 1;

endmodule

2.3 数码管驱动

查看平台手册,发现DE2-115开发板不涉及位选信号,每个段选信号都有一个单独的引脚。在这里插入图片描述
数码管驱动器模块代码如下,用于将输入的数据(data_o)转换为对应的数码管显示:

(1)seg_driver.sv

seg_driver:


// seg_driver模块用于驱动七段显示器,显示数字或特定的符号。
module seg_driver(
    input   logic       Clk,     // 输入的时钟信号。
    input   logic       Rst_n,   // 低电平有效的复位信号。
    input   logic [18:0] data_o, // 输入的数字数据,这里假设是测得的距离数据。
    output  logic [6:0]  hex1,   // 第1个七段显示器的段选信号输出。
    output  logic [6:0]  hex2,   // 第2个...
    output  logic [6:0]  hex3,
    output  logic [6:0]  hex4,
    output  logic [6:0]  hex5,
    output  logic [6:0]  hex6,
    output  logic [6:0]  hex7,
    output  logic [6:0]  hex8     
);

// 参数定义区,定义了特殊显示值和小数点的编码,以及计数器的最大值。
parameter NOTION  = 4'd10,  // 定义数字"10"用于消隐的编码。
         FUSHU   = 4'd11,  // 定义数字"11"用作小数点的编码。
         MAX20us = 10'd1000; // 定义20微秒计数器的最大值。

// 寄存器声明区,声明了用于控制和显示数字的内部寄存器。
logic [9:0]   cnt_20us;  // 用于动态扫描定时的20微秒计数器。
logic [7:0]   sel_r;     // 动态扫描控制的片选信号寄存器。
logic [3:0]   number;    // 要显示的数字,范围0-9或特殊编码。
logic [6:0]   seg_r;     // 根据number解析得到的七段显示器段选编码。

// 每个七段显示器的段选编码寄存器,用于存储最终输出到显示器的段选编码。
logic [6:0]   hex1_r,   hex2_r,   hex3_r,   hex4_r,   hex5_r,   hex6_r,   hex7_r,   hex8_r;

// 20微秒计数器始终块,用于周期性地重置计数器来实现动态扫描。
always_ff @(posedge Clk or negedge Rst_n) begin
    if (!Rst_n) begin
        cnt_20us <= 0;  // 复位时计数器清零。
    end
    else if (cnt_20us == (MAX20us - 1)) begin
        cnt_20us <= 0;  // 计数器达到最大值时重置。
    end
    else begin
        cnt_20us <= cnt_20us + 1;  // 否则计数器递增。
    end
end

// 动态扫描控制始终块,用于生成选择当前激活的七段显示器的片选信号。
always_ff @(posedge Clk or negedge Rst_n) begin
    if (!Rst_n) begin
        sel_r <= 8'b11_11_11_10;  // 复位时初始化片选信号。
    end
    else if (cnt_20us == (MAX20us - 1)) begin
        sel_r <= {sel_r[6:0], sel_r[7]};  // 计数器达到最大值时,片选信号左移循环。
    end
    else begin
        sel_r <= sel_r;  // 否则保持当前片选信号不变。
    end
end

// 组合逻辑块,根据片选信号sel_r获取要显示的数字。
always_comb begin
    case (sel_r)
        // 根据sel_r的值选择对应的数字或特殊编码。
        // 这些编码对应于输入数据data_o的不同部分。
        // ...(此处省略了部分case语句)
        default: number = 4'd0;  // 默认情况下不显示任何数字。
    endcase
end

// 组合逻辑块,根据数字解析出对应的七段显示器段选值seg_r。
always_comb begin
    case (number)
        // 对应数字0-9的七段显示器编码。
        // ...(此处省略了部分case语句)
        NOTION: seg_r = 7'b111_1111;  // 消隐编码,所有段都不亮。
        FUSHU: seg_r = 7'b011_1111;  // 小数点编码,只点亮小数点部分。
        default: seg_r = 7'b111_1111;  // 默认消隐。
    endcase
end

// 组合逻辑块,根据片选信号sel_r将seg_r值赋给对应的七段显示器寄存器。
always_comb begin
    // 初始化所有寄存器为消隐状态。
    hex1_r = 7'b111_1111;
    hex2_r = 7'b111_1111;
    hex3_r = 7'b111_1111;
    hex4_r = 7'b111_1111;
    hex5_r = 7'b111_1111;
    hex6_r = 7'b111_1111;
    hex7_r = 7'b111_1111;
    hex8_r = 7'b111_1111;

    // 根据当前选中的显示器,将seg_r的值赋给对应的寄存器。
    case (sel_r)
        8'b11_11_11_10: hex1_r = seg_r;
        8'b11_11_11_01: hex2_r = seg_r;
        // ...(此处省略了部分case语句)
        default: ;
    endcase
end

// 将寄存器的值通过assign语句输出到端口,连接到外部的七段显示器硬件。
assign  hex1 = hex1_r;
assign  hex2 = hex2_r;
assign  hex3 = hex3_r;
assign  hex4 = hex4_r;
assign  hex5 = hex5_r;
assign  hex6 = hex6_r;
assign  hex7 = hex7_r;
assign  hex8 = hex8_r;

endmodule

2.4 VGA驱动

(1)vga_dirve.sv

vga_dirve.sv:

module vga_dirve (
    input logic clk,            // 系统时钟
    input logic rst_n,          // 复位
    input logic [23:0] rgb_data, // 16位RGB对应值

    output logic vga_clk,    // vga时钟 25M
    output logic h_sync,     // 行同步信号
    output logic v_sync,     // 场同步信号
    output logic [11:0] addr_h, // 行地址
    output logic [11:0] addr_v,  // 列地址
    output logic [7:0] rgb_r,  // 红基色
    output logic [7:0] rgb_g,  // 绿基色
    output logic [7:0] rgb_b  // 蓝基色
);

// 640 * 480 60HZ
localparam int H_FRONT = 16; // 行同步前沿信号周期长
localparam int H_SYNC = 96;  // 行同步信号周期长
localparam int H_BLACK = 48; // 行同步后沿信号周期长
localparam int H_ACT = 640;   // 行显示周期长
localparam int V_FRONT = 11; // 场同步前沿信号周期长
localparam int V_SYNC = 2;   // 场同步信号周期长
localparam int V_BLACK = 31; // 场同步后沿信号周期长
localparam int V_ACT = 480;  // 场显示周期长

// 800 * 600 72HZ (已注释,使用640*480)
// ...

localparam int H_TOTAL = H_FRONT + H_SYNC + H_BLACK + H_ACT; // 行周期
localparam int V_TOTAL = V_FRONT + V_SYNC + V_BLACK + V_ACT; // 列周期

logic [11:0] cnt_h; // 行计数器
logic [11:0] cnt_v; // 场计数器
logic [23:0] rgb;  // 对应显示颜色值

// 对应计数器开始、结束、计数信号
logic flag_enable_cnt_h, flag_clear_cnt_h, flag_enable_cnt_v, flag_clear_cnt_v, flag_add_cnt_v, valid_area;

// 25M时钟 行周期*场周期*刷新率 = 800 * 525* 60
logic clk_25;
// 50M时钟 1040 * 666 * 72
// ...

// PLL实例化生成时钟
pll pll_inst (
    .areset(~rst_n),
    .inclk0(clk),
    .c0(clk_50), // 50M
    .c1(clk_25)  // 25M
);

// 根据不同分配率选择不同频率时钟
assign vga_clk = clk_25;

// 行计数
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt_h <= 0;
    end else if (flag_enable_cnt_h) begin
        cnt_h <= flag_clear_cnt_h ? 0 : cnt_h + 1;
    end
end

// 行同步信号
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        h_sync <= 0;
    end else if (cnt_h == H_SYNC - 1) begin
        h_sync <= 1;
    end else if (flag_clear_cnt_h) begin
        h_sync <= 0;
    end
end

// 场计数
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt_v <= 0;
    end else if (flag_enable_cnt_v) begin
        cnt_v <= flag_clear_cnt_v ? 0 : cnt_v + flag_add_cnt_v;
    end
end

// 场同步信号
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        v_sync <= 0;
    end else if (cnt_v == V_SYNC - 1) begin
        v_sync <= 1;
    end else if (flag_clear_cnt_v) begin
        v_sync <= 0;
    end
end

// 对应有效区域行地址 1-640
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        addr_h <= 0;
    end else if (valid_area) begin
        addr_h <= cnt_h - H_SYNC - H_BLACK + 1;
    end
end

// 对应有效区域列地址 1-480
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        addr_v <= 0;
    end else if (valid_area) begin
        addr_v <= cnt_v - V_SYNC - V_BLACK + 1;
    end
end

// 有效显示区域
assign valid_area = cnt_h >= H_SYNC + H_BLACK && cnt_h <= H_SYNC + H_BLACK + H_ACT &&
                    cnt_v >= V_SYNC + V_BLACK && cnt_v <= V_SYNC + V_BLACK + V_ACT;

// 显示颜色
always_ff @(posedge vga_clk or negedge rst_n) begin
    if (!rst_n) begin
        rgb <= 24'b0;
    end else if (valid_area) begin
        rgb <= rgb_data;
    end
end

assign rgb_r = rgb[23:16];
assign rgb_g = rgb[15:8];
assign rgb_b = rgb[7:0];

endmodule // vga_dirve






三、实现过程

3.1 模块说明

这里要求超声波模块的正负极分别接入5V和GND,其余trigger和echo自由接线,我这里使用的是GPIO[0]和GPIO[1]

在这里插入图片描述

3.2 引脚分配

首先这里提出引脚配置,其中trig和echo引脚与自己所接线的位置向同即可在这里插入图片描述

配置文件如下:
在这里插入图片描述
在这里插入图片描述

三、演示视频

使用System-Verilog实现FPGA基于DE2-115开发板驱动HC_SR04超声波测距模块|集成蜂鸣器,led和vga提示功能


总结

在本项目中,我成功实现了基于FPGA DE2-115开发板的HC-SR04超声波测距模块。通过使用SystemVerilog语言,我们设计并实现了时钟分频、超声波测距、数码管驱动以及VGA驱动等多个关键模块。这些模块协同工作,实现了超声波测距的基本功能,并将测量结果显示在数码管上,同时集成了蜂鸣器、LED和VGA提示功能,增强了用户体验。

关键实现点:

  1. 时钟分频模块 (clk_div.sv):生成周期为1us的时钟信号,为系统提供精确的时间控制。
  2. 超声波测距模块 (hc_sr_trig.sv 和 hc_sr_echo.sv):负责触发测距信号并处理回声信号,计算出距离。
  3. 数码管驱动模块 (seg_driver.sv):将测得的距离数据转换为数码管可以显示的格式。
  4. VGA驱动模块 (vga_dirve.sv):负责生成VGA信号,并在屏幕上显示警告图片,提供视觉反馈。

集成功能:

  1. 蜂鸣器提示小于20cm1s一响小于10cm0.5s一响
  2. LED提示小于20cm全亮提示
  3. VGA提示小于20cm ,显示 警告warning 图片

测试与验证:
通过在DE2-115开发板上的实际测试,我们验证了系统的测距功能和各种提示功能的准确性。展示了超声波测距模块的基本实现和扩展应用的可能性。

结论:
本项目不仅加深了对FPGA和SystemVerilog的理解,而且通过实际应用提高了解决实际问题的能力。虽然在实现过程中参考了前辈的代码,但能够补全并改进代码,对我来说是一次宝贵的学习和成长经历。期待在未来的项目中继续探索和创新。

参考

FPGA基于DE2-115 开发板板和HC_SR04驱动的超声波测距

基于DE2 115开发板驱动HC_SR04超声波测距模块

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/673311.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

简单聊聊分布式系统和微服务

分布式系统是由多个独立的计算机节点通过网络相互连接协作&#xff0c;共同完成一项或多项任务的系统。这些节点可以是服务器、个人电脑、移动设备等&#xff0c;它们之间通过消息传递或共享数据来协调工作&#xff0c;每个节点负责系统整体功能的一部分。分布式系统的关键在于…

k8s学习--k8s集群使用容器镜像仓库Harbor

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 环境 步骤一 容器镜像仓库Harbor部署二、Kubernetes集群使用harbor仓库 环境 Ip主机名cpu内存硬盘192.168.10.11master1cpu双核2G40G192.168.10.12node011cpu双核2…

网络链路层

data: 2024/5/25 14:02:20 周六 limou3434 叠甲&#xff1a;以下文章主要是依靠我的实际编码学习中总结出来的经验之谈&#xff0c;求逻辑自洽&#xff0c;不能百分百保证正确&#xff0c;有错误、未定义、不合适的内容请尽情指出&#xff01; 文章目录 1.协议结构2.封装分离3.…

计算机毕业设计 | SpringBoot 房屋销售租赁平台 房屋购物网站(附源码)

1&#xff0c;绪论 1.1 背景调研 在房地产行业持续火热的当今环境下&#xff0c;房地产行业和互联网行业协同发展&#xff0c;互相促进融合已经成为一种趋势和潮流。本项目实现了在线房产平台的功能&#xff0c;多种技术的灵活运用使得项目具备很好的用户体验感。 这个项目的…

Python自动化识别与删除Excel表格空白行和列

在处理Excel数据时&#xff0c;经常会遇到含有空白行和空白列的情况。这些空白区域不仅占用表格显示空间&#xff0c;还可能导致数据分析时出现偏差&#xff0c;影响数据处理的效率与结果的准确性&#xff0c;如空白行可能干扰数据聚合操作&#xff0c;导致统计计数不准确&…

【嵌入式DIY实例】-OLED显示天气数据

OLED显示天气数据 文章目录 OLED显示天气数据1、硬件准备与接线2、天气数据获取准备3、代码实现在这个物联网项目中,本文将展示如何使用 ESP8266 NodeMCU (ESP-12E) Wi-Fi 开发板和 SSD1306 OLED 显示屏(12864 像素)制作一个简单的互联网气象站。 NodeMCU 从天气网站 openwe…

牛客网刷题 | BC114 圣诞树 (不理解)

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 这道题没搞懂 也没找到视…

软件定义汽车,通信连接世界 | 2024汽车软件与通信大会开幕

5月28日-30日&#xff0c;在江苏省工业和信息化厅、智能汽车安全技术全国重点实验室指导下&#xff0c;由中国中检所属中国汽车工程研究院股份有限公司&#xff08;下称&#xff1a;中国汽研&#xff09;主办&#xff0c;中汽院(江苏)汽车工程研究院有限公司承办的2024汽车软件…

RTOS(ENV)串口DMA接收GPS数据并解析

RTOS&#xff08;ENV&#xff09;配置STM32串口DMA接收模式 环境&#xff1a; RTOS 4.0.3Keil5ENVSTm32l475 ENV配置 使能串口&#xff1a; 2. 使能DMA&#xff0c;并设置接收缓冲区大小&#xff1a; 创建工程 scons --targetmdk工程配置 1. 创建串口设备句柄 #define SA…

从零开始实现一个可靠、健壮的内存池

文章目录 概要 这个项目是干什么的项目所需储备知识什么是内存池 池化技术内存池内存池主要解决的问题框架设计开发计划系统测试情况遇到的主要问题和解决方法分工和协作提交仓库目录和文件描述比赛收获 概要 这个项目是干什么的 当前项目是实现一个高并发的内存池&#xff0c…

养生与健康|一起跟随林曦老师养个元气满满

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;皆在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。    在暄桐教室的六阶…

QT 使用信号和槽,让QLabel的内容实时与QLineEdit同步,类似vue框架的双向绑定

在窗口里放置一个单行文本编辑器&#xff08;QLineEdit&#xff09;和一个标签控件&#xff08;QLabel&#xff09;&#xff0c;实现的效果就是当编辑器的内容被编辑时&#xff0c;标 签控件同步显 示编辑控件里的内容 1&#xff09;当 lineEdit 控件被用户编辑时&#xff0c;它…

边缘密度分布图 | ggExtra包/aplot拼图/ggpubr包 等的实现方法

概述&#xff1a;aplot 拼图效果好 根据网友探索[1]&#xff0c;总结如下&#xff1a; ggExtra 包的拼图间隙有点大&#xff0c;图例在主图和边缘图之间&#xff0c;除非去掉图例&#xff0c;否则没法看。aplot包的默认拼图间隙很小&#xff0c;比较美观&#xff0c;图例在外…

Java——二进制原码、反码和补码

一、简要介绍 原码、反码和补码只是三种二进制不同的表示形式&#xff0c;每个二进制数都有这三个形式。 1、原码 原码是将一个数的符号位和数值位分别表示的方法。 最高位为符号位&#xff0c;0表示正&#xff0c;1表示负&#xff0c;其余位表示数值的绝对值。 例如&…

生成式AI,在云端的绽放与盛开

编辑&#xff1a;阿冒 设计&#xff1a;沐由 毫无疑问&#xff0c;生成式AI已然成为当今技术发展和应用创新的重要引擎之一。 过去的一年多时间里&#xff0c;我们每个人都在目睹和见证着生成式AI是如何以移山倒海的力量&#xff0c;为诸多行业带来革命性乃至颠覆性的变革&…

FS118M 单A口QC协议芯片

FS118M是一个QC快充协议芯片&#xff0c;FS118M可以识别插入的手机类型&#xff0c;选择最为合适的协议应对手机需要。USB Type-A 口的 D连接到FS118M芯片&#xff0c;当手机插入到 USB Type-A 口后&#xff0c;根据各个协议的约定&#xff0c;手机和FS118M之间将开始互相识别&…

计网ppt标黄知识点整理第(2)章节——谢希仁版本、期末复习自用

物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。4 个特性&#xff1a; 机械特性&#xff1a;指明接口所用接线器的形状和尺寸、引线数目和排列、固定和锁定装置等。 电气特性&#xff1a;指明在接口电缆的各条线上出现…

C/C++开发,2024.x CLion安装,亲测有效

CLion 是一款专为 C 和 C 开发者设计的跨平台集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了智能代码补全、代码分析、调试和 Git 集成等功能&#xff0c;以提高开发效率和代码质量。 1.下载安装c/c开发工具 CLion 先去官网下载&#xff0c;我这里下载的是最新版…

【docker】docker的安装

如果之前安装了旧版本的docker我们需要进行卸载&#xff1a; 卸载之前的旧版本 卸载 # 卸载旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc # 卸载历史版本 apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker…

问答机器人

怎样做自己的问答机器人&#xff1f; 根据我们提供的数据分析出问题的答案&#xff0c;我们并不需要训练自己的模型 微调模型 finetune&#xff0c;将语言模型调成另外的语言模型&#xff0c;更适合不同类型数据&#xff0c;运用finetune方法将模型变化 知识库模型 embedd…