verilog状态机 二段式 状态机 (代码 可以运行)
“硬件设计很讲究并行设计思想,虽然用Verilog描述的电路大都是并行实现的,但是对于实际的工程应用,往往需要让硬件来实现一些具有一定顺序的工作,这就要用到状态机思想。什么是状态机呢?简单的说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。硬件的并行性决定了用Verilog描述的硬件实现(臂如不同的always语句)都是并行执行的,那么如果希望分多个时间完成一个任务,怎么办?也许可以用多个使能信号来衔接多个不同的模块,但是这样做多少显得繁琐。状态机的提出会大大简化这一工作。”
——特权同学《深入浅出玩转FPGA》
一、状态机分类:
1.Moore型:状态机的状态变化仅和当前状态有关(特权同学《深入浅出玩转FPGA》);时序逻辑电路的输出只取决于当前状态(夏宇闻《Verilog数字系统设计》)。设计高速电路时常用此类状态机,把状态变化直接用作输出。
2.Mealy型:状态机的状态变化不仅与当前的状态有关,还取决于当前的输入条件(特权同学《深入浅出玩转FPGA》);时序逻辑的输出不但取决于状态还取决于输入(夏宇闻《Verilog数字系统设计》)。平常使用较多的是此类状态机。
“其实这几种状态机之间,只要做一些改变,便可以从一种形式转变为另一种形式。把状态机精确的分为这类或那类,其实并不重要,重要的是设计者如何把握输出的结构能满足设计的整体目标,包括定时的准确性和灵活性。”
——夏宇闻《Verilog数字系统设计》
二、状态机编码:
状态机的参数定义采用的都是独热码,和格雷码相比,虽然独热码多用了触发器,但所用组合电路可以省一些,因而使电路的速度和可靠性有显著提高,而总的单元数并无显著增加。采用独热编码后有了多余的状态,就有一些不可达到的状态。为此在case语句的最后需要增加default分支向。这可以用默认项表示该项,也可以用确定项表示,以确保回到初始状态。一般综合器都可以通过综合指令的控制来合理地处理默认项。
三、实例分析
状态机一般有三种不同的写法,即一段式、两段式和三段式的状态机写法,他们在速度、面积、代码可维护性等各个方面互有优劣,不要对任何一种写法给出“一棍子打死”的定论。手头上刚好有一个状态机的例子,借此记录一下三种状态机的Verilog写法。
要求:
售货机里有价值4元的脉动饮料,支持1元和2元硬币。请设计一个状态机,检测投入的硬币,当累计投入币值大于等于脉动价格时,售货机自动找零并弹出1瓶脉动饮料。硬币和商品都是一个一个的进出,不会出现一次性投很多个硬币弹出很多瓶脉动的情况。
信号 | 含义 |
---|---|
clk | 时钟信号 |
rst_n | 复位信号 |
in | 输入信号,币值,有1和2两种,投钱 |
out | 输出信号,币值,有1和2两种,找零 |
out_vld | 输出信号,脉动,为1则输出1瓶脉动 |
状态转移图:
根据要求,我们先把状态转移图画出来,绘画软件:Visio,如果没有安装也可以用wps自带应用的“流程图”功能:
//======================================================================
// --- 名称 : FSM_2
// --- 作者 : xianyu_FPGA
// --- 日期 : 2018-12-15
// --- 描述 : 售货机练习,采用二段式状态机
//======================================================================
module FSM_3
//---------------------<端口声明>---------------------------------------
(
input clk ,
input rst_n ,
input [1:0] in ,
output reg [1:0] out ,
output reg out_vld
);
//---------------------<信号定义>---------------------------------------
reg [3:0] state_c ;
reg [3:0] state_n ;
//---------------------<状态机参数>-------------------------------------
localparam S0 = 4'b0001 ;
localparam S1 = 4'b0010 ;
localparam S2 = 4'b0100 ;
localparam S3 = 4'b1000 ;
//----------------------------------------------------------------------
//-- 状态机第1段
//----------------------------------------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
state_c <= S0;
else
state_c <= state_n;
end
//----------------------------------------------------------------------
//-- 状态机第2段
//----------------------------------------------------------------------
always@(*)begin
case(state_c)
S0: begin
if(in==1)begin
state_n = S1;
end
else if(in==2)begin
state_n = S2;
end
else begin
state_n = state_c;
out = 0 ;
out_vld = 0 ;
end
end
S1: begin
if(in==1)begin
state_n = S2;
end
else if(in==2)begin
state_n = S3;
end
else begin
state_n = state_c;
end
end
S2: begin
if(in==1)begin
state_n = S3;
end
else if(in==2)begin
state_n = S0;
out_vld = 1 ;
end
else begin
state_n = state_c;
out_vld = 0;
end
end
S3: begin
if(in==1)begin
state_n = S0;
out_vld = 1 ;
end
else if(in==2)begin
state_n = S0;
out = 1 ;
out_vld = 1 ;
end
else begin
state_n = state_c;
out = 0;
out_vld = 0;
end
end
default:state_n = S0;
endcase
end
endmodule
`timescale 1ns/1ps //时间精度
`define Clock 20 //时钟周期
module FSM_3_tb;
//--------------------< 端口 >------------------------------------------
reg clk ;
reg rst_n ;
reg [1:0] in ;
wire [1:0] out ;
wire out_vld ;
//----------------------------------------------------------------------
//-- 模块例化
//----------------------------------------------------------------------
FSM_3 u_FSM_3
(
.clk (clk ),
.rst_n (rst_n ),
.in (in ),
.out (out ),
.out_vld (out_vld )
);
//----------------------------------------------------------------------
//-- 状态机名称查看器
//----------------------------------------------------------------------
localparam S0 = 4'b0001 ;
localparam S1 = 4'b0010 ;
localparam S2 = 4'b0100 ;
localparam S3 = 4'b1000 ;
//2字符16位
reg [15:0] state_name ;
always@(*)begin
case(u_FSM_3.state_c)
S0: state_name = "S0";
S1: state_name = "S1";
S2: state_name = "S2";
S3: state_name = "S3";
default:state_name = "S0";
endcase
end
//----------------------------------------------------------------------
//-- 时钟信号和复位信号
//----------------------------------------------------------------------
initial begin
clk = 1;
forever
#(`Clock/2) clk = ~clk;
end
initial begin
rst_n = 0; #(`Clock*20+1);
rst_n = 1;
end
//----------------------------------------------------------------------
//-- 设计输入信号
//----------------------------------------------------------------------
initial begin
$dumpfile("test.vcd");
$dumpvars(0,FSM_3_tb);
#1;
in = 0;
#(`Clock*20+1); //初始化完成
//情况1--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况2--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况3--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况4--------------------------
in = 1; //1块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
//情况5--------------------------
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*1);
in = 2; //2块钱
#(`Clock*1);
in = 0;
#(`Clock*10);
$stop;
end
endmodule
我用的是 vivado 21 秒学会 vivado 仿真
相关文章
- 网页运行js代码
- bat代码中判断 bat是否是以管理员权限运行,以及自动以管理员权限运行CMD BAT
- 编写高质量代码改善java程序的151个建议——[110-117]异常及Web项目中异常处理
- x264代码剖析(二):如何编译运行x264以及x264代码基本框架
- WinForm 代码实现以管理员身份运行
- Java单元测试(Junit+Mock+代码覆盖率)
- 能分析压缩的日志,且基于文件输入的PYTHON代码实现
- 【译】用Fragment创建动态的界面布局(附Android示例代码)
- 在线运行HTML代码器
- PHP代码审计之简单思路方法
- k8s部署daemonset代码示例:每个节点都会运行的守护进程
- Hadoop MapReduce手机上网流量统计代码示例及运行结果演示
- 已解决使用pycharm run运行代码正常而debug却抛出异常UnicodeDecodeError: ‘utf-8’ codec can’t decode bytes in position 10
- 基于合作型Stackerlberg博弈的考虑差别定价和风险管理的微网运行策略研究(Matlab代码实现)
- 基于非对称纳什谈判的多微网电能共享运行优化策略(Matlab代码实现)
- 碳交易机制下考虑需求响应的综合能源系统优化运行(Matlab代码实现)
- 【电动车】主动配电网多源协同运行优化研究——大规模电动汽车的蒙特卡洛模拟(Matlab代码实现)
- 二进制数据的贝叶斯非参数聚类算法(Matlab代码实现)
- 基于粒子群优化算法的冷热电联供型综合能源系统运行优化(Matlab代码实现)
- 一种用于模拟电晕放电的高效半拉格朗日算法(Matlab代码实现)
- 数学建模学习(109):几行代码训练几十种机器学习模型
- AppCube视角浅析: 艾瑞咨询《2022年中国低代码行业研究报告》
- 4行Python代码监测每行程序的运行时间和空间消耗
- 基于蜣螂算法改进的LSTM分类算法-附代码
- 基于曲线自适应和模拟退火的蝗虫优化算法-附代码
- verilog状态机 一段式 状态机 (代码 可以运行)
- vscode +Jupyter+子系统 python实战 windows系统下运行python写代码 windows子系统 window下Linux系统搭建
- python实战===一行代码就能搞定的事情!
- FlutterUnit 工具集录 | IconFont 类代码自动生成
- Kotlin — 运行代码片段(以轻量级方式编写和无需创建整个应用程序的方法)
- android intent打开各种文件(txt、apk、ppt、xls和doc)的方法,下面有代码 直接运行
- 【数字IC/FPGA】百度昆仑芯手撕代码--累加器