告别示波器!用EGO1 FPGA的XADC和VGA接口,搭建一个低成本的心电波形显示器(附完整Verilog代码)
基于EGO1 FPGA的心电波形可视化系统设计与实现在生物医学工程和电子工程的教学实验中心电信号采集与可视化是常见的实践项目。传统方案通常依赖昂贵的示波器或专业数据采集设备而本文将展示如何利用EGO1 FPGA开发板和普通VGA显示器构建一套低成本的心电波形显示系统。这个方案不仅成本低廉还能让学生深入理解信号采集、处理和显示的全流程。1. 系统架构与核心组件本系统的核心在于利用Xilinx FPGA内置的XADC模块进行信号采集通过双口RAM实现数据缓冲最终在VGA显示器上实时呈现心电波形。整个系统由三个关键部分组成信号采集模块XADC负责将模拟心电信号转换为数字量数据处理模块双口RAM作为数据缓冲区解决采样率与显示速率的匹配问题显示输出模块VGA控制器将处理后的数据转换为显示器可识别的时序信号系统工作流程如下心电信号经过分压电路适配到XADC的输入范围(0-1V)XADC以200Hz的采样率将模拟信号转换为12位数字量采样数据写入双口RAM的A端口VGA控制器从RAM的B端口读取数据并映射到屏幕的相应像素位置2. XADC配置与信号采集XADC(Xilinx Analog-to-Digital Converter)是7系列FPGA内置的模拟混合信号模块具有12位精度和最高1MSPS的转换速率。在本应用中我们将其配置为单端输入模式使用VAUXP2通道采集心电信号。2.1 XADC接口配置XADC模块通过DRP(Dynamic Reconfiguration Port)接口与FPGA逻辑交互。关键信号包括信号名称方向描述daddr_in输入DRP地址总线用于选择读取的通道den_in输入DRP使能信号控制数据读取时机drdy_out输出数据就绪指示信号do_out输出转换结果数据总线eoc_out输出转换完成脉冲信号配置XADC时需要注意将vauxn2引脚接地以实现单端输入模式设置daddr_in为通道地址(心电信号对应h12)使用eoc_out信号触发DRP读取操作xadc_wiz_0 u_xadc_wiz_0 ( .di_in(16b0), .daddr_in({2b0,CHANNEL_OUT}), .den_in(EOC_OUT), .dwe_in(1b0), .drdy_out(DRDY_OUT), .do_out(DO_OUT), .dclk_in(clock), .reset_in(reset), .vp_in(), .vn_in(), .vauxp2(IN1), .vauxn2(1d0), .channel_out(CHANNEL_OUT), .eoc_out(EOC_OUT) );2.2 采样率适配心电信号频率通常在0.5Hz-100Hz之间而XADC支持最高1MSPS的采样率。直接使用最高采样率会导致单个屏幕显示的时间窗口过短波形在水平方向上过度压缩RAM存储空间快速耗尽解决方案是采用200Hz的采样率这样对于1Hz的心电信号一个周期用200个点表示640×480分辨率的屏幕可显示约3个完整周期RAM深度设置为640刚好匹配屏幕水平分辨率实现方法是通过分频电路将系统时钟转换为200Hz作为RAM A端口的写入时钟module count( input clock, input reset, output reg clk ); reg [27:0] cnt_200Hz; always(posedge clock)begin if(reset)begin cnt_200Hz 28d0; clk 1d0; end else begin if (cnt_200Hz 28d249999)begin cnt_200Hz 28d0; clk ~clk; end else cnt_200Hz cnt_200Hz 1b1; end end endmodule3. 双口RAM的数据缓冲设计双口RAM是本系统的关键组件它解决了两个核心问题桥接不同时钟域200Hz采样时钟和25MHz VGA时钟实现数据速率匹配低频写入高频读取3.1 RAM配置参数参数值说明数据宽度12位匹配XADC输出精度深度640对应VGA水平分辨率端口A时钟200Hz采样时钟端口B时钟25MHzVGA像素时钟在FPGA中可以通过IP核生成器配置这样的双口RAM。关键配置如下端口A只写端口B只读使用独立的时钟和地址总线不启用复位功能以简化设计3.2 数据写入逻辑RAM的A端口负责接收XADC的采样数据。写入时需要注意仅在DRDY_OUT有效且通道正确时捕获数据地址自动递增达到639后回绕到0只保留DO_OUT的高12位有效数据always(posedge clock)begin if(reset) ram_data_a 1d0; else begin if(DRDY_OUT (CHANNEL_OUT 5h12)) ram_data_a DO_OUT[15:4]; else ram_data_a ram_data_a; end end always(posedge ram_clk)begin if(reset) ram_addr_a 1d0; else begin if(ram_addr_a 10d639) ram_addr_a 1d0; else ram_addr_a ram_addr_a 1d1; end end3.3 数据读取与缩放RAM的B端口输出需要经过两个处理步骤数据缩放将12位ADC值(0-4095)映射到480行显示范围坐标转换将电压值转换为屏幕Y坐标并考虑坐标系方向简单的实现方法是除以比例因子本设计采用除以10更优化的方案是使用移位操作assign data_xadc doutb_1 / 10; // 简单实现 // 更优方案assign data_xadc doutb_1[11:4]; // 取高8位4. VGA显示控制器实现VGA控制器负责生成符合VGA标准的时序信号并将RAM中的数据映射到屏幕相应位置。4.1 VGA时序参数标准640×48060Hz的VGA时序参数如下参数行时序(像素)场时序(行)同步脉冲962后沿4833有效显示640480前沿1610总计800525对应的Verilog实现需要两个计数器水平计数器0-799循环计数垂直计数器每完成一行(800像素)递增一次// 行计数器 always (posedge vga_clk) begin if (sys_rst_n) cnt_h 10d0; else begin if(cnt_h H_TOTAL - 1b1) cnt_h cnt_h 1b1; else cnt_h 10d0; end end // 场计数器 always (posedge vga_clk) begin if (sys_rst_n) cnt_v 10d0; else if(cnt_h H_TOTAL - 1b1) begin if(cnt_v V_TOTAL - 1b1) cnt_v cnt_v 1b1; else cnt_v 10d0; end end4.2 波形绘制算法波形显示的核心是将RAM中的数据转换为屏幕上的像素点。本设计采用以下策略当前X坐标对应RAM地址数据值决定Y坐标位置在数据点上下各扩展2个像素形成5像素粗的波形线always (posedge vga_clk) begin if (sys_rst_n) pixel_data BLACK; else begin if(((10d480-data_xadc) pixel_ypos - 2d2) ((10d480-data_xadc) pixel_ypos 2d2)) pixel_data RED; else pixel_data BLACK; end end4.3 时钟生成VGA标准要求25.175MHz的像素时钟实际应用中25MHz也能正常工作。本设计使用FPGA的PLL IP核生成精确的时钟输入系统时钟如100MHz通过PLL分频得到25MHz VGA时钟确保时钟稳定后再启用显示逻辑5. 系统集成与优化建议将各模块集成后完整的系统框图如下心电信号 → 分压电路 → XADC → 双口RAM → VGA控制器 → 显示器 ↑ ↑ ↑ 保护电路 采样时钟 像素时钟5.1 信号调理电路实际应用中心电信号需要经过适当调理才能接入XADC分压电路使用三个10kΩ电阻将信号幅度限制在0-1V范围内滤波电路添加低通滤波器消除高频噪声保护电路防止过压损坏FPGA引脚5.2 性能优化方向当前设计有几个可以改进的方面数据缩放算法用移位代替除法节省资源// 替代 data_xadc doutb_1 / 10; assign data_xadc doutb_1 3; // 近似除以8波形插值在点之间绘制线段而非离散点网格背景添加参考网格提高可读性多通道支持同时显示多个生物电信号测量功能添加心率计算等实用功能5.3 调试技巧开发过程中可能会遇到以下问题及解决方法问题现象可能原因解决方案无波形显示XADC配置错误检查通道选择和DRP地址波形闪烁RAM读写冲突确保读写地址不重叠垂直线条数据缩放不当调整缩放算法或分频比水平偏移时序不同步检查VGA时序参数6. 完整系统代码解析顶层模块整合了所有子模块主要完成以下功能实例化XADC、RAM、时钟生成和VGA控制器连接各模块间的数据和控制信号处理全局复位和时钟域交叉问题module comprehensive_lib( input clock, // 系统时钟 input reset, // 复位信号 input IN1, // 心电信号输入 output vga_hs, // VGA行同步 output vga_vs, // VGA场同步 output [11:0] vga_rgb // VGA颜色输出 ); // 信号声明 wire [15:0] DO_OUT; wire [4:0] CHANNEL_OUT; wire EOC_OUT, DRDY_OUT; wire vga_clk, locked, ram_clk; wire [11:0] doutb_1; wire [9:0] data_xadc; wire [11:0] pixel_data; wire [9:0] pixel_xpos, pixel_ypos; // XADC实例化 xadc_wiz_0 u_xadc_wiz_0 ( .di_in(16b0), .daddr_in({2b0,CHANNEL_OUT}), .den_in(EOC_OUT), .dwe_in(1b0), .drdy_out(DRDY_OUT), .do_out(DO_OUT), .dclk_in(clock), .reset_in(reset), .vp_in(), .vn_in(), .vauxp2(IN1), .vauxn2(1d0), .channel_out(CHANNEL_OUT), .eoc_out(EOC_OUT) ); // PLL时钟生成 ip_pll u_ip_pll( .vga_clk(vga_clk), .reset(reset), .locked(locked), .clock(clock) ); // 双口RAM实例化 ram_12x640d u_ram_12x640d ( .clka(ram_clk), .wea(1b1), .addra(ram_addr_a), .dina(ram_data_a), .clkb(vga_clk), .addrb(ram_addr_b), .doutb(doutb_1) ); // 200Hz分频器 count u_count( .clock(clock), .reset(reset), .clk(ram_clk) ); // VGA显示模块 vga_show u_vga_show( .vga_clk(vga_clk), .sys_rst_n(reset), .data_xadc(data_xadc), .pixel_xpos(pixel_xpos), .pixel_ypos(pixel_ypos), .pixel_data(pixel_data) ); // VGA控制器 vga_control u_vga_control( .vga_clk(vga_clk), .sys_rst_n(!locked), .vga_hs(vga_hs), .vga_vs(vga_vs), .vga_rgb(vga_rgb), .pixel_data(pixel_data), .pixel_xpos(pixel_xpos), .pixel_ypos(pixel_ypos) ); assign data_xadc doutb_1 / 10; assign ram_addr_b pixel_xpos 1b1; // RAM写入控制逻辑 reg [9:0] ram_addr_a; reg [11:0] ram_data_a; always(posedge clock)begin if(reset) ram_data_a 1d0; else begin if(DRDY_OUT (CHANNEL_OUT 5h12)) ram_data_a DO_OUT[15:4]; end end always(posedge ram_clk)begin if(reset) ram_addr_a 1d0; else begin if(ram_addr_a 10d639) ram_addr_a 1d0; else ram_addr_a ram_addr_a 1d1; end end endmodule7. 实际应用与教学价值这套基于EGO1 FPGA的心电显示系统在实际教学和项目中具有多重价值成本效益总成本不足千元远低于专业示波器教育意义完整覆盖信号链的各个环节模拟信号调理数据采集与转换数字信号处理图形显示技术扩展性强可轻松修改为其他生物电信号采集系统实践性强学生可以亲手构建完整系统而非仅使用现成设备在实验室环境中这套系统可以帮助学生理解心电信号的特性与采集要求掌握FPGA在实时系统中的应用学习跨时钟域设计技巧实践数字信号处理基础算法