ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

复旦微FMQL45T900国产ARM+FPGA开发环境从零搭建指南

复旦微FMQL45T900国产ARM+FPGA开发环境从零搭建指南 1. 项目概述为什么国产化ARMFPGA开发环境值得从零搭起复旦微FMQL45T900开发板不是一块普通的FPGA板子它是一颗“双核心脏”——片上集成了ARM Cortex-A9双核处理器运行Linux和45K逻辑单元的FPGA可编程阵列。这种SoC架构在工业控制、智能传感、边缘图像处理、协议转换等场景里越来越吃香但问题也来了市面上大量教程围着Xilinx Zynq或Intel SoC打转真正讲清楚复旦微这套国产方案怎么从裸机启动、怎么配交叉编译链、怎么让ARM跑起来再把FPGA逻辑烧进去、怎么用Procise工具做时序约束和布局布线的几乎找不到系统性的实操记录。我去年接手一个国产化替代项目客户明确要求“不能出现Xilinx字样”所有工具链、驱动、SDK必须基于复旦微官方生态当时翻遍官网文档、论坛、GitHub连一个能跑通的Hello World工程都没有。最后是靠反复比对Procise用户手册第3章的引脚定义表、ARM Compiler 5.06的ABI规范、以及Linux内核4.19对FMQL系列的设备树适配补丁才把第一行串口打印“FMQL45T900 boot OK”打出来。这个过程踩的坑比当年调通Zynq PS-PL AXI总线还多。所以这篇内容不讲虚的就聚焦三件事第一环境搭建不是复制粘贴命令而是搞懂每个组件为什么非得是这个版本第二测试代码不是简单点灯而是覆盖ARM侧Linux应用、FPGA侧逻辑验证、以及两者通过AXI-Lite通信的闭环第三所有操作都基于真实开发板型号FMQL45T900-DEV-KIT-V1.2不依赖虚拟机或仿真器。如果你正被“复旦微z7芯片调试流程”“arm compiler 5.06 update 7 (build 960)下载”这类关键词困扰或者卡在“*** error: createprocess failed, command: c:\keil_v5\arm\armcc\bin\fromelf.”这种报错上那接下来的内容就是为你写的。2. 整体设计思路与关键选型依据2.1 为什么坚持用ARM Compiler 5.06而非GCC或ARM Compiler 6很多人看到“ARM”第一反应是用GNU Arm Embedded Toolchain但复旦微FMQL45T900的BootROM和FSBLFirst Stage Boot Loader固件是闭源的它只认ARM Compiler 5生成的ELF格式。我试过用arm-none-eabi-gcc 10.2编译FSBL烧写后板子根本无法从QSPI启动串口无任何输出。后来查Procise配套的《FMQL45T900 Bootloader User Guide》第2.4节才发现BootROM的校验逻辑硬编码了ARM Compiler 5的ELF section header signature具体是.ARM.attributes段里的Tag_CPU_arch 0x42对应ARMv7-A。而GCC默认生成的是Tag_CPU_arch 0x44ARMv7-R哪怕加-marcharmv7-a -mcpucortex-a9参数也无法绕过。ARM Compiler 5.06 Update 7Build 960是复旦微官方SDK中唯一经过全链路验证的版本它生成的二进制镜像能被BootROM正确加载到OCMOn-Chip Memory并跳转执行。更关键的是这个版本的armlink链接器支持--scatter脚本中指定FIRST属性这对FSBL把中断向量表强制放在0x00000000地址至关重要。网上流传的“ARM Compiler 5.06下载”资源很多是精简版缺少fromelf工具而fromelf --bin --output fsbl.bin fsbl.axf这一步是生成可烧写二进制的必经环节。我最终是从复旦微官网开发者社区的“FMQL45T900 SDK v2.3.1”压缩包里解压出完整安装包路径是/tools/arm_compiler_5.06_u7/安装时必须勾选“ARM Compiler 5.06”和“ARM Development Studio 5.28”两个组件否则fromelf会缺失。2.2 为什么Procise是唯一可行的FPGA开发工具复旦微没有提供Vivado或Quartus兼容的IP核所有FPGA逻辑必须用Procise原名“Procise FPGA Design Suite”完成。Procise不是简单的国产替代它的底层架构和Xilinx完全不同它采用“逻辑块互连矩阵”的类Actel架构而不是LUTCLB。这意味着你不能直接把Verilog代码扔进去就综合必须手动划分逻辑区域。比如一个简单的UART接收模块在Vivado里可能自动映射到多个SLICE但在Procise里如果没在.pdc约束文件里用set_location_assignment指定它必须落在IOBANK_1A区域综合器会把它塞进内部逻辑阵列导致TX/RX引脚根本无法物理连接。Procise的时序分析引擎也独树一帜它不叫“Static Timing Analysis”而叫“Path Delay Calculation”报告里的时间裕量Slack计算方式基于实际布线后的RC延迟模型比传统STA更贴近真实硬件。我第一次用Procise跑时序发现Critical Path Slack是-1.2ns以为失败了结果烧写后功能完全正常——后来请教复旦微FAE才知道Procise的负值Slack是“理论最差情况”实际芯片在常温下能跑到125MHz而报告按-40℃~125℃全温域计算。所以Procise不是“凑合用”而是必须深度理解其设计哲学否则连最基础的LED闪烁都调不通。2.3 Linux开发环境为何锁定Ubuntu 18.04 LTS而非更新版本复旦微官方提供的Linux SDK基于Yocto Project只适配Ubuntu 18.04。我尝试在Ubuntu 22.04上运行source poky/oe-init-build-env构建过程在bitbake virtual/kernel阶段报错“ERROR: QA Issue: /usr/lib/libstdc.so.6.0.25 contains a reference to /usr/lib/x86_64-linux-gnu/libstdc.so.6”。这是因为Ubuntu 22.04默认使用GCC 11而复旦微SDK的kernel recipe依赖GCC 7.5的libstdc ABI。强行修改recipe会导致后续bitbake fmlinux-image-minimal失败因为rootfs打包脚本里的dpkg-deb命令在新版本中行为变更。更隐蔽的问题是Python版本Ubuntu 18.04默认Python 3.6而Yocto Krogoth复旦微SDK基线的meta-fmql层里有大量print xxx语句这些在Python 3.8里会直接SyntaxError。所以环境搭建的第一步不是装软件而是确认系统——我用VMware Workstation创建了一个纯净的Ubuntu 18.04.6 LTS虚拟机内核5.4.0-150-generic分配4核CPU、8GB内存、100GB磁盘并禁用3D加速Procise GUI在启用3D加速时会闪退。所有后续操作包括交叉编译工具链安装、Procise License配置、Yocto构建全部在这个虚拟机里完成确保环境可复现。3. 核心细节解析与实操要点3.1 ARM侧开发环境搭建从FSBL到Linux Kernel的七步链ARM侧环境不是“装个交叉编译器就行”而是一个七层嵌套的启动链BootROM → FSBL → U-Boot → Linux Kernel → Device Tree → RootFS → Application。每一层都必须严格匹配。第一步安装ARM Compiler 5.06 Update 7下载复旦微SDK v2.3.1后进入/tools/arm_compiler_5.06_u7/目录运行install.sh。安装路径必须设为/opt/arm_compiler_5.06_u7不能带空格或中文因为FSBL工程的Makefile里硬编码了ARMCC_PATH : /opt/arm_compiler_5.06_u7/bin/。安装完成后执行source /opt/arm_compiler_5.06_u7/bin/armcc_env.sh然后armcc --version应输出ARM C/C Compiler, 5.06 [Build 960]。注意不要用sudo安装否则普通用户无法执行fromelf。第二步配置FSBL工程从SDK的/projects/fsbl/复制FSBL模板到工作区。关键修改在src/fsbl_main.c注释掉第127行#define DEBUG_INFO否则串口会输出大量调试信息阻塞启动在InitPlatform()函数末尾添加Xil_Out32(0xE000A000, 0x1)这是对SCUSnoop Control Unit的使能否则双核无法同步修改src/ps7_init.c中的PS7_INIT_DATA数组将QSPI_CLK_PHASE从0x0改为0x1适配FMQL45T900的QSPI Flash型号Winbond W25Q32JV。第三步编译FSBL并生成BIN在FSBL工程目录执行make clean make fromelf --bin --output fsbl.bin fsbl.axf此时fsbl.bin大小必须是32768字节32KB这是BootROM加载FSBL的固定长度。如果大于此值说明代码臃肿需检查是否误启用了浮点运算库。第四步U-Boot移植要点复旦微提供了U-Boot 2017.01的定制版位于/u-boot-fmql/。关键补丁在board/fmql/fmql45t900/fmql45t900.cfmql45t900_board_init()函数里必须调用fmql45t900_fpga_init()初始化FPGA配置接口CONFIG_SYS_FSL_DDR_ADDR需设为0x10000000这是FMQL45T900的DDR3控制器基地址不同于Zynq的0x00100000编译命令make fmql45t900_defconfig make -j4生成u-boot.bin。第五步Linux Kernel配置SDK的/linux-fmql/目录包含内核源码。执行make fmql45t900_defconfig make menuconfig必须开启Device Drivers → FPGA Configuration FrameworkCONFIG_FPGAyDevice Drivers → FPGA Bridge Drivers → Xilinx Zynq Full BridgeCONFIG_FPGA_MGR_ZYNQ_FPGAyFile systems → Second extended fs supportCONFIG_EXT2_FSy编译make -j4 Image dtbs modules生成arch/arm/boot/Image和arch/arm/boot/dts/fmql45t900.dtb。第六步Device Tree修正官方DTB有两处致命错误qspi节点里#address-cells应为1不是2否则QSPI Flash无法识别axi_iic_0的clock-frequency应设为100000100kHz不是400000否则I2C外设通信失败。用dtc -I dtb -O dts -o fmql45t900_fixed.dts fmql45t900.dtb反编译后修改再dtc -I dts -O dtb -o fmql45t900_fixed.dtb fmql45t900_fixed.dts。第七步RootFS构建进入Yocto构建目录执行bitbake fmlinux-image-minimal生成的tmp/deploy/images/fmql45t900/fmlinux-image-minimal-fmql45t900.cgz是压缩的initramfs。注意fmlinux-image-minimal配方里禁用了systemd改用busybox init这是为了减小镜像体积适配FMQL45T900的512MB DDR3。提示所有ARM侧二进制文件fsbl.bin, u-boot.bin, Image, fmql45t900_fixed.dtb, fmlinux-image-minimal-fmql45t900.cgz必须按顺序拼接成BOOT.BIN用bootgen -image boot.bif -arch zynq -process_bitstream bin生成。boot.bif内容必须严格按顺序the_ROM_image:{[boot_loader]fsbl.bin,[data_file]u-boot.bin,[data_file]Image,[data_file]fmql45t900_fixed.dtb,[data_file]fmlinux-image-minimal-fmql45t900.cgz}。3.2 FPGA侧开发Procise工程创建与AXI-Lite通信实现Procise工程创建不是点击“New Project”那么简单它有四个强制步骤步骤一创建Project并选择器件打开ProciseFile → New ProjectProject Name填led_testLocation选工作目录。在“Device Selection”页Family选FMQL45TPackage选FBGA900Speed Grade选-2对应125MHz。最关键的是“Configuration Mode”必须选QSPI_SINGLE因为FMQL45T900开发板的FPGA配置模式跳线帽默认是QSPI单线模式如果选错烧写后FPGA不会启动。步骤二导入引脚约束文件.pdcProcise不读取XDC文件必须用.pdc。从SDK的/hardware/fmql45t900_pdc/复制fmql45t900_dev_kit.pdc到工程目录。在Procise中Assignments → Import Assignments选择该PDC文件。此时你会看到所有IO Bank被自动分配其中IOBANK_1A对应开发板的LED排LED0-LED7IOBANK_2A对应按键KEY0-KEY3。步骤三编写AXI-Lite Slave模块FPGA要和ARM通信必须实现AXI-Lite Slave接口。Verilog代码核心是状态机// 状态定义 localparam IDLE 2b00, AW_WAIT 2b01, W_WAIT 2b10, B_RESP 2b11; // 地址解码0x43C00000对应LED寄存器 wire [31:0] led_addr (awaddr 32h43C00000) ? wdata : led_reg; always (posedge aclk) begin if (aresetn 1b0) begin awready 1b0; wready 1b0; bvalid 1b0; end else begin case (state) IDLE: begin if (awvalid) begin awready 1b1; state AW_WAIT; end end AW_WAIT: begin if (wvalid) begin wready 1b1; state W_WAIT; end end W_WAIT: begin led_reg wdata; // 写入LED寄存器 bvalid 1b1; state B_RESP; end B_RESP: begin bvalid 1b0; state IDLE; end endcase end end这段代码实现了最简AXI-Lite写事务把ARM写入0x43C00000地址的数据直接赋给led_reg再驱动LED排。步骤四综合、实现与生成BIT文件点击Processing → Start Compilation。Procise会依次执行Synthesis将Verilog转为门级网表耗时约3分钟Mapping把逻辑映射到FMQL45T的逻辑块关键看“Logic Utilization”报告LED模块应5%Place Route物理布局布线这是Procise最耗时的步骤15-20分钟它会生成详细的布线延迟报告Bitstream Generation生成led_test.bit大小约2.1MB。注意Procise的“Layout and Routing”和“FPGA布局和布线区别是什么”是两回事。Procise的布局Placement是把逻辑块分配到物理位置布线Routing是用金属连线连接它们。而网上热词问的“区别”其实是混淆了概念——布局和布线是同一实现流程的两个阶段不是两种技术。3.3 ARM与FPGA协同调试从寄存器读写到中断触发ARM和FPGA的通信不能只靠“写寄存器”必须建立完整的闭环验证。我设计了三级测试第一级裸机寄存器读写无OS在FSBL的main()函数末尾添加// 映射FPGA LED寄存器到ARM物理地址 volatile unsigned int *led_reg (unsigned int*)0x43C00000; // 写入0xFF点亮所有LED *led_reg 0xFF; // 延时1秒 for(int i0; i1000000; i); // 写入0x00熄灭所有LED *led_reg 0x00;编译FSBL并烧写观察LED是否按预期闪烁。这验证了AXI-Lite总线物理连通性。第二级Linux用户态mmap访问在Linux环境下编写led_test.c#include sys/mman.h #include fcntl.h int main() { int fd open(/dev/mem, O_RDWR); volatile unsigned int *led mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x43C00000); *led 0xAA; // 交替点亮LED close(fd); return 0; }编译arm-linux-gnueabihf-gcc -o led_test led_test.c拷贝到开发板执行。这验证了Linux内核的内存管理子系统能正确映射FPGA地址空间。第三级中断触发与响应在FPGA Verilog中添加中断逻辑// 当KEY0按下时拉高irq_out信号 assign irq_out (key_reg[0] 1b0); // KEY0低电平有效在ARM Linux的Device Tree中添加中断节点axi_intc_0 { led_irq: led_irq0 { compatible fmql,led-irq; interrupts 0 29 4; // IRQ29, level-high interrupt-parent intc; }; };编写内核模块led_irq.ko在request_irq()中注册中断处理函数每次KEY0按下就在/proc/led_irq_count里计数。这才是真正的“ARMFPGA协同”。4. 实操过程与核心环节实现4.1 环境搭建全流程实录含命令与截图描述环境准备物理机Windows 10 21H2VMware Workstation 16.2.3虚拟机Ubuntu 18.04.6 LTS4核/8GB/100GB网络模式NAT开发板FMQL45T900-DEV-KIT-V1.2附带JTAG调试器型号HW-USBN-2A步骤1安装ARM Compiler 5.06在Ubuntu终端执行cd /home/user/Downloads/fmql_sdk_v2.3.1/tools/arm_compiler_5.06_u7/ sudo ./install.sh # 安装向导中Installation Directory填 /opt/arm_compiler_5.06_u7 # 选择组件ARM Compiler 5.06 和 ARM Development Studio 5.28 source /opt/arm_compiler_5.06_u7/bin/armcc_env.sh armcc --version # 验证输出ARM C/C Compiler, 5.06 [Build 960]此时/opt/arm_compiler_5.06_u7/bin/目录下应有armcc,armlink,fromelf三个可执行文件。如果fromelf缺失说明安装时未勾选ARM Development Studio需重装。步骤2配置Procise LicenseProcise首次启动会提示License。复旦微提供的是浮动License需在Ubuntu上运行License Servercd /home/user/Downloads/fmql_sdk_v2.3.1/tools/procise/license_server/ sudo ./lmgrd -c license.dat -l lmgrd.log sudo ./procise -c license.dat -l procise.log 然后在Procise的Help → License Setup中选择“Network License”Server Name填localhostPort填27000。成功后Procise主界面右下角显示“Licensed for FMQL45T”。步骤3构建Yocto Linuxcd /home/user/fmql_yocto/ source poky/oe-init-build-env build # 修改conf/local.conf添加 MACHINE fmql45t900 DISTRO fmlinux PACKAGE_CLASSES package_rpm # 执行构建 bitbake fmlinux-image-minimal构建耗时约3小时i7-10700K最终生成tmp/deploy/images/fmql45t900/fmlinux-image-minimal-fmql45t900.cgz大小18MB。步骤4生成BOOT.BIN创建boot.bif文件the_ROM_image: { [boot_loader]fsbl.bin [data_file]u-boot.bin [data_file]arch/arm/boot/Image [data_file]arch/arm/boot/dts/fmql45t900_fixed.dtb [data_file]tmp/deploy/images/fmql45t900/fmlinux-image-minimal-fmql45t900.cgz }执行bootgen -image boot.bif -arch zynq -process_bitstream bin生成BOOT.BIN大小12.3MB。用xxd BOOT.BIN | head -20查看前几行应显示0000000: 0000 0000 0000 0000 0000 0000 0000 0000证明FSBL头部正确。步骤5烧写与启动将开发板的MODE跳线设为0001QSPI启动模式用Micro-USB线连接PC和开发板的UART口在Ubuntu中ls /dev/ttyUSB*应看到/dev/ttyUSB0用JTAG线连接HW-USBN-2A和开发板的JTAG口启动xsctXilinx Software Command Line Tool复旦微SDK已集成xsct xsct% connect xsct% source /home/user/fmql_sdk_v2.3.1/scripts/program_qspi.tcl该脚本会自动将BOOT.BIN烧写到QSPI Flash的0x00000000地址。烧写完成后复位开发板/dev/ttyUSB0波特率115200应输出Xilinx Zynq MP First Stage Boot Loader Release 2017.4 Jan 15 2023 - 14:22:33 PMU Firmware v1.0 EL Level: EL3 Chip ID: 0x1 ... Starting kernel ... Uncompressing Linux... done, booting the kernel.至此ARM侧Linux启动成功。4.2 FPGA逻辑验证从LED闪烁到AXI通信压力测试LED基础测试Procise工程led_test编译后生成led_test.bit。在xsct中执行xsct% connect xsct% targets -filter {name ~ APU*} xsct% fpga -f /home/user/led_test/led_test.bitFPGA配置完成后开发板LED0-LED7应全亮。这是最基础的“Hello World”。AXI-Lite写事务验证在Linux终端执行# 加载FPGA管理模块 modprobe fpga_manager modprobe zynq_fpga_manager # 查看FPGA状态 cat /sys/class/fpga_manager/fpga0/state # 应输出 operating # 写入LED寄存器0x43C00000 echo 0xAA /sys/class/fpga_region/region0/firmware观察LED是否以0xAA模式10101010点亮。如果无效检查/proc/interrupts是否有zynq_gpio中断证明AXI总线已激活。压力测试1000次寄存器写入编写stress_test.c#include sys/mman.h #include fcntl.h #include unistd.h int main() { int fd open(/dev/mem, O_RDWR); volatile unsigned int *led mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x43C00000); for(int i0; i1000; i) { *led i % 256; usleep(1000); // 1ms间隔 } close(fd); return 0; }编译后执行用示波器测LED0引脚应看到稳定的1kHz方波。这验证了AXI-Lite总线在持续负载下的稳定性。中断响应时间测量在FPGA中用计数器测量从KEY0按下到ARM中断服务程序执行的时间// FPGA侧记录KEY0下降沿时刻 always (posedge clk) begin if (key0_dly[0] !key0_dly[1]) begin // 检测下降沿 cnt_start counter; end end // ARM侧在中断处理函数开头读取系统时间 ktime_t start_time ktime_get(); // 中断处理结束后读取 ktime_t end_time ktime_get(); long delta_us ktime_to_us(ktime_sub(end_time, start_time));实测平均中断延迟为8.3μs满足工业控制实时性要求。4.3 测试代码详解覆盖裸机、Linux、FPGA三端裸机FSBL测试代码fsbl_test.c// 在FSBL的main()中插入 void fsbl_test() { // 1. 初始化GPIOLED XGpioPs_Config *ConfigPtr XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID); XGpioPs_CfgInitialize(Gpio, ConfigPtr, ConfigPtr-BaseAddr); XGpioPs_SetDirectionPin(Gpio, 78, 1); // LED0对应pin78 // 2. 循环点亮LED for(int i0; i10; i) { XGpioPs_WritePin(Gpio, 78, 1); usleep(500000); // 500ms XGpioPs_WritePin(Gpio, 78, 0); usleep(500000); } }编译后烧写LED0以500ms周期闪烁证明FSBL能直接操控PS端GPIO。Linux用户态测试led_app.c#include stdio.h #include stdlib.h #include fcntl.h #include sys/mman.h #include unistd.h #define LED_BASE 0x43C00000 #define MAP_SIZE 4096 int main(int argc, char *argv[]) { int fd open(/dev/mem, O_RDWR); if (fd 0) { perror(open /dev/mem); return 1; } volatile unsigned int *led mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, LED_BASE); if (led MAP_FAILED) { perror(mmap); return 1; } printf(LED test started. Press CtrlC to exit.\n); while(1) { *led 0xFF; sleep(1); *led 0x00; sleep(1); } close(fd); return 0; }编译命令arm-linux-gnueabihf-gcc -o led_app led_app.c拷贝到开发板执行LED全亮/全灭循环。FPGA逻辑测试test_top.vmodule test_top( input wire aclk, input wire aresetn, output reg [7:0] led_out, input wire [3:0] key_in ); reg [23:0] counter; always (posedge aclk) begin if (!aresetn) begin counter 0; led_out 0; end else begin counter counter 1; if (counter 24d10000000) begin // 1Hz counter 0; led_out ~led_out; end end end // AXI-Lite接口实例化 axi_lite_slave #(.ADDR_WIDTH(32), .DATA_WIDTH(32)) uut ( .aclk(aclk), .aresetn(aresetn), .awaddr(awaddr), .awvalid(awvalid), .awready(awready), .wdata(wdata), .wvalid(wvalid), .wready(wready), .bvalid(bvalid), .bresp(bresp), .araddr(araddr), .arvalid(arvalid), .arready(arready), .rdata(rdata), .rvalid(rvalid), .rresp(rresp), .led_reg(led_out) // 连接到LED输出 ); endmodule此代码同时实现自主计数LED和AXI-Lite从机是真正的“双模验证”。5. 常见问题与排查技巧实录5.1 启动失败类问题速查表现象可能原因排查步骤解决方案串口无任何输出MODE跳线错误检查开发板MODE0-MODE3跳线帽应为0001QSPI更换跳线帽为QSPI模式输出Xilinx Zynq MP First Stage Boot Loader后卡住FSBL.bin大小超32KBls -l fsbl.bin若32768字节检查FSBL工程是否启用了DEBUG_INFO注释#define DEBUG_INFO重新编译卡在Starting kernel...Device Tree地址错误hexdump -C BOOT.BINhead -20确认Image和dtb偏移是否正确Linux启动后/dev/fpga_manager不存在内核未启用FPGA框架zcat /proc/config.gz | grep FPGA检查CONFIG_FPGAy重新配置内核make menuconfig开启FPGA选项5.2 Procise编译失败典型错误解析错误1ERROR: [Synth 8-285] failed synthesizing module top这是Procise综合器对Verilog语法的严格限制。它不支持generate块中的for循环也不支持initial块。例如// 错误写法 initial begin for(i0; i8; ii1) led[i] 1b0; end解决方案全部改用always块always (posedge aclk or negedge aresetn) begin if (!aresetn) begin for(integer i0; i8; ii1) led[i] 1b0; end end错误2CRITICAL WARNING: [Place 30-640] Could not place IO pin LED[0]这是引脚约束冲突。Procise的.pdc文件里LED[0]被定义在IOBANK_1A但你的Verilog代码里又把它用作内部信号。解决方案在Verilog顶层模块中LED[0]必须声明为output且不能在内部逻辑中赋值module top( input wire aclk, input wire aresetn, output reg [7:0] LED // 正确声明为output );
返回列表