FPGA入门笔记006——状态机设计实例
1.FPGA入门笔记0012.# FPGA入门笔记002——译码器
3.FPGA入门笔记006——状态机设计实例
4.FPGA入门笔记005——阻塞赋值和非阻塞赋值的区别5.FPGA入门笔记004——BCD计数器设计与使用6.FPGA入门笔记003——计数器IP核调用与验证7.FPGA入门笔记013——嵌入式块RAM使用之FIFO8.FPGA入门笔记012——嵌入式块RAM应用之ROM9.FPGA入门笔记011_B——搭建串口收发与存取双口RAM简易应用系统10.FPGA入门笔记011_A——嵌入式块RAM的使用11.FPGA入门笔记010——UART串口接收模块设计12.FPGA入门笔记009——UART串口发送模块设计13.FPGA入门笔记008——数码管动态扫描设计与验证14.FPGA入门笔记007_A——按键消抖模块设计与验证(状态机、$random、仿真模型、task语法)状态分析:
状态1:等待“H”的到来,如果检测到“H”,进入状态2,检测“e”,否则一直等待“H”;
状态2:检测当前字符是否是“e”,如果是“e”,跳转到状态3,检测“l”,否则,回到状态1,重新等待“H”;
状态3:检测当前字符是否是“l”,如果是“l”,跳转到状态4,检测“l”,否则,回到状态1,重新等待“H”;
状态4:检测当前字符是否是“l”,如果是“l”,跳转到状态5,检测“o”,否则,回到状态1,重新等待“H”;
状态5:检测当前字符是否是“o”,如果是“o”,驱动led控制引脚发生状态翻转,同时回到状态1,等待下一个“H”的到来,否则,回到状态1,重新等待“H”;
代码实现:
module Hello( Clk, Rst_n, data, led ); input Clk; //50M input Rst_n; //低电平复位 input [7:0]data; //存储字符的ASCII码 output reg led; localparam CHECK_H = 5'b0_0001, CHECK_e = 5'b0_0010, CHECK_la = 5'b0_0100, CHECK_lb = 5'b0_1000, CHECK_o = 5'b1_0000; reg[4:0]state; //状态 //一段式状态机、两段式状态机、三段式状态机 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n)begin led <= 1'b1; //led低电平有效 state <= CHECK_H; //当复位时,等待H状态 end else case(state) CHECK_H: if(data == "H") state <= CHECK_e; else state <= CHECK_H; CHECK_e: if(data == "e") state <= CHECK_la; else state <= CHECK_H; CHECK_la: if(data == "l") state <= CHECK_lb; else state <= CHECK_H; CHECK_lb: if(data == "l") state <= CHECK_o; else state <= CHECK_H; CHECK_o: begin state <= CHECK_H; if(data == "o") led <= ~led; else led <= led; end default:state <= CHECK_H; endcase end endmodule
语法知识:
localparam
在Verilog中,可以使用localparam(本地参数)来声明常量。
(注:parameter可用作在顶层模块中例化底层模块时传递参数的接口,localparam的作用域仅仅限于当前module,不能作为参数传递的接口。)
例如:
localparam CHECK_H = 5'b0_0001, CHECK_e = 5'b0_0010, CHECK_la = 5'b0_0100, CHECK_lb = 5'b0_1000, CHECK_o = 5'b1_0000;
(注:语句与语句之间用","隔开,最后一个语句末尾用";"。)
testbench文件代码如下:
`timescale 1ns/1ns `define clock_period 20 module Hello_tb; reg Clk; reg Rst_n; reg [7:0]ASCII; wire led; Hello Hello0( .Clk(Clk), .Rst_n(Rst_n), .data(ASCII), .led(led) ); initial Clk = 1; always #(`clock_period/2) Clk = ~Clk; initial begin Rst_n = 0; ASCII = 0; #(`clock_period*200); Rst_n = 1; #(`clock_period*200 + 1); //"+1"操作使ASCII信号与时钟信号上升沿不对齐,方便查看仿真结果 forever begin ASCII = "I"; #(`clock_period); ASCII = "A"; #(`clock_period); ASCII = "M"; #(`clock_period); ASCII = "X"; #(`clock_period); ASCII = "i"; #(`clock_period); ASCII = "a"; #(`clock_period); ASCII = "o"; #(`clock_period); ASCII = "M"; #(`clock_period); ASCII = "e"; #(`clock_period); ASCII = "i"; #(`clock_period); ASCII = "g"; #(`clock_period); ASCII = "e"; #(`clock_period); ASCII = "H"; #(`clock_period); ASCII = "E"; #(`clock_period); ASCII = "M"; #(`clock_period); ASCII = "l"; #(`clock_period); ASCII = "H"; #(`clock_period); ASCII = "E"; #(`clock_period); ASCII = "L"; #(`clock_period); ASCII = "L"; #(`clock_period); ASCII = "O"; #(`clock_period); ASCII = "H"; #(`clock_period); ASCII = "e"; #(`clock_period); ASCII = "l"; #(`clock_period); ASCII = "l"; #(`clock_period); ASCII = "o"; #(`clock_period); ASCII = "l"; end end endmodule
语法知识:
forever 循环
forever 循环语法格式如下:
forever begin … end
forever 语句表示永久循环,不包含任何条件表达式,一旦执行便无限的执行下去,系统函数 $finish 可退出 forever。forever 相当于while(1) 。通常,forever 循环是和时序控制结构配合使用的。
本文作者:Yamada_Ryo
本文链接:https://www.cnblogs.com/little55/p/17851843.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
合集:
FPGA入门笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步