从零到一:用紫光同创PGL22G FPGA搭建你的第一个片上系统(SoC)实战
第一次接触FPGA和片上系统(SoC)开发时,很多人会被复杂的工具链和抽象的概念吓退。但如果你手头有一块紫光同创PGL22G开发板,15分钟就能让软核跑起来,看到LED灯随你的代码闪烁——这种即时反馈的成就感,正是学习嵌入式开发的最佳动力。本文将带你完整走通这个流程,从工具安装到最终验证,避开那些新手常踩的坑。
1. 环境准备与工具链配置
工欲善其事,必先利其器。紫光同创PGL22G开发需要以下软件环境:
- Pango Design Suite:紫光官方FPGA开发工具,支持综合、布局布线
- Keil MDK:用于Arm Cortex-M1软核的嵌入式程序开发
- 串口调试工具:如Putty或MobaXterm
- RISC-V工具链(可选):如果选择RISC-V软核则需要安装
注意:Pango Design Suite需要license文件,可联系紫光同创技术支持获取教育版授权。
安装完成后,建议按以下顺序验证环境:
# 检查Pango工具是否正常 pango --version # 检查Arm工具链 arm-none-eabi-gcc --version常见问题排查:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| Pango无法识别设备 | 驱动未安装 | 安装Pango驱动包中的CP210x驱动 |
| Keil编译报错 | 未正确配置设备包 | 在Pack Installer中添加PGL22G支持 |
| 下载失败 | 板卡供电不足 | 确保使用配套12V电源适配器 |
2. 构建最小片上系统
2.1 创建基础工程
在Pango Design Suite中新建项目时,关键配置如下:
- 器件选择:PGL22G-6FBG484
- 语言:Verilog或VHDL(根据个人偏好)
- 添加IP核:Cortex-M1或RISC-V软核
对于初学者,建议从Cortex-M1开始,因为其工具链更成熟。创建工程后,需要配置以下基本组件:
- 处理器时钟(通常使用板载50MHz晶振)
- 复位电路(外部复位按钮)
- 调试接口(SWD或JTAG)
2.2 连接GPIO外设
在Pango的IP Integrator中,添加AXI GPIO控制器并连接到处理器:
// 示例:Verilog中实例化GPIO模块 gpio_controller gpio_inst ( .s_axi_aclk(clk_50m), .s_axi_aresetn(!reset), .gpio_io_o(led_output), .gpio_io_i(sw_input) );引脚分配需要对照开发板原理图完成。以常见的LED和按键为例:
| 信号名称 | FPGA引脚 | 板载功能 |
|---|---|---|
| led_output[0] | F5 | 用户LED1 |
| sw_input[0] | A8 | 用户按键1 |
3. 编写嵌入式程序
3.1 Keil工程配置
新建Keil项目时需要注意:
- 设备选择:Cortex-M1
- 运行时环境:勾选CMSIS-Core和Device-Startup
- 链接脚本:修改ROM/RAM大小匹配软核配置
一个简单的点灯程序结构如下:
#include "PGL22G_M1.h" #define LED_PIN 0 #define SW_PIN 0 int main(void) { GPIO_InitTypeDef GPIO_InitStruct; // 启用GPIO时钟 __HAL_RCC_GPIO_CLK_ENABLE(); // 配置LED引脚为输出 GPIO_InitStruct.Pin = (1 << LED_PIN); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置按键引脚为输入 GPIO_InitStruct.Pin = (1 << SW_PIN); GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); while (1) { // 读取按键状态并控制LED HAL_GPIO_WritePin(GPIOA, (1 << LED_PIN), HAL_GPIO_ReadPin(GPIOB, (1 << SW_PIN))); } }3.2 调试技巧
遇到程序不运行时,可以按以下步骤排查:
- 检查复位向量是否正确(通常0x00000000)
- 确认时钟配置与硬件一致
- 使用SWD接口读取PC寄存器值
- 在startup.s中设置断点观察是否执行到main()
提示:初期调试建议关闭优化(-O0),并启用semihosting输出调试信息。
4. 系统验证与进阶扩展
4.1 功能验证流程
- 在Pango中生成比特流文件(.bit)
- 通过Programmer工具下载到FPGA
- 在Keil中编译并下载.hex文件到软核
- 观察LED是否随按键变化
4.2 扩展思路
完成基础功能后,可以尝试以下进阶实验:
- 添加定时器中断实现LED闪烁
- 通过UART打印调试信息
- 移植FreeRTOS实现多任务
- 添加SPI接口连接外部传感器
// 示例:使用HAL库实现UART输出 void debug_printf(char *str) { HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), 1000); }开发过程中最常遇到的三个问题:
- 时钟不同步导致外设无法工作
- 解决方案:检查PLL配置和分频系数
- 内存访问越界导致HardFault
- 解决方案:调整链接脚本中的堆栈大小
- 外设寄存器读写无效
- 解决方案:确认外设时钟已使能
当LED第一次按照预期亮起时,你会意识到那些配置步骤和调试过程都是值得的。建议把这个最小系统作为模板工程保存,后续项目可以直接在此基础上添加新功能。