FPGA实战:用Verilog和Quartus II从零搭建出租车计费器(附完整代码)

FPGA实战:用Verilog和Quartus II从零搭建出租车计费器(附完整代码) FPGA实战从零构建智能出租车计费系统的完整指南1. 项目概述与设计思路出租车计费系统是FPGA学习的绝佳实践项目它涵盖了数字电路设计的多个核心概念。这个项目不仅能帮助初学者掌握Verilog HDL语言还能理解如何将现实世界的需求转化为硬件逻辑。在设计之初我们需要明确几个关键功能点基础计费功能包括起步价和里程单价计算时间计费模块处理等待时间的费用计算显示系统实时显示费用、里程和等待时间模式切换允许司机调整计费参数硬件架构选择方面我们采用模块化设计思想将系统划分为以下核心组件模块名称功能描述关键特性分频模块提供系统所需的各种时钟信号可配置分频系数消抖模块消除按键机械抖动10ms消抖周期控制模块系统状态管理与模式切换有限状态机实现计费模块核心计费逻辑支持起步价和里程单价设置显示驱动模块控制数码管显示动态扫描显示速度测量模块通过脉冲信号计算车速1Hz门限信号测量提示模块化设计是FPGA开发的核心思想每个功能模块应该保持高内聚低耦合便于单独测试和维护。2. 开发环境搭建与基础配置2.1 Quartus II环境准备首先需要安装Intel Quartus Prime开发环境本文以18.1版本为例。安装完成后建议进行以下基础配置创建新项目时选择正确的FPGA器件型号根据实际开发板选择设置默认语言为Verilog HDL配置仿真工具如ModelSim# 示例Quartus命令行编译指令 quartus_sh --flow compile taxi quartus_pgm -c USB-Blaster -m JTAG -o p;output_files/taxi.sof2.2 工程目录结构合理的目录结构能显著提高开发效率/taxi_project ├── /rtl # Verilog源代码 │ ├── taxi_top.v # 顶层模块 │ ├── div_clk.v # 分频模块 │ └── ... # 其他模块 ├── /sim # 仿真文件 ├── /constraints # 引脚约束文件 └── /doc # 设计文档2.3 关键引脚分配根据硬件连接情况需要在Quartus中正确分配引脚。典型配置如下# 示例引脚约束文件片段 set_location_assignment PIN_B14 -to clk_50M set_location_assignment PIN_A13 -to reset set_location_assignment PIN_B13 -to start set_location_assignment PIN_A12 -to key3. 核心模块实现详解3.1 分频模块设计系统需要多种频率的时钟信号1Hz用于时间和里程计数500Hz数码管扫描频率1000Hz按键消抖采样频率module div_clk(clk, fs, cko); input clk; // 50MHz系统时钟 input [31:0] fs; // 分频系数 output cko; // 分频输出 reg cko; parameter N 50_000_000; reg [31:0] ACC; always (posedge clk) begin if(ACC N/2-1) ACC ACC fs; else begin ACC 0; cko !cko; end end endmodule3.2 按键消抖模块机械按键存在5-10ms的抖动期必须通过消抖处理module key_shake(clk, key_in, key_out); input clk; // 1000Hz时钟 input key_in; // 物理按键输入 output key_out;// 消抖后输出 reg [6:0] cnt; reg key_out; always (posedge clk) begin if(!key_in) cnt cnt 1; else cnt 0; if(cnt 100) key_out 0; else key_out 1; end endmodule注意消抖时间设置为10ms100个1kHz周期这个值需要根据实际按键特性调整。3.3 里程计费模块里程计费逻辑需要考虑3公里内按起步价计费超过3公里按里程单价计费每公里脉冲数需要根据实际传感器调整module distancemokuai(clk, flag, reset, distance, distance_enable, module_Flag); input clk, flag, reset, module_Flag; output [7:0] distance; output distance_enable; reg [7:0] distance; reg [7:0] cnt; always (posedge clk or negedge reset) begin if(!reset) begin distance 8H00; cnt 0; end else if((flag1b0) (module_Flag1b1)) begin if(cnt 8d50) begin // 假设50个脉冲1公里 cnt 0; if(distance[3:0] 4B1001) begin distance[3:0] 4B0000; if(distance[7:4] 4B1001) distance[7:4] 4B0000; else distance[7:4] distance[7:4] 1; end else distance[3:0] distance[3:0] 1; end else cnt cnt 1; end end assign distance_enable ((distance[7:0] 8H02) (cnt 8d50)) ? 1b1 : 1b0; endmodule4. 系统集成与调试技巧4.1 顶层模块设计顶层模块负责实例化所有子模块并实现互连module taxi( input clk_50M, reset, start, pluse, key, set, output [7:0] sel, output a,b,c,d,e,f,g,p, output led ); // 内部信号声明 wire [7:0] distance, s, m, fee; wire [3:0] rprice; // ...其他信号声明 // 模块实例化 div_clk u0(.clk(clk_50M), .fs(1), .cko(hz)); div_clk u1(.clk(clk_50M), .fs(500), .cko(hz1)); // ...其他模块实例化 // 控制信号连接 assign select_clk flag ? time_enable : distance_enable; endmodule4.2 常见调试问题解决数码管显示异常检查位选和段选信号极性确认扫描频率在300-1000Hz之间测量各段LED的驱动电流按键响应不稳定增加消抖时间检查硬件上拉电阻确认时钟信号质量计费计算错误仿真测试各子模块检查数值溢出情况验证时钟分频精度4.3 功能扩展建议增加EEPROM存储保存计费参数断电不丢失添加无线通信模块支持远程计价器管理实现语音提示功能提升用户体验加入GPS模块实现基于位置的计费策略5. 性能优化与进阶技巧5.1 资源优化策略FPGA资源有限需要优化设计共享分频器多个模块使用同一分频器输出状态编码优化使用独热码或格雷码流水线设计提高关键路径时序// 优化后的分频器示例 module opt_div_clk(input clk, output reg clk_1k, clk_500, clk_1); reg [15:0] cnt; always (posedge clk) begin cnt cnt 1; clk_1k cnt[5]; // 50MHz/64 ≈ 781kHz clk_500 cnt[6]; // ≈390kHz clk_1 cnt[15:0]; // 约763Hz end endmodule5.2 时序约束与验证合理的时序约束确保设计稳定# 示例SDC约束文件 create_clock -name clk_50M -period 20 [get_ports clk_50M] set_input_delay -clock clk_50M 2 [all_inputs] set_output_delay -clock clk_50M 2 [all_outputs]5.3 高级调试技术SignalTap逻辑分析仪实时捕获内部信号虚拟JTAG通过Quartus与设计交互自定义测试模式通过按键组合进入// SignalTap调试代码片段 initial begin $display(Starting simulation at %0t, $time); if($test$plusargs(debug)) begin $display(Debug mode enabled); // 启用调试功能 end end6. 完整系统测试方案6.1 仿真测试流程模块级测试验证每个子模块功能集成测试检查模块间接口系统测试完整功能验证// 测试平台示例 module taxi_tb; reg clk, reset, start; // ...其他输入信号 taxi dut (.*); // 实例化被测设计 initial begin clk 0; forever #10 clk ~clk; // 50MHz时钟 end initial begin reset 0; #100 reset 1; // 添加测试用例 end endmodule6.2 硬件测试步骤电源检查确认各电压正常时钟验证测量时钟信号质量功能测试按场景逐一验证压力测试长时间运行观察稳定性6.3 典型测试用例测试场景输入条件预期结果起步价计费里程3km显示起步价里程计费里程3km显示起步价超里程费用时间计费等待2分钟显示等待费用模式切换按下模式键正确切换显示模式参数设置在设置模式下调整新参数生效7. 项目总结与进阶方向完成这个出租车计费系统项目后你应该已经掌握了FPGA开发的基本流程。在实际部署时还需要考虑以下因素环境适应性不同温度下的稳定性电源管理低功耗设计EMC设计减少电磁干扰生产测试批量生产的测试方案对于想进一步深入的学习者建议研究AXI总线协议实现更复杂的系统集成学习使用HLS高层次综合工具加速开发探索基于FPGA的AI加速器设计参与开源FPGA项目积累实战经验