ROCCHI THE ROCK!|

Yamada_Ryo

园龄:1年4个月粉丝:3关注:5

FPGA入门笔记006——状态机设计实例

状态分析:

微信图片_20231123142212

状态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 中国大陆许可协议进行许可。

posted @   Yamada_Ryo  阅读(76)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起