news 2026/4/15 4:17:24

FPGA 通过 UART 通讯解析上位机数据包:三段式状态机实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FPGA 通过 UART 通讯解析上位机数据包:三段式状态机实战

实际项目开发中用到的代码,FPGA通过uart通讯解析上位机发送的数据包,并实现数据存储和调用,采用三段式状态机,Verilog语言。 数据包包含帧头、命令、数据长度、数据、16位的crc校验(会给出对应的多项式)、帧尾。 为了保证帧头和帧尾唯一性,使用了字符转义,并且在检测出帧头错误,校验错误,帧尾错误时会返回特定的指令给上位机,实现与PC端握手。 资料包含工程文件(可选quartus或Xilinx),代码(带注释),testbench,可运行仿真查看波形。

在实际项目开发里,FPGA 与上位机通过 UART 通讯实现数据交互是非常常见的需求。今天咱就唠唠如何用 Verilog 语言结合三段式状态机,让 FPGA 准确解析上位机发送的数据包,并完成数据存储和调用。

数据包结构剖析

咱们要解析的数据包包含这么几个部分:帧头、命令、数据长度、数据、16 位的 CRC 校验(对应的多项式会给出)以及帧尾。为了保证帧头和帧尾的唯一性,这里还用到了字符转义。

比如说,假设帧头定义为8'hAA,帧尾定义为8'hBB。一旦检测出帧头错误、校验错误或者帧尾错误,FPGA 就得返回特定指令给上位机,实现与 PC 端握手。

三段式状态机 Verilog 代码实现

状态定义

typedef enum reg [2:0] { IDLE = 3'b000, WAIT_HEADER = 3'b001, RECEIVE_CMD = 3'b010, RECEIVE_LEN = 3'b011, RECEIVE_DATA = 3'b100, RECEIVE_CRC = 3'b101, CHECK_CRC = 3'b110, WAIT_TAIL = 3'b111 } state_t;

这里我们定义了不同的状态,IDLE是初始空闲状态,等待接收数据。WAIT_HEADER用于等待帧头,后续每个状态对应数据包不同部分的接收和处理。

状态转移逻辑

always @(posedge clk or negedge rst_n) begin if (!rst_n) begin current_state <= IDLE; end else begin case (current_state) IDLE: begin if (uart_rx_valid) begin if (uart_rx_data == HEADER) begin current_state <= WAIT_HEADER; end end end WAIT_HEADER: begin if (uart_rx_valid) begin if (uart_rx_data == HEADER) begin current_state <= RECEIVE_CMD; end else begin current_state <= IDLE; end end end // 其他状态转移类似,这里省略部分代码 CHECK_CRC: begin if (crc_calculated == uart_rx_crc) begin current_state <= WAIT_TAIL; end else begin // 返回校验错误指令给上位机 send_error_cmd(CRC_ERROR); current_state <= IDLE; end end WAIT_TAIL: begin if (uart_rx_valid) begin if (uart_rx_data == TAIL) begin // 数据解析成功,存储数据 store_data(); current_state <= IDLE; end else begin // 返回帧尾错误指令给上位机 send_error_cmd(TAIL_ERROR); current_state <= IDLE; end end end endcase end end

在这段代码里,从IDLE状态开始,一旦检测到uartrxvalid信号有效且接收到正确的帧头,就转移到WAITHEADER状态进一步确认帧头。CHECKCRC状态下,比较计算出的 CRC 和接收到的 CRC,如果不一致就返回校验错误指令给上位机。WAIT_TAIL状态则检查帧尾是否正确,不正确同样返回错误指令。

数据存储和调用

reg [7:0] data_store [0:255]; reg data_index; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin data_index <= 0; end else if (current_state == RECEIVE_DATA) begin data_store[data_index] <= uart_rx_data; data_index <= data_index + 1; end end function [7:0] get_data; input [7:0] index; begin get_data = data_store[index]; end endfunction

这里定义了一个数组datastore来存储接收到的数据,dataindex记录存储位置。在RECEIVEDATA状态时,将接收到的数据存入数组。getdata函数用于后续调用存储的数据。

工程相关资料

资料里包含工程文件(可以选择 quartus 或者 Xilinx),代码都是带有详细注释的,方便大家理解每一步的操作。同时还有 testbench,通过运行仿真就能查看波形,直观地验证我们设计的正确性。比如说,通过观察波形,我们可以看到各个状态的转移是否正确,数据的接收和存储是否符合预期。

通过这样一套设计,我们就实现了 FPGA 通过 UART 通讯准确解析上位机数据包,并完成数据存储和调用,利用三段式状态机让整个流程清晰明了,有条不紊。希望这篇博文能给大家在相关项目开发中提供一些有用的思路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 7:06:47

从零搭建ESP8266 RTOS开发环境:5步搞定物联网项目基础

从零搭建ESP8266 RTOS开发环境&#xff1a;5步搞定物联网项目基础 【免费下载链接】ESP8266_RTOS_SDK Latest ESP8266 SDK based on FreeRTOS, esp-idf style. 项目地址: https://gitcode.com/gh_mirrors/es/ESP8266_RTOS_SDK 想要快速上手ESP8266物联网开发吗&#xff…

作者头像 李华
网站建设 2026/4/15 14:00:43

Open-AutoGLM 桌面端 vs 云端API:成本、速度与隐私的终极对比

第一章&#xff1a;Open-AutoGLM 桌面端 vs 云端API&#xff1a;核心差异全景图在人工智能推理部署方案中&#xff0c;Open-AutoGLM 提供了桌面端本地运行与云端API调用两种主流模式&#xff0c;二者在性能、隐私、成本和扩展性方面存在显著差异。部署灵活性与资源控制 桌面端允…

作者头像 李华
网站建设 2026/4/14 16:19:39

Webhook自动化部署终极指南:10个高效CI/CD实战技巧

Webhook自动化部署终极指南&#xff1a;10个高效CI/CD实战技巧 【免费下载链接】webhook webhook is a lightweight incoming webhook server to run shell commands 项目地址: https://gitcode.com/gh_mirrors/we/webhook 在现代软件开发中&#xff0c;Webhook自动化部…

作者头像 李华
网站建设 2026/4/15 14:10:41

VC++运行环境终极指南:从2005到2022完整部署方案

VC运行环境终极指南&#xff1a;从2005到2022完整部署方案 【免费下载链接】VCWindows运行环境合集VC2005-VC2022 本仓库提供了一个VC Windows运行环境合集&#xff0c;涵盖了从VC2005到VC2022的所有必要运行库。这些运行库是生成C运行程序&#xff08;如MFC等&#xff09;后&a…

作者头像 李华
网站建设 2026/4/14 16:37:43

AD16终极封装库:电子设计工程师的完整资源宝典

AD16终极封装库&#xff1a;电子设计工程师的完整资源宝典 【免费下载链接】AD16最全封装库自用 本仓库提供了一个名为“AD16最全封装库&#xff08;自用&#xff09;.rar”的资源文件下载。该文件包含了各种CPU、存储器、电源芯片、几乎所有接口&#xff08;如DB9、DB15、RJ45…

作者头像 李华
网站建设 2026/4/15 14:10:44

Docker 适配 AMD64/ARM64 的多架构 Python 镜像构建方案

文章目录 一、优化后的Dockerfile(Dockerfile-multiarch) 二、不推送的多架构构建命令(本地构建&测试) 1. 前置准备(安装qemu,支持跨架构模拟) 2. 构建多架构镜像(本地存储,不推送) 3. 本地测试不同架构的镜像 三、关键优化说明 总结 一、错误原因解析 二、解决方…

作者头像 李华