System-Verilog 实现DE2-115倒车雷达模拟
引言:
·
随着科技的不断进步,汽车安全技术也日益成为人们关注的焦点。在众多汽车安全辅助系统中,倒车雷达以其实用性和高效性脱颖而出,成为现代汽车不可或缺的一部分。倒车雷达系统利用超声波探测技术,帮助驾驶员在倒车时检测车辆后方的障碍物,有效避免了碰撞事故的发生,大大提高了驾驶的安全性。
·
本项目旨在设计并实现一个基于HC-SR04超声波传感器和DE2-115 FPGA开发板的倒车雷达系统。通过深入研究超声波传感器的工作原理,结合现代电子设计自动化(EDA)工具,我们将探索如何利用SystemVerilog这一高级硬件描述语言(HDL)来构建系统模型,并实现距离测量、数码管显示以及蜂鸣器警告等功能。
·
推荐歌曲—凄美地-郭顶
冲啊!!!! ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶
文章目录
- System-Verilog 实现DE2-115倒车雷达模拟
- 一、 SystemVerilog
- 1. SystemVerilog简介
- 2. 基本语法和特性
- 二、项目背景
- 1. 倒车雷达的原理和功能
- 2. HC-SR04 超声波传感器
- 3. DE2-115 开发板
- 三、实现原理
- 1. HC-SR04 传感器的工作原理
- 2. 数码管显示和蜂鸣器控制的逻辑
- 四、实现过程
- 五、实验效果
- 六、项目总结
一、 SystemVerilog
1. SystemVerilog简介
SystemVerilog是一种高级的硬件描述语言(HDL),它不仅继承了Verilog语言的所有特性,还增加了一系列的新特性,使其成为现代电子系统设计和验证的强大工具。以下是对SystemVerilog的更详尽的介绍。
起源与发展: SystemVerilog起源于2002年,由Accellera标准组织开发,并于2005年被IEEE正式采纳为IEEE 1800-2005标准。随着电子系统复杂性的增加,SystemVerilog不断更新,以满足设计者的需求。
设计和验证的重要性: SystemVerilog作为硬件设计和验证的重要工具,它允许设计者以更高的抽象层次来描述和验证复杂的电子系统。在设计阶段,SystemVerilog可以用于创建功能模型和测试平台;在验证阶段,它提供了丰富的特性来构建测试环境和检查设计是否符合预期。
应用领域:
- 集成电路设计:SystemVerilog用于设计从简单的门电路到复杂的SoC(System on Chip)。
- 仿真和原型设计:用于快速原型设计和仿真,以验证设计的功能和性能。
- 形式验证:与形式验证工具结合使用,以数学方式证明设计的属性。
- 硬件-软件协同设计:支持硬件和软件的并行开发,确保两者的兼容性。
2. 基本语法和特性
数据类型: SystemVerilog引入了多种新的数据类型,包括但不限于:
- 枚举类型(enum):允许定义一组命名的常量。
- 结构体(struct):可以创建复杂的数据结构。
- 联合体(union):允许不同的数据类型共享相同的内存位置。
- 动态数据类型:如队列(queue)和关联数组(associative arrays)。
面向对象编程: SystemVerilog支持面向对象编程(OOP)的特性,如类(class)和对象(object),以及封装、继承和多态性。
并发建模: SystemVerilog提供了并发建模的机制,如:
- 进程控制:使用
initial
和always
块来描述并发行为。 - 并发语句:如
fork-join
,允许设计者编写并行执行的代码块。
断言(Assertions): SystemVerilog提供了断言功能,用于在设计中检测错误和违反设计意图的行为。断言包括:
- 立即断言(immediate assertions):在代码执行时立即检查条件。
- 时序断言(concurrent assertions):在仿真过程中持续检查条件。
随机化: SystemVerilog支持随机化测试,允许自动生成测试向量,提高测试的覆盖率和效率。
封装: SystemVerilog支持模块化设计,通过模块(module)、程序包(package)和类(class)等封装机制,提高代码的重用性和可维护性。
时序: SystemVerilog提供了高级的时序控制语句,如always_ff
,用于精确控制时序行为。
系统任务和函数: SystemVerilog扩展了系统任务和函数,使得与仿真环境的交互更加灵活。
其他特性:
- 属性(Properties):用于定义可以在整个仿真过程中持续检查的时序属性。
- 接口(Interfaces):用于定义模块之间的通信协议,简化了复杂的连接和通信。
- 覆盖率分析:支持覆盖率分析,帮助设计者评估测试的完整性。
SystemVerilog的这些特性使其成为现代电子设计自动化(EDA)工具的核心语言之一,广泛应用于从设计到验证的各个阶段。随着技术的发展,SystemVerilog将继续演进,以满足电子系统设计日益增长的复杂性和性能要求。
二、项目背景
1. 倒车雷达的原理和功能
倒车雷达是一种汽车安全辅助系统,它通过发射和接收超声波来检测车辆后方的障碍物。其主要功能包括:
- 障碍物检测:倒车雷达能够检测到车辆后方一定范围内的障碍物,如墙壁、树木、其他车辆等。
- 距离显示:系统会实时显示与障碍物的距离,帮助驾驶员判断停车位置。
- 声音和视觉警告:当检测到障碍物距离过近时,系统会发出声音警告或在仪表盘上显示警告信息,提醒驾驶员注意。
- 自动停车辅助:一些高级的倒车雷达系统还可以与车辆的自动控制系统配合,实现自动停车。
倒车雷达的工作原理如下:
- 发射超声波:雷达系统通过超声波传感器发射高频声波。
- 接收反射波:当声波遇到障碍物时,会反射回来。
- 计算距离:系统根据发射和接收声波之间的时间差来计算障碍物与车辆的距离。
- 处理和显示信息:计算出的距离信息被处理后,通过声音或视觉方式反馈给驾驶员。
2. HC-SR04 超声波传感器
HC-SR04是一款广泛使用的超声波传感器,它由一个超声波发射器和一个接收器组成。该传感器能够通过发射和接收超声波来测量距离,其主要特点包括:
- 易用性:HC-SR04具有简单的接口,易于与微控制器或开发板连接。
- 测量范围:通常能够测量2厘米至400厘米范围内的距离。
- 精度:提供较高的测量精度,适合于多种应用场景。
- 触发和回声引脚:具有单独的触发(Trig)和回声(Echo)引脚,用于控制超声波的发射和接收。
3. DE2-115 开发板
DE2-115是一款由Altera公司(现为Intel的一部分)生产的FPGA开发板,它适用于学习和实验数字电路设计。DE2-115的主要特点包括:
- FPGA芯片:搭载了一颗FPGA芯片,提供了大量的逻辑单元和I/O引脚。
- 丰富的外设:包括多个LED、七段显示器、按钮、开关等,方便进行各种实验。
- 扩展接口:支持扩展模块,如存储器、传感器等,以增强开发板的功能。
- 开发环境:支持Quartus II等开发工具,方便进行FPGA编程和仿真。
将HC-SR04超声波传感器与DE2-115开发板结合使用,可以构建一个倒车雷达系统原型,用于学习和验证倒车雷达的原理和功能。通过编写适当的FPGA程序,可以实现超声波的发射、接收和距离计算,进而实现障碍物检测和警告功能。
三、实现原理
1. HC-SR04 传感器的工作原理
HC-SR04超声波传感器的工作原理基于超声波的发射和接收。它由两部分组成:一个超声波发射器和一个接收器。以下是其工作原理的详细步骤:
-
触发信号:当传感器的触发引脚(Trig)接收到一个至少10微秒的高电平信号时,传感器开始工作。
-
超声波发射:传感器内部的发射器产生一个频率为40kHz的连续超声波脉冲。
-
超声波传播:发射出的超声波向周围空间传播,当遇到障碍物时,超声波会被反射回来。
-
超声波接收:传感器内部的接收器监听反射回来的超声波信号。
-
计算时间差:传感器测量超声波从发射到接收的时间差。由于超声波在空气中的传播速度是已知的(大约为343米/秒,取决于温度和湿度),可以通过时间差计算出距离。
-
距离计算:距离 ( D ) 可以通过以下公式计算得出:
D = (速度 * 时间差)/2
其中,速度是声速,时间差是超声波往返的时间。
2. 数码管显示和蜂鸣器控制的逻辑
在倒车雷达系统中,数码管显示和蜂鸣器控制是两个重要的反馈机制,用于向驾驶员提供视觉和听觉警告。以下是它们的实现逻辑:
-
数码管显示:
- 距离转换:计算得到的距离需要转换为数码管能够显示的格式,通常是以厘米或米为单位。
- 数字编码:每个数字(0-9)都有对应的二进制编码,这些编码通过数码管的驱动电路转换成对应的显示。
- 动态扫描:如果数码管有多个位,需要通过动态扫描的方式依次点亮每一位,以实现连续显示。
-
蜂鸣器控制:
- 阈值设定:设定一个距离阈值,当检测到的障碍物距离小于该阈值时,蜂鸣器开始发出警告声。
- 控制信号:生成一个控制信号,当距离小于阈值时,控制信号为高电平,使蜂鸣器工作。
- 声音频率:蜂鸣器发出的声音频率可以与距离成反比,距离越近,频率越高,以提供更加紧急的警告。
在实际的倒车雷达系统中,这些逻辑可以通过FPGA开发板上的逻辑电路来实现。FPGA可以接收HC-SR04传感器的信号,处理距离数据,并根据结果控制数码管和蜂鸣器。
四、实现过程
在实现倒车雷达系统的过程中,我需要考虑几个关键的模块:超声波传感器的驱动、触发信号的生成、数码管显示以及蜂鸣器控制。以下是这些模块的分步实现介绍和代码片段示例。
1. 超声波传感器的驱动
首先,我需要编写代码来驱动HC-SR04超声波传感器。这涉及到生成触发信号,并读取回声信号。
代码片段示例:
hc_sr_driver.sv
module hc_sr_driver (input logic Clk,input logic Rst_n,input logic echo,output logic trig,output logic [18:0] data_o
);logic clk_us;hc_sr_echo u_hc_sr_echo (.Clk (Clk),.clk_us (clk_us),.Rst_n (Rst_n),.echo (echo),.data_o (data_o)
);hc_sr_trig u_hc_sr_trig (.clk_us (clk_us),.Rst_n (Rst_n),.trig (trig)
);clk_div u_clk_div (.Clk (Clk),.Rst_n (Rst_n),.clk_us (clk_us)
);endmodule
hc_sr_echo.sv
module hc_sr_echo (input logic Clk, // 系统时钟输入input logic clk_us, // 微秒时钟输入input logic Rst_n, // 复位信号,低电平有效input logic echo, // 超声波传感器的echo信号output logic [18:0] data_o // 输出的测量结果
);parameter T_MAX = 16'd60_000; // 最大计数值,代表超声波信号的最大时间间隔// 定义内部信号
logic r1_echo, r2_echo; // 用于同步和边沿检测的寄存器
logic echo_pos, echo_neg; // 上升沿和下降沿检测信号
logic [15:0] cnt; // 计数器,用于计数echo信号的高电平时间
logic add_cnt; // 计数器使能信号
logic end_cnt; // 计数器结束信号
logic [18:0] data_r; // 用于存储最终的测量结果// 对echo信号进行同步处理
always_ff @(posedge Clk or negedge Rst_n) beginif(!Rst_n) beginr1_echo <= 1'b0; // 复位时将r1_echo设为0r2_echo <= 1'b0; // 复位时将r2_echo设为0end else beginr1_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) beginif(!Rst_n) begincnt <= 'd0; // 复位时将计数器清零end else if(add_cnt) beginif(end_cnt) begincnt <= cnt; // 计数结束时保持计数值不变end else begincnt <= cnt + 1; // 计数器递增endend else begincnt <= 'd0; // 计数器未使能时清零end
end// 计数器使能信号,仅在echo信号为高电平时使能
assign add_cnt = echo;// 计数器结束信号,当计数器达到最大值时产生
assign end_cnt = add_cnt && cnt >= T_MAX - 1;// 处理echo信号的下降沿,计算距离并更新结果
always_ff @(posedge Clk or negedge Rst_n) beginif(!Rst_n) begindata_r <= 'd2; // 复位时将结果设为初始值2end else if(echo_neg) begindata_r <= (cnt << 4) + cnt; // 计算距离,cnt左移4位再加上cntend else begindata_r <= data_r; // 结果保持不变end
end// 输出结果,data_r右移1位
assign data_o = data_r >> 1;endmodule
hc_sr_trig.sv
module hc_sr_trig (input logic clk_us, // 微秒时钟输入input logic Rst_n, // 复位信号,低电平有效output logic trig // 触发信号输出
);parameter CYCLE_MAX = 19'd300_000; // 计数器的最大计数值,对应触发信号的周期
logic [18:0] cnt; // 计数器,用于生成周期性触发信号
logic add_cnt; // 计数器使能信号
logic end_cnt; // 计数器结束信号// 计数器逻辑
always_ff @(posedge clk_us or negedge Rst_n) beginif(!Rst_n) begincnt <= 'd0; // 复位时将计数器清零end else if(add_cnt) beginif(end_cnt) begincnt <= 'd0; // 计数器达到最大值后重新开始end else begincnt <= cnt + 1; // 计数器递增endend else begincnt <= cnt; // 计数器保持不变end
end// 计数器使能信号,始终使能计数器
assign add_cnt = 1'b1;// 计数器结束信号,当计数器达到最大值时产生
assign end_cnt = add_cnt && cnt >= CYCLE_MAX - 9'd1;// 生成触发信号,当计数器值小于15时,触发信号为高电平
assign trig = cnt < 15 ? 1'b1 : 1'b0;endmodule
2. 超声波时钟生成
超声波时钟生成是启动传感器发射超声波的关键步骤。
代码片段示例:
clk_div.sv
module clk_div (input logic Clk,input logic Rst_n,output logic clk_us
);
// 产生 1us 的时钟 用于给 HC-SR04 的信号
parameter CNT_MAX = 19'd50;
logic [5:0] cnt;
logic add_cnt;
logic end_cnt;always_ff @(posedge Clk or negedge Rst_n) beginif(!Rst_n) begincnt <= 'd0;end else if(add_cnt) beginif(end_cnt) begincnt <= 'd0;end else begincnt <= cnt + 1;endend else begincnt <= cnt;end
endassign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt >= CNT_MAX - 19'd1;
assign clk_us = end_cnt;
endmodule
3. 数码管显示
数码管显示模块负责将测量到的距离转换为数字格式并显示。
代码片段示例:
seg_driver.sv
module seg_driver(input logic Clk ,input logic Rst_n ,input logic [18:0] data_o ,output logic [6:0] hex1 ,output logic [6:0] hex2 ,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,FUSHU = 4'd11;
parameter MAX20us = 10'd1000;logic [9:0] cnt_20us;
logic [7:0] sel_r;
logic [3:0] number;
logic [6:0] seg_r;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) beginif (!Rst_n) begincnt_20us <= 10'd0;endelse if (cnt_20us == MAX20us - 1'd1) begincnt_20us <= 10'd0;endelse begincnt_20us <= cnt_20us + 1'd1;end
end// 单个信号sel_r位拼接约束
always_ff @(posedge Clk or negedge Rst_n) beginif (!Rst_n) beginsel_r <= 8'b11_11_11_10;endelse if (cnt_20us == MAX20us - 1'd1) beginsel_r <= {sel_r[6:0], sel_r[7]};endelse beginsel_r <= sel_r;end
end// 拿到数字
always_comb begincase (sel_r)8'b11_11_11_10: number = NOTION ;8'b11_11_11_01: number = data_o / 10_0000 ;8'b11_11_10_11: number = (data_o % 10_0000) / 1_0000 ;8'b11_11_01_11: number = ((data_o % 10_0000) % 1_0000) / 1000 ;8'b11_10_11_11: number = FUSHU ;8'b11_01_11_11: number = (((data_o % 10_0000) % 1_0000) % 1000) / 100 ;8'b10_11_11_11: number = ((((data_o % 10_0000) % 1_0000) % 1000) % 100) / 10;8'b01_11_11_11: number = ((((data_o % 10_0000) % 1_0000) % 1000) % 100) % 10;default: number = 4'd0 ;endcase
end// 通过数字解析出seg值
always_comb begincase (number)4'd0 : seg_r = 7'b100_0000;4'd1 : seg_r = 7'b111_1001;4'd2 : seg_r = 7'b010_0100;4'd3 : seg_r = 7'b011_0000;4'd4 : seg_r = 7'b001_1001;4'd5 : seg_r = 7'b001_0010;4'd6 : seg_r = 7'b000_0010;4'd7 : seg_r = 7'b111_1000;4'd8 : seg_r = 7'b000_0000;4'd9 : seg_r = 7'b001_0000;NOTION : seg_r = 7'b111_1111;FUSHU : seg_r = 7'b011_1111;default : seg_r = 7'b111_1111;endcase
end// 将seg值分配到对应的hex寄存器
always_comb beginhex1_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;case (sel_r)8'b11_11_11_10: hex1_r = seg_r;8'b11_11_11_01: hex2_r = seg_r;8'b11_11_10_11: hex3_r = seg_r;8'b11_11_01_11: hex4_r = seg_r;8'b11_10_11_11: hex5_r = seg_r;8'b11_01_11_11: hex6_r = seg_r;8'b10_11_11_11: hex7_r = seg_r;8'b01_11_11_11: hex8_r = seg_r;default: ; endcase
endassign 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
4. 蜂鸣器控制
蜂鸣器控制模块会在检测到障碍物距离过近时发出警告声。
代码片段示例:
beepled.sv
module beepled (input logic Clk,input logic Rst_n,input logic [18:0] data_o,output logic beep,output logic [3:0] led
);parameter MAX1S = 26'd2500_0000;
parameter MAX1_2S = 26'd1250_0000;
logic [25:0] cnt1s;
logic [25:0] cnt1_2s;
logic [3:0] led_r;
logic beep_r;/设计两个计数器,用于响不同的频率蜂鸣器///
//1s计数器
always_ff @(posedge Clk or negedge Rst_n) beginif (!Rst_n) begincnt1s <= 26'd0;end else if (cnt1s == MAX1S - 1) begincnt1s <= 26'd0;end else begincnt1s <= cnt1s + 1;end
end//0.5s计数器
always_ff @(posedge Clk or negedge Rst_n) beginif (!Rst_n) begincnt1_2s <= 26'd0;end else if (cnt1s == MAX1_2S - 1) begincnt1_2s <= 26'd0;end else begincnt1_2s <= cnt1_2s + 1;end
end
/设计两个计数器,用于响不同的频率蜂鸣器/////led灯 当距离小于20cm时,led灯亮!!!
always_ff @(posedge Clk or negedge Rst_n) beginif (!Rst_n) beginled_r <= 4'b0000;end else if(data_o/1000 <= 20) beginled_r <= 4'b1111;end else beginled_r <= 4'b0000;end
end//蜂鸣器 当距离小于20cm时,蜂鸣器微响 当距离小于10cm时,蜂鸣器狂响!!!
always_ff @(posedge Clk or negedge Rst_n) beginif(!Rst_n) beginbeep_r <= 1'b0;end else if (data_o/1000 > 20) beginbeep_r <= 1'b0;end else if (data_o/1000 <= 20) beginif (cnt1s == MAX1S - 1) beginbeep_r <= ~beep_r;end else if (data_o/1000 <= 10 && cnt1s == MAX1_2S - 1) beginbeep_r <= ~beep_r;end else beginbeep_r <= beep_r;endend else beginbeep_r <= 1'b0;end
endassign beep = beep_r;
assign led = led_r;
endmodule
五、实验效果
- 数码管显示对应的测量距离
- 当距离小于20cm时LED点亮,当时蜂鸣器微响
- 当距离小于10cm时LED点亮,当时蜂鸣器狂响
展示视频
实验-按键-图片-名称-动态条纹
六、项目总结
经验与收获
- 跨学科知识整合:通过倒车雷达项目,我学习了电子工程、编程和机械工程的基础知识,实现了跨学科知识的整合。
- 硬件操作经验:在与HC-SR04超声波传感器和DE2-115开发板的实际操作中,我获得了宝贵的硬件操作经验。
- 编程技能提升:编写控制逻辑和用户界面代码的过程中,我的编程技能得到了显著提升。
- 问题解决能力:在项目实施过程中遇到的各种技术难题,锻炼了我的问题解决能力。
优点与改进之处
-
优点:
- 实用性:倒车雷达是一个实用的项目,可以直接应用于汽车安全领域。
- 教育性:项目提供了学习和实践电子工程和编程的机会。
- 模块化设计:项目的各个部分(传感器驱动、显示、蜂鸣器控制)相对独立,便于理解和维护。
-
改进之处:
- 精确度:在某些情况下,超声波传感器的测量精确度可能受到环境因素的影响,需要进一步优化算法。
- 用户界面:当前的用户界面可能还有改进空间,例如增加图形界面或更直观的指示灯。
- 稳定性:系统在长时间运行或高负载下的稳定性需要进一步测试和改进。
扩展方向与改进思路
- 多传感器融合:可以考虑集成多种类型的传感器(如红外、激光雷达等),以提供更全面的障碍物检测。
- 智能控制:将倒车雷达与车辆的自动控制系统相结合,实现更智能的自动停车功能。
- 移动应用集成:开发移动应用程序,通过蓝牙或Wi-Fi与倒车雷达系统通信,提供远程监控和控制。
- 环境适应性:增强系统对不同环境(如雨天、雾天)的适应性,确保在各种条件下都能稳定工作。
- 能耗优化:优化系统设计,降低能耗,延长电池寿命,特别是在便携式或移动应用中。
- 用户定制:提供用户定制选项,允许用户根据自己的需求调整系统设置,如距离阈值、声音频率等。
通过这个项目,我不仅获得了宝贵的实践经验,还为未来的技术发展和创新打下了坚实的基础。随着技术的不断进步,我期待在未来能够实现更多创新和改进。