状态机思想编程

文章目录


一、状态机思想重新写一个 LED流水灯的FPGA代码

1.状态机的概念

状态机的基本要素有 3 个,其实我们在第一节的举例中都有涉及,只是没有点明,它们是:状态、输出和输入。

1、状态:也叫状态变量。在逻辑设计中,使用状态划分逻辑顺序和时序规律。比如:设计伪随机码发生器时,可以用移位寄存器序列作为状态;在设计电机控制电路时,可以以电机的不同转速作为状态;在设计通信系统时,可以用信令的状态作为状态变量等。

2、输出:输出指在某一个状态时特定发生的事件。如设计电机控制电路中,如果电机转速过高,则输出为转速过高报警,也可以伴随减速指令或降温措施等。

3、输入:指状态机中进入每个状态的条件,有的状态机没有输入条件,其中的状态转移较为简单,有的状态机有输入条件,当某个输入条件存在时才能转移到相应的状态。

根据状态机的输出是否与输入条件相关,可将状态机分为两大类:摩尔(Moore)型状态机和米勒(Mealy)型状态机。

2.代码设计

bash 复制代码
// 流水灯模块代码:led_fsm.v
module led_fsm(
    input        clk,     // 时钟信号 (50MHz)
    input        rst_n,   // 复位信号 (低有效)
    output reg [3:0] led  // LED输出,低电平点亮
);

// 定义状态编码
parameter S0 = 2'b00;    // LED0亮
parameter S1 = 2'b01;    // LED1亮
parameter S2 = 2'b10;    // LED2亮
parameter S3 = 2'b11;    // LED3亮

reg [1:0] state;         // 当前状态
reg [1:0] next_state;    // 下一状态
reg [24:0] counter;      // 计时器(0.5秒@50MHz)

// 状态寄存器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        state <= S0;
    else
        state <= next_state;
end

// 状态转移逻辑
always @(*) begin
    case(state)
        S0: next_state = (counter == 25'd24_999_999) ? S1 : S0;
        S1: next_state = (counter == 25'd24_999_999) ? S2 : S1;
        S2: next_state = (counter == 25'd24_999_999) ? S3 : S2;
        S3: next_state = (counter == 25'd24_999_999) ? S0 : S3;
        default: next_state = S0;
    endcase
end

// 计数器逻辑
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        counter <= 25'd0;
    else if(next_state != state)
        counter <= 25'd0;
    else
        counter <= counter + 25'd1;
end

// 输出逻辑
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        led <= 4'b1110;  // 初始状态LED0亮
    else begin
        case(state)
            S0: led <= 4'b1110;
            S1: led <= 4'b1101;
            S2: led <= 4'b1011;
            S3: led <= 4'b0111;
            default: led <= 4'b1111;
        endcase
    end
end

endmodule

代码解释:

使用 二进制编码(2位可表示4个状态)。每个状态对应一个LED点亮(S0→LED0,S1→LED1,依此类推)。

state 和 next_state 用于实现状态寄存器和组合逻辑的分离。

计数器阈值:24_999_999 对应 0.5 秒计时(50MHz时钟下,周期20ns,总时间=25,000,000×20ns=500ms)。

状态转移条件:当计数器达到阈值时切换到下一状态,否则保持当前状态。

复位清零:复位或状态即将切换时计数器清零。连续计数:在状态保持期间,每个时钟周期加1。低电平有效:0 表示点亮LED(例如 4'b1110 表示LED0亮)。同步输出:在时钟上升沿更新输出,避免毛刺。

二、CPLD和FPGA芯片的主要技术区别与适用场合

二、适用场合

CPLD 的典型应用

1.控制密集型任务

状态机、总线接口控制(如PCI、I2C)、逻辑粘合(Glue Logic)。简单数据处理(编码转换、电平转换)。

2.实时性与可靠性要求高的场景

工业控制、电源管理、电机驱动。需要快速上电启动(毫秒级配置加载)。

3.低功耗与成本敏感设计

便携设备、加密芯片控制、简单协议转换。

FPGA 的典型应用

1.数据密集型任务

高速信号处理(图像处理、通信基带)、数字滤波器、FFT。并行计算(AI加速、区块链哈希运算)。

2.复杂系统原型与动态重构

ASIC/SoC原型验证、软件定义无线电(SDR)。支持部分动态重配置(如Xilinx的部分型号)。

3.高吞吐量接口

高速串行通信(PCIe、10G以太网)、视频编解码(H.265/AV1)。数据中心加速(SmartNIC、存储控制器)。

三、hdlbitsFPGA教程网站上进行学习

1.创建一个具有两个 2 位输入A1:0和B1:0的电路,并产生一个输出z。如果A = B ,则z的值应为 1 ,否则z应为 0。

bash 复制代码
module top_module ( input [1:0] A, input [1:0] B, output z ); 
    assign z = (A ==B) ? 1'B1 : 1'B0;
endmodule

2.创建一个半加法器。半加器将两位相加(没有进位)得到加和和进位。

bash 复制代码
module top_module( 
    input a, b,
    output cout, sum );
	assign sum = a^b;
    assign cout = a&b;
endmodule

3.创建一个全加器。全加器将三位相加(包括进位)并产生和和进位。

bash 复制代码
module top_module( 
    input a, b, cin,
    output cout, sum );
    assign sum = a^b^cin;
    assign cout = a&b | a&cin | b&cin;
endmodule

4.创建 3 个实例来创建一个 3 位二进制波纹进位加法器。加法器将两个 3 位数字和一个进位相加产生一个 3 位加和和进位。为了鼓励实例化全加器,还要输出纹波进位加法器中每个全加器的进位。cout2 是最后一个全加器的最终进位,也是您通常看到的进位。

bash 复制代码
//第一种方法
module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );
    add1 u1 (.a(a[0]),.b(b[0]),.cin(cin),.sum(sum[0]),.cout(cout[0]));
    add1 u2 (.a(a[1]),.b(b[1]),.cin(cout[0]),.sum(sum[1]),.cout(cout[1]));
    add1 u3 (.a(a[2]),.b(b[2]),.cin(cout[1]),.sum(sum[2]),.cout(cout[2]));
endmodule
 
module add1 ( input a, input b, input cin,   output sum, output cout );
	assign sum = a^b^cin;
    assign cout = a&b|a&cin|b&cin;
endmodule

5.假设您有两个 8 位 的补码,a7:0 和 b7:0。这些数字相加产生 s7:0。还要计算是否发生了(有符号的)溢出。

bash 复制代码
module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); 
    assign s = a+b;
    assign overflow = (a[7]&b[7]&~s[7])|(~a[7]&~b[7]&s[7]);
endmodule
相关推荐
Hello-FPGA8 小时前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安9 小时前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha601610 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld10 小时前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家1 天前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家1 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
FPGA小迷弟2 天前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha1282 天前
CPU 内部结构是什么?---deepseek
fpga开发
abc light2 天前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072193 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理