欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 【PFPGA学习】状态机思想编程HDLbitsFPGA练习

【PFPGA学习】状态机思想编程HDLbitsFPGA练习

2025/4/9 18:30:09 来源:https://blog.csdn.net/2301_78895982/article/details/147016189  浏览:    关键词:【PFPGA学习】状态机思想编程HDLbitsFPGA练习

目录

一、用状态机实现LED流水灯

1.1状态机思想

1.2状态机思想LED流水灯

1.3 modesim仿真

1.4 FPGA烧录实现

二、CPLD和FPGA芯片

1. 核心结构与技术原理

2. 性能与容量

3. 适用场景

4. 选型建议

三、HDLbitsFPGA练习记录(combinational logic)

练习一:7420chip

练习二:电路描述

 练习三、多路选择器1-9

练习四:Full adder

 练习五、Bcdadd4

四、总结

前言:

  1. 掌握状态机思想在FPGA开发中的应用。

  2. 学习Modelsim仿真与DE2-115开发板验证流程。

  3. 理解CPLD与FPGA技术差异及适用场景。

  4. 通过HDLbits刷题巩固组合逻辑设计能力。

一、用状态机实现LED流水灯

1.1状态机思想

状态机(Finite State Machine, FSM) 是一种描述系统状态转移的数学模型,广泛应用于时序逻辑设计。在FPGA中,状态机通过明确的状态划分和转移条件,简化复杂控制流程的设计。

①现态:是指当前所处的状态。

②条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。

③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。

④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

核心要素

  • 现态(Current State):系统当前所处的状态。

  • 事件(Event):触发状态迁移的条件(如用户输入、传感器信号等)。

  • 动作(Action):状态迁移时执行的操作(如开启设备、发送数据等)。

  • 次态(Next State):事件触发后系统将进入的新状态。

分类与模型

  • Moore型:输出仅由当前状态决定(如交通信号灯的红绿灯切换)。

  • Mealy型:输出由当前状态和输入共同决定(如网络协议中的应答机制)。

  • 确定型(DFA):每个状态对同一事件有唯一迁移路径。

  • 非确定型(NFA):同一事件可能触发多个迁移路径,需额外逻辑处理。

1.2状态机思想LED流水灯

1.代码编写(verilog):

状态机通过定义不同的状态和状态之间的转换逻辑,能够精确地控制LED灯的点亮顺序。在代码中,S0S7这8个状态分别对应着8个LED灯依次点亮的状态。通过状态的转换,实现了LED流水灯的效果。

module led_fsm(input clk,          // 50MHz时钟input rst_n,        // 复位信号(低有效)output reg [7:0] led
);// 状态定义(8个状态)localparam [2:0] S0=0, S1=1, S2=2, S3=3, S4=4, S5=5, S6=6, S7=7;reg [2:0] state;reg [24:0] cnt;wire en = (cnt == 25'd24_999_999); // 分频使能// 分频计数器always @(posedge clk or negedge rst_n) beginif (!rst_n) cnt <= 0;else if (en) cnt <= 0;else cnt <= cnt + 1;end// 状态机主逻辑always @(posedge clk or negedge rst_n) beginif (!rst_n) beginstate <= S0;led <= 8'b00000001; // 初始状态S0点亮LED0endelse if (en) begincase(state)S0: begin led <= 8'b00000010; state <= S1; end  //S0→S1(第2个LED亮)S1: begin led <= 8'b00000100; state <= S2; end  //S1→S2(第3个LED亮)S2: begin led <= 8'b00001000; state <= S3; end  //S2→S3(第4个LED亮)S3: begin led <= 8'b00010000; state <= S4; end  //S3→S4(第5个LED亮)S4: begin led <= 8'b00100000; state <= S5; end  //S4→S5(第6个LED亮)S5: begin led <= 8'b01000000; state <= S6; end  //S5→S6(第7个LED亮)S6: begin led <= 8'b10000000; state <= S7; end  //S6→S7(第8个LED亮)S7: begin led <= 8'b00000001; state <= S0; end  //S7→S0(第1个LED亮,循环)default: state <= S0;                          // 默认回到初始状态endcaseendend
endmodule

1.3 modesim仿真

创建工程文件后,跟着步骤来进行仿真操作(可参考参考文件三仿真步骤比较详细,由于之前的博客写过步骤,我就只保存截图了关键部分)

设置成为顶层文件后编译代码

点击Processing-->Start-->Start test bench template writer,这时我们的文件夹之下已经有了一个example.vt文件

(默认是保存在当前目录simulationmodelsim文件夹下的.vt格式文件。)对刚才生成的文件进行修改(可以直接复制下面代码,注意修改文件名称),然后在编译一次

`timescale 1ns/1nsmodule led_fsm;reg        clk;reg        rst_n;reg        data;wire       pos_edge;wire       neg_edge;wire       data_edge;wire [1:0] D;example   u1(.clk(clk),.rst_n(rst_n),.data(data),.pos_edge(pos_edge),.neg_edge(neg_edge),.data_edge(data_edge),.D(D));//产生时钟激励initial  clk = 1; always #10  clk = ~clk;//输入激励initial  begin rst_n=0;data=0;#100;rst_n = 1;#50data=1;#201;data=0;#201;data=1; #101;data=0;	#200;$stop;endendmodule 

 现在设置仿真,点击Tools-->Options-->EDA ToolsOptions选项,点击浏览Modelsim安装目录下的Win64或者Win32

4、然后对仿真文件设置点击Assignments-->Settings,再点击下面的Simulation按照如图设置

5、选择上面的Compile test bench点击后面Test Bench进入选择,点击New新建

按照顺序先编辑名字,然后浏览刚才的.vt文件,最后点击Add添加达到如下图效果,再点击OK,这里如果浏览的是.vo文件则后面仿真需要自己设置时间及电平,然后一直点击OK回到代码编辑界面

 来到主页点击:自动跳转至Modelsim,选择下面的Wave即可看到波形。

 

1.4 FPGA烧录实现

 配置确认引脚,烧录程序(可参考之前的FPGA文件,有详细记录每一步操作,这里就给出关键操作截图)

 烧录效果:

【博客调用】状态机思想实习流水灯

二、CPLD和FPGA芯片

CPLD(Complex Programmable Logic Device,复杂可编程逻辑器件)和FPGA(Field-Programmable Gate Array,现场可编程门阵列)是可编程逻辑器件的两大分支,它们在结构、性能和应用场景上有显著差异。

1. 核心结构与技术原理

特性CPLDFPGA
逻辑单元基于**乘积项(Product-Term)**结构,包含与阵列和或阵列,逻辑块较大且固定。基于**查找表(LUT)**结构,每个LUT(如4/6输入)模拟任意组合逻辑,逻辑块细粒度。
互连资源全局总线式互连,延迟固定且确定性高分布式可编程互连,延迟可变但灵活性高
存储技术非易失性(如Flash/EEPROM),配置掉电保留。易失性(SRAM为主),需外部配置芯片(如Flash)存储代码。
触发器数量较少,适合组合逻辑为主的设计。大量触发器,支持复杂时序逻辑。

2. 性能与容量

指标CPLDFPGA
逻辑规模较小(数百至数千逻辑门)大(数万至数百万逻辑门)
运行速度高(固定延迟,适合高速控制)中高(依赖布线优化,适合并行计算)
功耗低(静态功耗为主)中高(动态功耗显著,尤其高频场景)
配置时间毫秒级(非易失性,上电即用)秒级(需从外部加载配置)

3. 适用场景

场景CPLDFPGA
简单控制逻辑电源管理、接口转换、总线桥接。不适用(资源浪费)。
复杂算法处理不适用(容量不足)。图像处理、通信协议(如5G)、AI推理。
确定性时序需求高(如电机控制、工业PLC)。低(时序受布线影响)。
原型验证不适用。高(可快速迭代设计)

4. 选型建议

  • 选择CPLD

    • 需要非易失性存储,上电即用。

    • 设计简单(如组合逻辑、小型状态机)。

    • 对功耗敏感(电池供电设备)。

  • 选择FPGA

    • 处理复杂算法(如FFT、卷积运算)。

    • 需要动态重构(如通信协议切换)。

    • 高并行性需求(如数据中心加速)。

三、HDLbitsFPGA练习记录(combinational logic)

练习点击这里:HDLBitshttps://hdlbits.01xz.net/wiki/Main_Page

 实验记录:

练习一:7420chip

7400 系列集成电路是一系列每个都包含几个门电路的数字芯片。7420 是一种包含两个 4 输入 NAND 门的芯片。
创建一个具有与 7420 芯片相同功能的模块。该模块有 8 个输入和 2 个输出。

分析:

  • 每个 4 输入的 NAND 门的逻辑功能是:当所有输入都为 1 时,输出为 0;否则,输出为 1。
  • 每个 4 输入 NAND 门的输入是4个输入信号,输出是 1 个信号。

代码:

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

 仿真电路图;

练习二:电路描述

电路 B 可以通过以下模拟波形来描述:

代码:

module top_module ( input x, input y, output z );assign z = ~(x ^ y);
endmodule

仿真图:

 练习三、多路选择器1-9

设计一个 16 位宽、9 对 1 的多路复用器。当 sel=0 时选择 a,当 sel=1 时选择 b,以此类推。对于未使用的模式(sel=9 到 15),将所有输出位都设置为 '1'。

代码如下:

module top_module (input [15:0] a,input [15:0] b,input [15:0] c,input [15:0] d,input [15:0] e,input [15:0] f,input [15:0] g,input [15:0] h,input [15:0] i,input [3:0] sel,output logic [15:0] out
);// Case语句只能用在过程性块(always块)中// 这是一个组合逻辑电路,所以使用组合逻辑的always @(*)块。always @(*) beginout = '1;    // '1 是一种特殊的字面量语法,表示所有位都为1的数。// '0、'x 和 'z 也是有效的。// 给 'out' 赋一个默认值,case (sel)4'h0: out = a;4'h1: out = b;4'h2: out = c;4'h3: out = d;4'h4: out = e;4'h5: out = f;4'h6: out = g;4'h7: out = h;4'h8: out = i;endcaseendendmodule

 仿真波形图:

 

练习四:Full adder

创建一个全加器。全加器接收三个位(包括进位输入)并输出和以及进输出。位

预期的解决方案长度:约 2 行。

代码:

module top_module (input a,         // 输入位ainput b,         // 输入位binput cin,       // 进位输入output sum,      // 和输出output cout      // 进位输出
);assign {cout, sum} = a + b + cin;  // 使用加法运算直接计算和与进位endmodule

代码解释

  1. 模块接口

    • input ainput b:两个加数位。

    • input cin:进位输入(来自低位的进位)。

    • output sum:加法结果的和。

    • output cout:进位输出(用于更高位的加法)。

  2. 逻辑实现

    • 使用 assign 语句实现组合逻辑。

    • a + b + cin:直接对三个输入位进行加法运算。

    • {cout, sum}:将加法结果的高位赋值给 cout(进位输出),低位赋值给 sum(和输出)。

 练习五、Bcdadd4

您将获得一个名为 bcd_fadd 的 BCD(二进制编码十进制)一位数加法器,它能将两个 BCD 数字以及进位输入相加,并生成和以及进位输出。

module bcd_fadd (input [3:0] a,input [3:0] b,input     cin,output   cout,output [3:0] sum );

实例化 4 个 bcd_fadd 模块以创建一个 4 位 BCD 溪流进位加法器。您的加法器应将两个 4 位 BCD 数字(打包成 16 位向量)和一个进位输入相加,以产生一个 4 位和进位输出。

代码:

module top_module (input [15:0] a, b,  // 输入的两个 4 位 BCD 数字,打包成 16 位向量input cin,         // 进位输入output cout,       // 进位输出output [15:0] sum  // 4 位 BCD 和,打包成 16 位向量
);// 中间进位信号,用于连接各个 BCD 加法器wire c1, c2, c3;  // 实例化 4 个 bcd_fadd 模块bcd_fadd fa0 (.a(a[3:0]),      // 第一个 BCD 数字的最低位.b(b[3:0]),      // 第二个 BCD 数字的最低位.cin(cin),       // 进位输入.cout(c1),       // 输出到下一个加法器的进位.sum(sum[3:0])   // 第一个 BCD 位的和);bcd_fadd fa1 (.a(a[7:4]),      // 第一个 BCD 数字的次低位.b(b[7:4]),      // 第二个 BCD 数字的次低位.cin(c1),        // 从上一个加法器传来的进位.cout(c2),       // 输出到下一个加法器的进位.sum(sum[7:4])   // 第二个 BCD 位的和);bcd_fadd fa2 (.a(a[11:8]),     // 第一个 BCD 数字的次高位.b(b[11:8]),     // 第二个 BCD 数字的次高位.cin(c2),        // 从上一个加法器传来的进位.cout(c3),       // 输出到下一个加法器的进位.sum(sum[11:8])  // 第三个 BCD 位的和);bcd_fadd fa3 (.a(a[15:12]),    // 第一个 BCD 数字的最高位.b(b[15:12]),    // 第二个 BCD 数字的最高位.cin(c3),        // 从上一个加法器传来的进位.cout(cout),     // 最终的进位输出.sum(sum[15:12]) // 第四个 BCD 位的和);endmodule

 练习结果仿真图:

 

四、总结

本次实验完成了,收获颇丰,进一步掌握状态机思想,又一次复习了仿真操作,对FPGA的掌握更上一层楼。还学会了使用HDLbits 用来模拟仿真波形图,很是方便。在这个在线网站上也可以自己做题,理解底层电路设计的更多知识,收获很大,这是本人实验时候的一个记录过程,希望与大家共勉!

另外,本人才疏学浅,要是有错误的地方,还望大家海涵,感谢您的阅读!

参考文献:

什么是状态机(Finite-state machine)?-CSDN博客

FPGA学习(四)——状态机重写LED流水灯并仿真-CSDN博客

Quartus使用步骤及联合Modelsim仿真教程_quartus仿真-CSDN博客

HDLbits刷题中文完整版,按照刷题网站顺序每日更新一道_hdlbits网站中文版-CSDN博客

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词