基于串口的FPGA远程升级源代码verilog支持vivadoxilinx等各类厂家FPGA。 串口升级支持RS422RS232RS485最大速率可达921600bps波特率可设置奇偶校验可设置。 具备升级过程中异常掉电防变砖的功能具备golden镜像、multiboot镜像、支持镜像损坏回退看门狗超时回退等功能。 串口预留FIFO接口后续可移植其它接口升级最近在工业控制项目里折腾FPGA远程升级发现市面上的方案要么太贵要么不够稳。自己搓了个基于串口的升级方案实测支持Xilinx全系FPGAVivado 2018-2023版本都验证过。核心代码不到800行Verilog支持三模串口和镜像守护机制先上段状态机代码镇楼// 镜像切换状态机 always (posedge clk or posedge rst) begin if(rst) begin boot_state CHECK_GOLDEN; end else begin case(boot_state) CHECK_GOLDEN: if(golden_crc_err) begin boot_state WDT_RESET; error_cnt 8d0; end else if(update_flag) begin boot_state LOAD_MULTIBOOT; end LOAD_MULTIBOOT: if(wdt_timeout || crc32_error) begin boot_state FALLBACK_GOLDEN; end else if(bitstream_done) begin boot_state REBOOT_NEW_IMAGE; end //...其他状态省略 endcase end end这个状态机的骚操作在于实现了三级保护上电先校验Golden镜像的CRC32相当于给FPGA买了意外险加载Multiboot镜像时同步跑看门狗超时或校验失败自动回滚异常计数器防抖设计避免误触发回退串口协议栈用了参数化设计波特率配置寄存器直接挂钩系统时钟// 波特率生成器 parameter CLK_FREQ 100_000_000; reg [31:0] baud_divider; always (*) begin case(baud_rate_setting) 115200: baud_divider CLK_FREQ/(115200*16); 921600: baud_div_divider CLK_FREQ/(921600*4); // 超频模式 default: baud_divider CLK_FREQ/(baud_rate_setting*16); endcase end实测在Artix-7上跑到921600bps不掉包秘诀是接收端用了双缓冲FIFO// 乒乓缓冲结构 reg [7:0] fifo_buffer[0:1023]; reg [9:0] wr_ptr 0, rd_ptr 0; reg current_buffer 0; always (posedge uart_rx_clk) begin if(rx_data_valid) begin fifo_buffer[wr_ptr] rx_data; wr_ptr wr_ptr 1; if(wr_ptr 511) begin current_buffer ~current_buffer; wr_ptr 0; end end end防变砖的核心在于ICAPE2硬核的妙用。加载新镜像前先通过原镜像的ICAP接口把配置数据写入备用区域验证通过后再切换启动地址// ICAPE2硬核调用 ICAPE2 #( .ICAP_WIDTH(X32) ) icap_inst ( .CLK(clk), .CSIB(icap_cs), .I(icap_data), .O() );掉电保护方案比较暴力但有效——在配置Flash中划出三个独立区域Golden镜像区永远保留出厂版本Multiboot镜像区存储待验证的升级固件备份缓冲区传输过程中分块存储凑满一帧才整体写入实测从开始升级到完成写入整个过程中任意时刻断电都不会损坏原有固件。有一次故意在升级到99%时拔电板子还是能正常回滚到前一个可用版本。基于串口的FPGA远程升级源代码verilog支持vivadoxilinx等各类厂家FPGA。 串口升级支持RS422RS232RS485最大速率可达921600bps波特率可设置奇偶校验可设置。 具备升级过程中异常掉电防变砖的功能具备golden镜像、multiboot镜像、支持镜像损坏回退看门狗超时回退等功能。 串口预留FIFO接口后续可移植其它接口升级移植性方面顶层模块把物理接口抽象成了FIFO协议。要改成网口升级的话基本上只需要替换uartrx模块为ethrx实测过通过UDP传输配置数据的版本。最后给个调试建议用Vivado的ILA抓取ICAP状态信号时记得设置触发条件为crc_error上升沿这样能快速定位镜像传输过程中的异常点。曾经有个诡异bug就是靠这个逮到时钟域没同步的问题。