FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

FPGA毕业设计:基于RISC-V软核的智能传感器数据采集系统

二牛学FPGA二牛学FPGA
技术分享
7小时前
0
0
2

Quick Start

  • 步骤1:在Vivado中创建新工程,选择xc7a35tcsg324-1(Arty A7-35T示例)作为目标器件。
  • 步骤2:从GitHub克隆VexRiscv(https://github.com/SpinalHDL/VexRiscv)或使用预编译的bitstream,将其作为软核集成到工程中。
  • 步骤3:添加传感器接口模块(如I2C或SPI控制器),并连接至VexRiscv的AXI4-Lite总线。
  • 步骤4:编写顶层文件,例化软核、传感器接口和UART调试模块,分配时钟(100MHz)和复位。
  • 步骤5:运行综合(Synthesis)和实现(Implementation),确认无严重时序违例。
  • 步骤6:生成bitstream并下载到FPGA板卡,通过串口终端(115200 baud)观察传感器数据输出。
  • 步骤7:预期结果:系统上电后,UART每秒输出一次“Sensor: [温度值] °C, [湿度值] %”格式的数据。
  • 步骤8:若未输出,检查串口连接、时钟频率和传感器供电;使用ILA抓取AXI总线信号确认软核是否启动。

前置条件与环境

项目/推荐值说明替代方案
器件/板卡Xilinx Artix-7 (xc7a35tcsg324-1) 或更高Altera Cyclone V (5CEBA4F23C7N) 需调整约束
EDA版本Vivado 2022.2 或更高Vivado 2021.1 需注意IP核兼容性
仿真器Vivado Simulator 或 ModelSim SE-64 2020.1QuestaSim 2021.1
时钟/复位100MHz 单端时钟输入,低电平有效复位50MHz 也可,但需调整IP核配置
接口依赖UART (115200, 8N1) 用于调试输出JTAG-USB桥接(如Digilent Adept)
约束文件XDC文件:定义时钟周期10ns,复位管脚,UART管脚手动创建或从板卡厂商获取模板
传感器I2C温湿度传感器(如SHT30)或SPI加速度计(如ADXL345)模拟传感器需外接ADC

目标与验收标准

  • 功能点:系统通过I2C/SPI接口读取传感器数据,经软核处理后通过UART输出;支持每秒至少一次采样率。
  • 性能指标:软核主频≥50MHz(示例配置),UART波特率115200无误码;I2C时钟频率100kHz。
  • 资源占用:LUT ≤ 2000,FF ≤ 1500,BRAM ≤ 4块(以VexRiscv最小配置为例,典型值约1800 LUT,1200 FF)。
  • 验收方式:上电后串口终端每秒输出传感器数据,格式为“Sensor: [value1], [value2]”;ILA波形显示I2C/SPI事务正常完成。
  • 边界条件:传感器未连接时,系统应输出“Sensor: Error”或保持最后有效值;时钟频率偏差±5%内仍能工作。

实施步骤

阶段一:工程结构与软核集成

  • 创建Vivado工程,添加RTL源文件:顶层文件(top.v)、软核包装器(vexriscv_wrapper.v)、传感器接口模块(sensor_if.v)。
  • 使用VexRiscv的预编译bitstream或通过SpinalHDL生成RTL:配置为最小RV32IM配置,包含AXI4-Lite主接口和中断控制器。
  • 在顶层中例化软核:连接时钟、复位、AXI总线;将传感器接口模块挂载到AXI从端口(地址映射:0x40000000-0x40000FFF)。
  • 常见坑:软核复位时序要求高,确保复位信号至少保持10个时钟周期低电平;使用同步复位释放逻辑。
  • 验收点:综合后检查资源报告,确认软核占用与预期一致;仿真中软核应能完成启动并访问外设。

阶段二:传感器接口模块设计

// sensor_if.v - I2C 温湿度传感器接口 (SHT30)
module sensor_if (
    input  wire        clk,
    input  wire        rst_n,
    // AXI4-Lite 从接口
    input  wire [31:0] s_axi_awaddr,
    input  wire        s_axi_awvalid,
    output wire        s_axi_awready,
    input  wire [31:0] s_axi_wdata,
    input  wire        s_axi_wvalid,
    output wire        s_axi_wready,
    output wire [1:0]  s_axi_bresp,
    output wire        s_axi_bvalid,
    input  wire        s_axi_bready,
    input  wire [31:0] s_axi_araddr,
    input  wire        s_axi_arvalid,
    output wire        s_axi_arready,
    output wire [31:0] s_axi_rdata,
    output wire [1:0]  s_axi_rresp,
    output wire        s_axi_rvalid,
    input  wire        s_axi_rready,
    // I2C 接口 (外部引脚)
    inout  wire        i2c_sda,
    output wire        i2c_scl
);

// 内部寄存器
reg [31:0] status_reg;
reg [31:0] data_reg;

// AXI 写事务处理
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        status_reg <= 32'h0;
    end else if (s_axi_awvalid && s_axi_wvalid) begin
        if (s_axi_awaddr[3:0] == 4'h0) begin
            status_reg <= s_axi_wdata; // 写控制寄存器
        end
    end
end

// I2C 控制器实例化 (省略具体实现)
i2c_master #(.CLK_FREQ(100_000_000), .I2C_FREQ(100_000)) u_i2c (
    .clk(clk),
    .rst_n(rst_n),
    .start(status_reg[0]),
    .addr(8'h44),   // SHT30 地址
    .data_in(16'h2C06), // 测量命令
    .data_out(data_reg[15:0]),
    .done(done),
    .sda(i2c_sda),
    .scl(i2c_scl)
);

// AXI 读事务处理
assign s_axi_rdata = (s_axi_araddr[3:0] == 4'h0) ? status_reg :
                     (s_axi_araddr[3:0] == 4'h4) ? data_reg : 32'h0;

endmodule

逐行说明

  • 第1行:模块声明,定义I2C传感器接口,端口包括时钟、复位、AXI4-Lite从接口和I2C引脚。
  • 第2-5行:AXI4-Lite写地址通道信号,用于软核写入控制寄存器。
  • 第6-9行:AXI4-Lite写数据通道信号,携带写入的数据。
  • 第10-12行:写响应通道,返回事务状态。
  • 第13-17行:AXI4-Lite读地址和读数据通道,用于软核读取传感器数据。
  • 第18-19行:I2C总线信号,sda为双向,scl为输出。
  • 第22-23行:内部寄存器,status_reg控制I2C启动,data_reg存储读取结果。
  • 第26-33行:写事务逻辑,当软核写入地址0x0时,更新status_reg以触发I2C测量。
  • 第36-44行:I2C主控制器实例化,配置时钟频率100MHz,I2C速率100kHz;发送SHT30地址0x44和测量命令0x2C06。
  • 第47-49行:读事务逻辑,根据地址返回status_reg或data_reg,供软核读取。
  • 常见坑:I2C双向信号sda需在顶层使用三态缓冲器;AXI地址对齐要求低两位为0,否则可能产生错误响应。

阶段三:时序约束与验证

# top.xdc - 时序约束
create_clock -period 10.000 -name sys_clk [get_ports clk]
set_input_jitter sys_clk 0.100

# 复位约束
set_property PACKAGE_PIN E3 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]

# UART 管脚约束
set_property PACKAGE_PIN D10 [get_ports uart_tx]
set_property IOSTANDARD LVCMOS33 [get_ports uart_tx]

# I2C 管脚约束
set_property PACKAGE_PIN G13 [get_ports i2c_sda]
set_property PACKAGE_PIN G14 [get_ports i2c_scl]
set_property IOSTANDARD LVCMOS33 [get_ports i2c_sda]
set_property IOSTANDARD LVCMOS33 [get_ports i2c_scl]

# 伪路径约束(跨时钟域)
set_false_path -from [get_clocks sys_clk] -to [get_clocks jtag_clk]

逐行说明

  • 第1行:创建主时钟,周期10ns对应100MHz,命名sys_clk。
  • 第2行:设置输入抖动为100ps,用于时序分析中的时钟不确定性。
  • 第4-5行:复位引脚约束,指定封装位置和I/O标准。
  • 第7-8行:UART发送引脚约束,用于调试输出。
  • 第10-13行:I2C引脚约束,sda和scl都使用LVCMOS33标准。
  • 第15行:伪路径约束,忽略sys_clk到jtag_clk的时序路径,因为JTAG时钟与系统时钟异步。
  • 常见坑:I2C引脚需设置为开漏输出,在XDC中无法直接配置,需在RTL中使用三态门实现;复位引脚若未约束,可能被优化导致功能异常。

阶段四:软件编写与上板调试

// main.c - 软核固件 (RISC-V)
#include <stdint.h>

#define SENSOR_BASE 0x40000000
#define STATUS_REG  (*(volatile uint32_t *)(SENSOR_BASE + 0x0))
#define DATA_REG    (*(volatile uint32_t *)(SENSOR_BASE + 0x4))

void uart_send_str(const char *str) {
    while (*str) {
        // 假设UART寄存器地址为0x80000000
        *(volatile uint32_t *)0x80000000 = *str++;
    }
}

int main() {
    uint32_t status, data;
    while (1) {
        // 启动I2C测量
        STATUS_REG = 0x1;  // 写控制寄存器,触发测量
        // 等待完成(轮询或中断)
        do {
            status = STATUS_REG;
        } while (!(status & 0x2)); // 检查done位
        // 读取数据
        data = DATA_REG;
        // 通过UART发送
        uart_send_str("Sensor: ");
        // 发送温度值(示例:data高16位为温度)
        // 实际需转换为ASCII
        uart_send_str("

");
        // 延时1秒
        for (volatile int i = 0; i < 1000000; i++);
    }
    return 0;
}

逐行说明

  • 第1行:包含标准整数类型头文件。
  • 第3-5行:定义传感器模块基地址和寄存器偏移,使用volatile防止编译器优化。
  • 第7-11行:UART发送字符串函数,逐个字符写入UART发送寄存器。
  • 第14行:主函数入口。
  • 第16行:无限循环,持续采集传感器数据。
  • 第18行:向控制寄存器写0x1,触发I2C测量。
  • 第20-22行:轮询状态寄存器,等待done位(bit1)置位。
  • 第24行:读取数据寄存器。
  • 第26-29行:通过UART发送字符串和数据(此处简化,实际需转换整数为ASCII)。
  • 第31行:软件延时约1秒(假设主频50MHz,循环100万次)。
  • 常见坑:轮询方式会阻塞CPU,可改用中断提高效率;延时循环依赖主频,若主频变化需调整计数值。

原理与设计说明

为什么选择RISC-V软核而非硬核或纯FSM?RISC-V软核(如VexRiscv)提供了可编程灵活性,允许在FPGA上运行C代码,降低传感器协议解析的复杂度,同时支持中断和任务调度,适合毕业设计展示嵌入式系统能力。相比ARM Cortex-M硬核,RISC-V软核开源、可定制,且资源占用低(最小配置约1800 LUT),适合资源受限的FPGA。

关键trade-off:资源 vs Fmax。VexRiscv提供多种配置(最小、标准、高性能),最小配置减少LUT但降低主频(约50-80MHz),标准配置增加流水线级数提升Fmax(可达100MHz+)但多消耗约500 LUT。本设计采用最小配置以降低资源占用,留出空间给传感器接口和调试逻辑。

吞吐 vs 延迟:I2C传感器采样率通常为1-10Hz,软核轮询方式延迟约1ms,满足需求;若需高吞吐(如音频),应使用DMA或硬件加速器,避免CPU干预。

易用性 vs 可移植性:使用AXI4-Lite总线接口使传感器模块可复用于其他RISC-V软核(如PicoRV32、SERV),但需注意地址映射和时序差异。VexRiscv的AXI接口兼容AMBA标准,便于未来升级。

验证与结果

指标测量值(示例)测量条件
Fmax (软核)72 MHzVivado 2022.2, Artix-7, 最小配置, 最差工艺角
LUT 占用1856含软核+传感器接口+UART
FF 占用1234同上
BRAM 占用3.5 块软核指令/数据存储器各1块,UART FIFO 0.5块
I2C 采样率1 Hz软件延时1秒
UART 输出115200 baud, 无错码串口终端捕获1000字节

波形特征:ILA捕获显示I2C事务时序正确,SCL频率100kHz,SDA数据在SCL低电平时变化;软核启动后约2ms完成初始化,随后每秒触发一次I2C测量。

故障排查 (Troubleshooting)

  • 现象:UART无输出 → 原因:软核未启动或时钟未使能 → 检查点:ILA抓取复位信号和时钟活动 → 修复:确保复位释放后至少10个周期,时钟频率正确。
  • 现象:I2C无响应 → 原因:传感器地址错误或I2C引脚未配置开漏 → 检查点:示波器测量SCL/SDA波形 → 修复:在顶层添加三态缓冲器,确认传感器供电。
  • 现象:数据全为0 → 原因:AXI读事务未正确完成 → 检查点:仿真中检查s_axi_arready和s_axi_rvalid时序 → 修复:确保读数据通道握手信号完整。
  • 现象:综合后时序违例 → 原因:软核时钟频率过高或约束不完整 → 检查点:查看时序报告中的最差路径 → 修复:降低时钟频率或启用retiming优化。
  • 现象:软核启动后卡死 → 原因:中断向量表未正确配置 → 检查点:检查软核启动代码中的trap处理 → 修复:在链接脚本中正确设置中断入口。
  • 现象:传感器数据错误 → 原因:I2C命令字节顺序错误 → 检查点:对比传感器数据手册的时序图 → 修复:调整data_in字节序(如SHT30需高字节在前)。
  • 现象:资源占用过高 → 原因:软核配置了不必要的功能 → 检查点:查看软核生成时的配置选项 → 修复:禁用FPU、调试模块或乘法器。
  • 现象:上电后I2C总线被拉低 → 原因:传感器初始化未完成或总线冲突 → 检查点:测量传感器供电和复位时序 → 修复:在软核启动后延时100ms再发起I2C通信。
  • 现象:UART输出乱码 → 原因:波特率不匹配或时钟频率偏差 → 检查点:用示波器测量UART引脚位宽 → 修复:调整UART IP核的分频系数。
  • 现象:ILA无法触发 → 原因:触发条件设置错误或采样深度不足 → 检查点:检查ILA探针连接和触发逻辑 → 修复:使用简单触发条件(如上升沿)并增加采样深度。

扩展与下一步

  • 参数化:将传感器类型、I2C地址、采样率等作为参数,通过软核的配置寄存器动态调整,提高通用性。
  • 带宽提升:改用SPI接口传感器(如ADXL345),支持更高采样率(可达1kHz),配合中断驱动减少CPU轮询开销。
  • 跨平台:将传感器接口模块迁移至Altera Cyclone V平台,使用Qsys集成软核(如Nios II),对比资源占用和性能。
  • 加入断言/覆盖:在仿真环境中添加SystemVerilog断言,验证I2C时序和AXI协议合规性;使用功能覆盖率收集传感器数据范围。
  • 形式验证:使用SymbiYosys对传感器接口模块进行形式验证,证明其满足AXI4-Lite协议规范。
  • 实时操作系统:在软核上运行FreeRTOS,实现多任务调度(如传感器采集、数据记录、网络通信),提升系统复杂度。

参考与信息来源

<
  • VexRiscv官方文档与GitHub仓库:https://github.com/SpinalHDL/VexRiscv
  • SHT30温湿度传感器数据手册(Sensirion)
  • Xilinx Vivado Design Suite User Guide (UG910)
  • AMBA AXI4-Lite Protocol Specification (ARM IHI 0022)
  • <
标签:
本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/40802.html
二牛学FPGA

二牛学FPGA

初级工程师
这家伙真懒,几个字都不愿写!
91819.24W3.99W3.67W
分享:
成电国芯FPGA赛事课即将上线
FPGA动态重配置在AI边缘设备中的2026年新应用:实施手册与设计指南
FPGA动态重配置在AI边缘设备中的2026年新应用:实施手册与设计指南上一篇
国产FPGA在工业以太网(EtherCAT)控制器中的替代方案:上手指南与实施手册(2026版)下一篇
国产FPGA在工业以太网(EtherCAT)控制器中的替代方案:上手指南与实施手册(2026版)
相关文章
总数:944
FPGA低功耗设计实施指南:时钟门控与电源门控工程实践

FPGA低功耗设计实施指南:时钟门控与电源门控工程实践

在FPGA系统设计中,功耗优化已成为与性能、面积同等重要的设计目标。总功…
技术分享
15天前
0
0
33
0
动手玩转FPGA:用OV5640摄像头打造实时边缘检测系统

动手玩转FPGA:用OV5640摄像头打造实时边缘检测系统

嘿,想不想亲手用FPGA做一个能“看见”边缘的视觉系统?在自动驾驶、安防…
技术分享
25天前
0
0
109
1
FPGA软核处理器与商用MPU选型实施指南:基于RISC-V的灵活性与性能权衡

FPGA软核处理器与商用MPU选型实施指南:基于RISC-V的灵活性与性能权衡

在嵌入式系统架构设计中,选择基于FPGA的软核处理器(如RISC-V)还…
技术分享
13天前
0
0
26
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容