紫光同创FPGA开发板LED流水灯实现教程

1. 盘古PGX-MINI-4K开发板硬件概览

紫光同创盘古PGX-MINI-4K开发板是一款基于国产FPGA芯片PGC4KD-6ILPG144设计的开发平台。作为国产FPGA生态中的重要组成部分,这款开发板在硬件设计上充分考虑了初学者的使用需求。开发板采用Type-C接口供电,真正实现了"一根线搞定所有"的便捷体验。板载资源包括两组20PIN扩展IO接口、四位八段数码管、四个机械按键以及八个可编程LED灯。

开发板的核心芯片PGC4KD-6ILPG144属于紫光同创Compa系列FPGA,具有4K逻辑单元规模,采用LUT4架构,工作电压范围为1.2V,支持多种配置模式。特别值得一提的是,该开发板集成了JTAG调试接口,省去了外接下载器的麻烦,大大降低了初学者的入门门槛。

在LED硬件电路设计上,开发板采用了经典的共阳极连接方式,每个LED通过一个限流电阻连接到FPGA的IO口。当FPGA对应IO输出低电平时,LED点亮;输出高电平时,LED熄灭。这种设计在保证安全性的同时,也简化了程序控制逻辑。

2. 开发环境搭建与项目创建

2.1 软件工具准备

要进行FPGA开发,首先需要安装紫光同创官方提供的PDS开发环境。目前最新版本为PDS 2022.1,可以从紫光同创官网下载。安装过程需要注意以下几点:

  1. 安装路径不要包含中文或特殊字符
  2. 安装完成后需要手动添加License文件
  3. 建议同时安装USB驱动,确保开发板能够被正确识别

安装完成后,打开PDS软件,界面布局与主流EDA工具类似,主要包括工程管理窗口、设计输入窗口、综合报告窗口等几个主要区域。

2.2 新建工程步骤

  1. 点击File→New→Project创建新工程
  2. 选择正确的设备型号:PGC4KD-6ILPG144
  3. 设置工程存放路径(同样避免中文路径)
  4. 在"Add Source"步骤可以先跳过,后续再添加设计文件
  5. 完成工程创建后,建议立即进行保存

提示:初次使用PDS时,建议在工程设置中将"Enable Message Suppression"选项关闭,这样可以获取更详细的编译和调试信息,便于排查问题。

2.3 硬件连接与检测

将开发板通过Type-C接口连接到电脑后,需要确认设备管理器能够正确识别开发板。正常情况下会显示"Tang Primer USB-JTAG"设备。如果出现黄色感叹号,可能需要手动安装驱动。

可以通过PDS软件的"Programmer"工具检测开发板连接状态。点击"Auto Detect"按钮,如果一切正常,应该能够看到检测到的FPGA设备信息。这一步非常重要,确保后续的程序下载能够正常进行。

3. LED流水灯设计原理

3.1 硬件电路分析

盘古PGX-MINI-4K开发板上的LED采用共阳极连接方式,电路原理如下图所示:

FPGA IO口 → 220Ω限流电阻 → LED阳极 → LED阴极 → GND

这种连接方式意味着:

  • 当FPGA IO输出低电平(0)时,形成电流通路,LED点亮
  • 当FPGA IO输出高电平(1)时,没有电势差,LED熄灭

开发板上的8个LED分别连接到FPGA的以下IO口:

LED编号FPGA管脚网络标号
LED0P44LED[0]
LED1P45LED[1]
LED2P46LED[2]
LED3P47LED[3]
LED4P48LED[4]
LED5P49LED[5]
LED6P50LED[6]
LED7P51LED[7]

3.2 流水灯实现原理

流水灯效果的本质是按照特定规律依次点亮和熄灭LED。要实现这一效果,需要考虑以下几个关键点:

  1. 时序控制:需要设计一个计数器来产生时间基准,控制LED状态变化的节奏
  2. 状态转换:定义LED点亮的顺序和模式(左移、右移、交替等)
  3. 消抖处理:虽然LED控制不需要消抖,但良好的设计习惯应该考虑信号的稳定性

在FPGA中,通常使用时钟分频产生的定时信号来控制流水速度。例如,使用50MHz的系统时钟,通过分频产生1Hz的信号,就能实现每秒移动一次的流水效果。

4. Verilog代码实现详解

4.1 顶层模块设计

首先创建顶层模块led_water_flow.v,定义模块接口:

module led_water_flow( input wire clk, // 50MHz系统时钟 input wire rst_n, // 低电平复位信号 output reg [7:0] led // 8位LED输出 );

顶层模块主要完成以下功能:

  • 接收50MHz时钟和复位信号
  • 输出8位LED控制信号
  • 实例化定时器和LED控制逻辑

4.2 时钟分频设计

为了产生适合人眼观察的流水效果,需要对50MHz系统时钟进行分频。设计一个32位计数器,在计数值达到25,000,000时(对应0.5秒)产生一个脉冲信号:

reg [31:0] counter; reg timer_tick; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin counter <= 32'd0; timer_tick <= 1'b0; end else if(counter == 32'd24_999_999) begin counter <= 32'd0; timer_tick <= 1'b1; end else begin counter <= counter + 32'd1; timer_tick <= 1'b0; end end

这段代码实现了一个简单的分频器,每0.5秒产生一个时钟周期的高电平脉冲(timer_tick),用于触发LED状态变化。

4.3 LED状态机设计

LED流水效果可以通过状态机来实现。这里设计一个8状态的状态机,每个状态对应一个LED点亮的位置:

reg [2:0] state; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= 3'd0; led <= 8'b1111_1110; // 初始状态:LED0点亮 end else if(timer_tick) begin case(state) 3'd0: begin led <= 8'b1111_1101; state <= 3'd1; end 3'd1: begin led <= 8'b1111_1011; state <= 3'd2; end 3'd2: begin led <= 8'b1111_0111; state <= 3'd3; end 3'd3: begin led <= 8'b1110_1111; state <= 3'd4; end 3'd4: begin led <= 8'b1101_1111; state <= 3'd5; end 3'd5: begin led <= 8'b1011_1111; state <= 3'd6; end 3'd6: begin led <= 8'b0111_1111; state <= 3'd7; end 3'd7: begin led <= 8'b1111_1110; state <= 3'd0; end default: begin led <= 8'b1111_1110; state <= 3'd0; end endcase end end

这种实现方式虽然代码量稍大,但逻辑清晰,便于理解和修改。每个时钟分频脉冲到来时,LED点亮位置向右移动一位,形成流水效果。

4.4 移位寄存器实现方案

除了状态机方案,还可以使用移位寄存器来实现流水灯效果,代码更加简洁:

reg [7:0] led_pattern; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin led_pattern <= 8'b1111_1110; end else if(timer_tick) begin led_pattern <= {led_pattern[6:0], led_pattern[7]}; end end assign led = led_pattern;

这种实现方式利用Verilog的位拼接操作,每次将最高位移到最低位,实现循环移位效果。代码更加简洁,但可能对初学者理解起来稍有难度。

5. 约束文件配置与下载验证

5.1 管脚约束文件配置

在FPGA开发中,约束文件用于指定模块端口与实际物理管脚的对应关系。创建led_water_flow.pdc文件,添加以下内容:

# 系统时钟,连接到开发板50MHz晶振 set_pin_assignment { clk } { LOCATION = P23; } # 复位按键,连接到开发板K4按键 set_pin_assignment { rst_n } { LOCATION = P38; IOSTANDARD = LVCMOS33; PULLTYPE = PULLUP; } # LED输出管脚约束 set_pin_assignment { led[0] } { LOCATION = P44; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[1] } { LOCATION = P45; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[2] } { LOCATION = P46; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[3] } { LOCATION = P47; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[4] } { LOCATION = P48; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[5] } { LOCATION = P49; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[6] } { LOCATION = P50; IOSTANDARD = LVCMOS33; } set_pin_assignment { led[7] } { LOCATION = P51; IOSTANDARD = LVCMOS33; }

5.2 综合与实现

完成代码编写和约束文件配置后,按照以下步骤进行综合与实现:

  1. 点击"Flow"菜单中的"Synthesize"进行综合
  2. 综合完成后,点击"Implement"进行布局布线
  3. 实现过程完成后,查看时序报告,确保没有时序违例
  4. 生成比特流文件(.fs)

注意:初次使用时可能会遇到一些警告信息,如"Net 'xxx' has no load"等,这些通常与未使用的管脚或信号有关,不影响基本功能,但良好的设计习惯应该处理所有警告。

5.3 程序下载与调试

将生成的.fs文件下载到开发板的步骤如下:

  1. 确保开发板已正确连接电脑
  2. 打开PDS Programmer工具
  3. 点击"Add File"选择生成的.fs文件
  4. 确保编程选项选择"SRAM"模式(掉电后程序会丢失)
  5. 点击"Program"按钮开始下载

下载完成后,应该能看到开发板上的LED开始从右向左流动显示。如果按下K4按键(复位键),LED会恢复到初始状态。

6. 功能扩展与进阶实验

6.1 流水速度调节

可以通过修改分频系数来调整流水速度。例如,要加快流水速度,可以减小分频系数:

else if(counter == 32'd12_499_999) begin // 0.25秒 counter <= 32'd0; timer_tick <= 1'b1; end

也可以添加一个速度控制开关,通过开发板上的拨码开关来选择不同的分频系数,实现动态调速。

6.2 流水方向控制

扩展设计,添加方向控制功能。使用开发板上的一个按键来控制流水方向:

input wire dir_key, // 方向控制按键 // 在状态机或移位寄存器逻辑中添加方向判断 if(dir_key) begin // 向右流动 led_pattern <= {led_pattern[0], led_pattern[7:1]}; end else begin // 向左流动 led_pattern <= {led_pattern[6:0], led_pattern[7]}; end

6.3 多种流水模式实现

通过状态机实现多种流水模式切换,如:

  • 单灯流水
  • 双灯追逐
  • 全亮全灭呼吸效果
  • 随机点亮模式

可以使用开发板上的多个按键来切换不同模式,每种模式对应不同的LED控制逻辑。

6.4 使用PWM实现亮度渐变

在简单的开关控制基础上,可以引入PWM(脉宽调制)技术,实现LED亮度的渐变效果:

reg [7:0] pwm_counter; reg [7:0] pwm_value; reg pwm_out; always @(posedge clk) begin pwm_counter <= pwm_counter + 8'd1; pwm_out <= (pwm_counter < pwm_value) ? 1'b0 : 1'b1; end // 将pwm_out连接到LED控制信号

通过改变pwm_value的值,可以调节LED的亮度,实现呼吸灯等更丰富的视觉效果。

7. 常见问题与调试技巧

7.1 LED不亮或全部常亮

这是最常见的现象,可能原因包括:

  1. 管脚约束错误:检查.pdc文件中的管脚分配是否正确
  2. 极性理解错误:确认LED是共阳极还是共阴极连接
  3. 程序未正确下载:检查下载过程和下载模式设置
  4. 复位信号问题:确保复位信号正常工作

7.2 流水速度异常

如果流水速度与预期不符:

  1. 检查时钟分频计算是否正确
  2. 确认系统时钟频率是否为50MHz
  3. 查看综合后的时序报告,确认时钟网络延迟

7.3 个别LED不工作

如果大部分LED正常,只有个别不工作:

  1. 检查对应LED的硬件电路,包括电阻和LED本身
  2. 测量FPGA对应管脚是否有信号输出
  3. 确认约束文件中该管脚的配置正确

7.4 调试技巧分享

  1. 使用SignalTap逻辑分析仪:PDS工具内置了SignalTap功能,可以实时捕获内部信号,非常有助于调试
  2. 分模块验证:先验证时钟分频模块是否正常工作,再逐步添加其他功能
  3. 简化测试:可以先设计一个简单的LED闪烁程序,确认基本功能正常后再实现复杂逻辑
  4. 查阅官方文档:紫光同创提供了详细的器件手册和开发板资料,遇到问题时应该首先查阅相关文档

8. 项目总结与进阶学习建议

通过这个LED流水灯实验,我们完成了FPGA开发的全流程实践,包括:

  • 开发环境搭建
  • Verilog代码编写
  • 约束文件配置
  • 综合与实现
  • 程序下载与调试

这个简单的项目涵盖了FPGA开发的基本要素,是学习数字逻辑设计的良好起点。在实际操作中,我发现紫光同创PDS工具链虽然界面友好,但在一些细节处理上仍需注意,比如约束文件的语法与其他厂商略有不同。

对于想要进一步学习的开发者,建议从以下几个方向深入:

  1. 学习更复杂的时序电路设计,如FSM(有限状态机)
  2. 研究FPGA的时钟管理和时序约束
  3. 尝试外设接口开发,如UART、SPI、I2C等
  4. 探索基于FPGA的嵌入式系统设计,如使用RISC-V软核

国产FPGA生态正在快速发展,掌握紫光同创FPGA开发技术将为未来的职业发展带来更多机会。这个流水灯项目虽然简单,但已经包含了FPGA开发的核心思想,希望读者能够通过这个入门实验,开启自己的FPGA开发之旅。