Lattice ICE40 FPGA UltraPlus 扩展板, 基于 APIO 的有限状态机(FSM)

本文将聚焦于 基于 APIO 工具链的 SystemVerilog Mealy有限状态机 (FSM) 的实现方法。

Lattice ICE40 FPGA UltraPlus 扩展板是一款性能出色的开发板。

本文将基于该开发板,使用 SystemVerilog 硬件描述语言,通过 APIO 工具链实现一个 Mealy 有限状态机的示例。APIO 工具链已原生支持 SystemVerilog 硬件描述语言。本示例对应的 Mealy 有限状态机状态图如下所示。

此前实现的摩尔型有限状态机包含红、蓝、绿三种状态,其输出仅由有限状态机的内部状态编码决定(状态编码完全来源于状态寄存器的状态,而状态寄存器是有限状态机的存储单元)。与之不同的是,Mealy 有限状态机的输出 rgb(用于驱动开发板上的 RGB LED),由外部输入信号next内部当前状态共同控制。下图为摩尔型有限状态机的结构框图,可直观对比两者的差异。

从上图可以看出,摩尔型有限状态机的输出仅由组合逻辑电路根据内部状态寄存器的当前值生成。而Mealy有限状态机的输出则由输入信号(见下图红线标注)和内部状态编码共同决定,具体结构如下所示。

在传统有限状态机的设计流程中,可根据实际需求选择不同的内部状态编码方式。常用的编码方式包括顺序编码、格雷编码、约翰逊编码和独热编码,具体选择需匹配应用场景的需求:

  • 独热编码:在 FPGA 开发中应用广泛,因为 FPGA 具备充足的触发器资源;
  • 顺序编码与格雷编码:多用于 CPLD 和资源紧凑的 ASIC 设计,这类器件的触发器资源相对稀缺。

SystemVerilog 综合编译器提供两种编码选择模式:

  1. 用户自定义模式:由开发者指定编码方式;
  2. 自动选择模式:编译器根据目标器件的资源特性自动匹配最优编码方式。

Mealy有限状态机的一个典型特性是:在状态数量相同的情况下,能实现更多的输出状态组合。这是因为其输出由组合逻辑结合异步输入信号next生成。基于这一特性,在满足设计需求的前提下,部分摩尔型有限状态机可转换为Mealy有限状态机,通过状态合并减少所需的状态数量(注:该转换并非适用于所有场景,需结合具体设计需求判断可行性)。

前文的状态图已明确Mealy有限状态机的状态定义,以及基于外部输入信号next的状态转移规则。该离散输入信号next与开发板上的按键开关相连,可在 FPGA 运行过程中异步控制 RGB LED 的输出颜色。为了让状态变化的效果肉眼可见,需通过一个辅助分频器,将开发板的 12 MHz 时钟信号进行分频处理。

本示例中,Mealy 有限状态机的输出rgb,由有限状态机当前状态(与摩尔型一致)和输入信号next 通过组合逻辑共同生成,并最终驱动 Lattice ICE40 FPGA UltraPlus 扩展板的 RGB LED。状态机的三种状态(红、蓝、绿)对应 RGB LED 的基础颜色,但这并非next信号有效时的实际输出颜色:当输入信号next无效时,无论状态机处于何种状态,RGB LED 均输出黄色(对应电平为r=1g=1b=0),该逻辑由Mealy有限状态机的状态图定义。

系统中设计了异步复位功能,复位后状态机将进入红色状态。根据状态图定义,当离散输入信号next无效时,状态机在三个状态下的 RGB LED 输出均为黄色。

本示例的实现依赖以下工程文件,其中顶层 SystemVerilog 文件为top.sv

//Digikey Coffee Cup SystemVerilog HDL Mealy State Machine

module top(input [3:0] SW, input clk, output LED_R, output LED_G, output LED_B);
   
   Mealy fsm_sm1(.clk(counter[23]),.reset(SW[0]), .next(SW[1]), .r(LED_R), .g(LED_G), .b(LED_B));
	
   //Auxiliary counter to divide the clock to be used in the Mealy State Machine Demo
   reg [23:0] counter;	
	
   initial begin
      counter = 0;
   end

   always_ff @(posedge clk)
   begin
      counter <= counter + 1;
   end

endmodule

Mealy 有限状态机的功能实现文件为mealy_fsm.sv

//Digikey Coffee Cup SystemVerilog HDL Mealy State Machine

module Mealy(
	input logic clk,
	input logic reset,
	input logic next,
	output logic r, g, b
);

	typedef enum logic [1:0] {RED, BLUE, GREEN} statetype;
	statetype state, nextstate;
	
	// state register
	always_ff @(posedge clk, posedge reset)
		if (reset) 
			state <= RED;
		else 
			state <= nextstate;
	
	// next state logic
	always_comb
	case (state)
		RED: if (next) nextstate = BLUE;
			else nextstate = RED;
		BLUE: if (next) nextstate = GREEN;
			else nextstate = BLUE;
		GREEN: if (next) nextstate = RED;
			else nextstate = GREEN;
		default: nextstate = RED;
	endcase
	
	// output logic (not simplified)
	assign r = ~( next&(state == RED & state != GREEN & state != BLUE) | ~next&(1) );
	assign b = ~( next&(state != RED & state != GREEN & state == BLUE) | ~next&(0) );
	assign g = ~( next&(state != RED & state == GREEN & state != BLUE) | ~next&(1) );
	
endmodule

工程目录下的所有 SystemVerilog 文件及 APIO 工程配置文件如下所示:

├── apio.ini
├── mealy_fsm.sv
├── pinout.pcf
└── top.sv

apio.ini为工程配置文件,内容如下:

; DigiKey Cofffe Cup Apio project file.

[env:default]

; Board id.
board = ice40-up5k

; Top module name (top.sv)
top-module = top

引脚约束文件pinout.pcf的内容如下:

# DigiKey Cofffe Cup Apio pins definitions file

set_io LED_R 41
set_io LED_G 40
set_io LED_B 39
set_io SW[0] 23
set_io SW[1] 25
set_io SW[2] 34
set_io SW[3] 43
set_io clk 35

首先调用 APIO 的代码检查命令,进行语法及逻辑错误检测:

Digikey_Coffee_Cup # apio lint

随后执行工程构建命令:

Digikey_Coffee_Cup # apio build

通过以下命令可查看 FPGA 资源的占用情况:

Digikey_Coffee_Cup # apio report

该命令将输出目标 FPGA 的资源利用率报告:

Using env default (ice40-up5k)
Setting shell vars.
----------------------------------------------------------------------------------------------------------------------------------------
Formatting pnr report.

FPGA Resource Utilization                         
┌──────────────────┬────────┬──────────┬─────────┐
│  RESOURCE        │  USED  │   TOTAL  │  UTIL.  │
├──────────────────┼────────┼──────────┼─────────┤
│  ICESTORM_DSP    │        │       8  │         │
│  ICESTORM_HFOSC  │        │       1  │         │
│  ICESTORM_LC     │    32  │    5280  │     0%  │
│  ICESTORM_LFOSC  │        │       1  │         │
│  ICESTORM_PLL    │        │       1  │         │
│  ICESTORM_RAM    │        │      30  │         │
│  ICESTORM_SPRAM  │        │       4  │         │
│  IO_I3C          │        │       2  │         │
│  SB_GB           │     2  │       8  │    25%  │
│  SB_I2C          │        │       2  │         │
│  SB_IO           │     8  │      96  │     8%  │
│  SB_LEDDA_IP     │        │       1  │         │
│  SB_RGBA_DRV     │        │       1  │         │
│  SB_SPI          │        │       2  │         │
│  SB_WARMBOOT     │        │       1  │         │
└──────────────────┴────────┴──────────┴─────────┘

Clock Information                     
┌────────────────┬───────────────────┐
│  CLOCK         │  MAX SPEED [Mhz]  │
├────────────────┼───────────────────┤
│  clk           │            79.74  │
├────────────────┼───────────────────┤
│  counter[23]_  │           232.23  │
└────────────────┴───────────────────┘

Run 'apio report --verbose' for more details.
===================================================== [SUCCESS] Took 0.22 seconds ======================================================

若需查看本示例的 FPGA 配置可视化结构图,可执行以下命令:

Digikey_Coffee_Cup # apio graph

该命令将生成一个.svg 格式的文件,文件中包含 FPGA 配置的可视化框图,如下图所示。

在此之前,请确保 Lattice ICE40 FPGA UltraPlus 扩展板上的跳线已正确连接,以支持 FLASH 烧录操作。完成跳线配置后,执行以下命令将配置文件下载至 FPGA 中:

plaintext

Digikey_Coffee_Cup # apio upload

下述视频展示了Mealy有限状态机在 Lattice ICE40 FPGA UltraPlus 扩展板上的实际运行效果。

至此,本文详细介绍了如何在Lattice ICE40 UltraPlus 扩展板上,通过 APIO 工具链实现基于 SystemVerilog 的Mealy有限状态机。 Lattice ICE40 FPGA UltraPlus 扩展板是一款性价比高、配备原型开发区域的 FPGA 开发板,可适用于多种应用场景,目前可通过得捷电子(DigiKey)购买。