大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
今天给大侠带来“FPGA学习系列 altera"系列,持续更新。此学习心得是本人之前所写,所用设计软件为Quartus II 13.1,现Quartus II 新版本已更新到19 ,以下仅供初学者学习参考。后续会更新其他系列,敬请关注。话不多说,上货。
流水灯设计
对于每一个的小实验,我们都可以把它看作是一个小项目,逐步的去分析,设计,调试,最后完成功能。下面我们就开始我们的“小项目”。
项目名称:流水灯。
具体要求:复位时,四个灯全亮。正常工作时,四个灯做流水。每一个灯亮一秒钟。用状态机实现。
状态机的结构如下:
在实际的应用中,根据有限状态机是否使用输入信号,设计人员经常将其分为Moore型有限状态机和Mealy型有限状态机两种类型。
Moore型和Mealy型有限状态机的区别:Moore型有限状态机仅与当前状态有关,而与输入信号无关;Mealy型有限状态机不但与当前状态有关,而且还与状态机的输入信号有关。
Moore状态机是Mealy状态机的一种独特类型。
通过分析上述的“项目名称”和“具体要求”,我们可以设计出如下的架构:
系统设计:
1. 工程的名称:ledrun。
2. 在项目中,四个灯做流水,故而设置为四个状态。
3. 用一个计数器,计数一秒钟。
4. 状态转移图如下:
设计代码如下:
代码语言:javascript复制/*
模块名称:ledrun
模块功能:四个灯做流水,每一个灯亮一秒钟
作者:郝旭帅
邮箱:746833924@qq.com
*/
module ledrun (clk, rst_n, led);
input clk;
input rst_n; //低电平有效
output reg [3:0] led;
parameter T1s = 50_000_000;//参数设置
reg [25:0] count;//计数器(需要计数50M个周期)
reg [1:0] state;//四个状态
localparam s0 = 2'b00,//定义四个状态机参数
s1 = 2'b01,
s2 = 2'b10,
s3 = 2'b11;
always @ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
state <= s0;
count <= 26'd0;
led <= 4'b0000;
end
else
begin//状态机的关键字case()···endcase
case(state) //按照设计的状态转移图进行描述
s0 : begin
if (count < T1s - 1)
begin
led <= 4'b0111;
state <= s0;
count <= count 1;
end
else
begin
count <= 0;
state <= s1;
end
end
s1 : begin
if (count < T1s - 1)
begin
led <= 4'b1011;
state <= s1;
count <= count 1;
end
else
begin
count <= 0;
state <= s2;
end
end
s2 : begin
if (count < T1s - 1)
begin
led <= 4'b1101;
state <= s2;
count <= count 1;
end
else
begin
count <= 0;
state <= s3;
end
end
s3 : begin
if (count < T1s - 1)
begin
led <= 4'b1110;
state <= s3;
count <= count 1;
end
else
begin
count <= 0;
state <= s0;
end
end
default : state <= s0;
endcase
end
end
endmodule
解析:
parameter T1s = 50_000_000;参数设置。我们可以在例化时改变它。下板时,我们让参数为50_000_000,仿真时,我们让参数为5.如果仿真50_000_000时间将会很长,我们只做一下简单的验证就可以。
计数器计数为什么到50_000_000 – 1? 我们的本地晶振是50MHz,周期为20ns。如果计数到1秒钟的话,应该需要计50_000_000个数。假设我们要计5个数,从0开始计,那么到4(5-1)就可以了。
下面在激励中,笔者给大家讲解怎么样在例化时改变参数。
激励代码如下:
代码语言:javascript复制/*
模块名称:ledrun_tb
模块功能:为ledrun模块提供激励信号
作者:郝旭帅
邮箱:746833924@qq.com
*/
`timescale 1ns/1ps
module ledrun_tb;
reg clk;
reg rst_n; //低电平有效
wire [3:0] led;
parameter T1s = 5;//参数设置(仿真时)
initial begin
clk = 1'b1;
rst_n = 1'b0;
# 200.1//复位200.1ns
rst_n = 1'b1;
# 2000
$stop;
end
always #10 clk = ~clk;//50M
ledrun #(T1s)//参数传递
ledrun_dut(
.clk(clk),
.rst_n(rst_n),
.led(led)
);
endmodule
仿真波形如下:
从仿真出来的波形来看,第一:led灯在流水(低电平在流水)。第二:每一个led灯亮5个周期(我们设置的仿真时是5个周期)。
设计正确,下板即可验证。如果小伙伴的电路原理和笔者的不一样,请自行更改设计。如果还是有不明白的小伙伴可以发邮件到我邮箱或者加群询问。
END
制作人:郝旭帅