【FPGA】状态机思想回顾流水灯

【FPGA】状态机思想回顾流水灯

一、LED流水灯实现

1. 基本要求

  • 用状态机思想写一个 LED流水灯的FPGA代码
  • 写出仿真测试代码,用Modelsim进行仿真分析
  • DE2-115板上验证

2. 状态机思想

用状态机思想的话,流水灯通常可以用几个状态来表示不同的LED亮的位置。

比如,每个状态对应一个LED亮,然后通过状态转移来实现流动的效果。由于我们流水灯是8个灯亮,所以对应8个状态。

所以,状态机的状态定义可能如下:

状态S0: LED0亮

状态S1: LED1亮

...

状态S7: LED7亮

流水灯就是一个状态持续一段时间再进入下一个状态。

3. 关键代码

复制代码
// File: led_flow.v
module led_flow(
    input clk,          // 50MHz时钟 (DE2-115 PIN_Y2)
    input rst_n,        // 复位信号 (低电平有效)
    output reg [7:0] led// LED输出 (DE2-115 LEDG7-LEDG0)
);

// 状态定义
localparam S0 = 3'b000; // 初始状态:LED0亮
localparam S1 = 3'b001;
localparam S2 = 3'b010;
localparam S3 = 3'b011;
localparam S4 = 3'b100;
localparam S5 = 3'b101;
localparam S6 = 3'b110;
localparam S7 = 3'b111;

// 内部信号
reg [2:0] state;        // 当前状态
reg [24:0] cnt;         // 分频计数器
wire en;                // 状态切换使能(0.5Hz)

// 0.5Hz分频(0.5秒切换)
assign en = (cnt == 25'd24_999_999); // 50MHz/(25M+1) ≈ 0.5Hz

// 分频计数器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) cnt <= 0;
    else if(en) cnt <= 0;
    else cnt <= cnt + 1;
end

// 状态机主逻辑
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state <= S0;
        led <= 8'b0000_0001; // 初始状态
    end
    else if(en) begin
        case(state)
            S0: begin led <= 8'b0000_0010; state <= S1; end
            S1: begin led <= 8'b0000_0100; state <= S2; end
            S2: begin led <= 8'b0000_1000; state <= S3; end
            S3: begin led <= 8'b0001_0000; state <= S4; end
            S4: begin led <= 8'b0010_0000; state <= S5; end
            S5: begin led <= 8'b0100_0000; state <= S6; end
            S6: begin led <= 8'b1000_0000; state <= S7; end
            S7: begin led <= 8'b0000_0001; state <= S0; end
            default: state <= S0;
        endcase
    end
end

endmodule

4. 仿真测试

写完代码后,参考连接博客进行仿真。
Quartus使用步骤及联合Modelsim仿真教程-
知安的小白

操作步骤这篇博客讲的很清楚了,一同操作后的效果截图如下

仿真代码(tb_led_flow.v)

csharp 复制代码
// File: tb_led_flow.v
`timescale 1ns/1ps
module tb_led_flow();

reg clk;
reg rst_n;
wire [7:0] led;

// 实例化被测模块
led_flow uut(
    .clk(clk),
    .rst_n(rst_n),
    .led(led)
);

// 生成50MHz时钟
initial begin
    clk = 0;
    forever #10 clk = ~clk; // 20ns周期=50MHz
end

// 测试激励
initial begin
    // 初始化
    rst_n = 0;
    #100;
    rst_n = 1;
    
    // 观察10个状态周期
    #100000000; // 仿真10ms(实际应仿真更长时间)
    $stop;
end

endmodule

下面是仿真波形:

5. 效果演示

[FPGA]状态机思想回顾流水灯演示效果

二、CPLD和FPGA

1. 技术区别

特性 特性 FPGA
结构 乘积项逻辑 查找表(LUT)结构
逻辑容量 通常<10万门 可达数百万逻辑单元
布线结构 固定互联 可编程互联
时序特性 确定延迟 布线依赖延迟
存储资源 有限 包含专用Block RAM
配置方式 非易失,上电即用 通常需要外部配置芯片
功耗 低静态功耗 高动态功耗
适用场景 胶合逻辑、状态机 复杂算法、并行处理

2. 应用场景

  • CPLD典型应用:

    接口协议转换(UART、SPI)

    简单状态机控制

    地址译码电路

    上电时序管理

  • FPGA典型应用:

    数字信号处理(FIR滤波器)

    高速接口(PCIe、DDR)

    图像处理流水线

    协议加速(TCP/IP Offload)

三、HDLbits组合逻辑题目

HDLbits问题集(Verilog)精选题目及解答

题目1:Exams/m2014 q4g

复制代码
module top_module (
    input in1,
    input in2,
    input in3,
    output out);
    assign out = (~(in1^in2)^in3);
endmodule

题目2:Gates

Module Declaration

module top_module(

input a, b,

output out_and,

output out_or,

output out_xor,

output out_nand,

output out_nor,

output out_xnor,

output out_anotb

);

大概意思就是写个逻辑语句实现名称。

复制代码
module top_module( 
    input a, b,
    output out_and,
    output out_or,
    output out_xor,
    output out_nand,
    output out_nor,
    output out_xnor,
    output out_anotb
);
	assign out_and=a&b;
    assign out_or=a|b;
    assign out_xor=a^b;
    assign out_nand=~(a&b);
    assign out_nor=~(a|b);
    assign out_xnor=~(a^b);
    assign out_anotb=a&(~b);
endmodule

题目3:Arithmetic Circuits--Adder(加法器设计)

verilog 复制代码
 module top_module (
    input [3:0] x, 
    input [3:0] y, 
    output [4:0] sum);
    assign sum = x + y;
endmodule

题目4:7420

74LS20芯片内部逻辑电路如下,由两个nand(与非门)组成。需要写个语句实现7420功能。

verilog 复制代码
module top_module ( 
    input p1a, p1b, p1c, p1d,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
    assign p1y=~(p1a&p1b&p1c&p1d);
    assign p2y=~(p2a&p2b&p2c&p2d);
endmodule

题目5:Truthtable1

按真值表实现电路。

如果数电学的不好不知道怎么办的话,可以用logisim,点击Project->Analyze Circuit->Table:

再点击Build Circuit就生成电路图了。

verilog 复制代码
module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output f   // one output
);
    assign f=((~x3)&x2)|(x1&x3);
endmodule

四、实验总结

本次实验掌握了状态机编程思想,事实上,状态机思想也更简易更容易想到。

相关推荐
FPGA小迷弟10 小时前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha12810 小时前
CPU 内部结构是什么?---deepseek
fpga开发
abc light11 小时前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072191 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理
XMAIPC_Robot1 天前
-40~85℃宽温实测:RK3588 机器人控制器硬件底座,长时间 SLAM 定位稳定性验证
人工智能·fpga开发·机器人·边缘计算·arm+fpga·rk3588+fpga
樱木花道長1 天前
AMD Ross 深度系列 8:FAQ 七问七答(文末附网盘链接)
人工智能·fpga开发
FPGA小迷弟1 天前
FPGA 与无人机:从飞控实时性到智能载荷的硬件加速实践
人工智能·ai·fpga开发·架构·无人机·ai编程
低慢小uav1 天前
(已解决)Zynq芯片lwip协议栈,使用tcp作为服务器Service,接收大量数据时,长度接收正常,接收对数据校验,校验和异常分析
网络协议·tcp/ip·fpga开发
szxinmai主板定制专家1 天前
ARM+FPGA 数控机床控制器:选 CODESYS SoftMotion CNC,还是基于 LinuxCNC 自研搭建?架构、授权、实时性、量产风险深度对比
arm开发·fpga开发·codesys·数据采集卡·linuxcnc·rk3576
女神下凡1 天前
芯参谋(79):嵌入式学习进阶_(硬件与软件)深入实践指南
arm开发·单片机·嵌入式硬件·学习·fpga开发·设计规范