Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机
原文链接:https://blog.csdn.net/qq_34070723/article/details/100737225
作者:King阿金
目录
1.状态机原理与三段式状态机
2.状态机示例
2.1自动饮料售卖机/卖报机
2.2序列检测器
1.状态机原理与三段式状态机
MOORE 与 MEALEY 状态机的特征?
Moore 状态机的输出仅与当前状态值有关, 且只在时钟边沿到来时才会有状态变化。次态=f(现状,输入),输出=f(现状)
Mealy 状态机的输出不仅与当前状态值有关, 而且与当前输入值有关。次态=f(现状,输入),输出=f(现状,输入)
描述同一个事务,mealy的状态更少。
通用mealy三段式状态机(建议实际工程中采用的结构)
- //------采用独热码或格雷码或其他方式编码状态
- parameter IDLE = ...
- parameter S0 = ...
- ...
- reg [x:0] curr_state;
- reg [x:0] next_state;
- //------每个时钟只产生一次状态变化
- always @(posedge clk or posedge asy_rst)
- begin
- if(asy_rst) curr_state <= IDLE ;
- else curr_state <= next_state;
- end
- //------产生的下一状态的组合逻辑
- always @(*)
- begin
- next_state = 'bx;
- case(curr_state)
- IDLE: if(输入) next_state = S0 ;else...;
- S0: if(输入) next_state = ...;
- ...
- default: next_state = ...;
- endcase
- end
- /************************时序或组合二选一***********************/
- //------时序逻辑输出(比组合逻辑延时一个时钟)
- always@(posedge clk or posedge asy_rst)
- begin
- if(asy_rst)out<= ...;
- else
- case(curr_state)
- sO: if(...) out <= ...;
- sO: if(...) out <= ...;
- default: out <= ...;
- endcase
- end
- //------组合逻辑输出 采用 assign 或always
- always @(*)
- begin
- if(asy_rst)out = ...;
- else
- case(curr_state)
- sO: if(...) out = ...;
- sO: if(...) out = ...;
- default: out = ...;
- endcase
- end
- /***********************************************************/
2.状态机示例
2.1自动饮料售卖机/卖报机
题目:商品是5分钱,只能投3种硬币:1分,2分,5分,考虑找零。
思路1:采用状态机,共分为5个状态,S0-S4代表已经投入的钱,画出状态转换图(略),采用三段式mealy状态机。
思路2:(更简单)不采用状态机,直接对输入的钱进行加法运算,多余5分就输出和找零,同时将内部加法器清零。
另一个版本:用Verilog实现接受0.5元,1元的可乐售卖机,单价2.5元,考虑找零和出货。
- module auto_sell_better#(
- parameter I_WD = 4 , O_WD = 4
- )(
- input clk,
- input asy_rst,
- input [I_WD-1:0] i_dat,
- input i_val,
- output reg [O_WD-1:0] o_money,//找零
- output reg o_goods //商品
- );
- parameter S0=4'b0000;
- parameter S1=4'b0001; //1分钱
- parameter S2=4'b0010;
- parameter S3=4'b0100;
- parameter S4=4'b1000; //4分钱
- reg [3:0] curr_s;
- reg [3:0] next_s;
- //每个时钟只产生一次状态变化
- always @(posedge clk or posedge asy_rst)
- begin
- if(asy_rst)
- curr_s <= S0;
- else
- curr_s <= next_s;
- end
- //产生的下一状态的组合逻辑
- always @(*)
- begin
- next_s = 'dx;
- case(curr_s)
- S0: if(i_dat == 1) next_s = S1;
- else if(i_dat == 2) next_s = S2;
- else if(i_dat == 5) next_s = S0;
- else next_s = S0;
- S1: if(i_dat == 1) next_s = S2;
- else if(i_dat == 2) next_s = S3;
- else if(i_dat == 5) next_s = S0;
- else next_s = S1;
- S2: if(i_dat == 1) next_s = S3;
- else if(i_dat == 2) next_s = S4;
- else if(i_dat == 5) next_s = S0;
- else next_s = S2;
- S3: if(i_dat == 1) next_s = S4;
- else if(i_dat == 2) next_s = S0;
- else if(i_dat == 5) next_s = S0;
- else next_s = S3;
- S4: if(i_dat == 1) next_s = S0;
- else if(i_dat == 2) next_s = S0;
- else if(i_dat == 5) next_s = S0;
- else next_s = S4;
- default: next_s = S0;
- endcase
- end
- /**************************时序逻辑的输出*******************************/
- always @(posedge clk or posedge asy_rst)
- begin
- if(asy_rst)
- begin
- o_money <= 0;
- o_goods <= 0;
- end
- else
- case(curr_s)
- S0:
- begin
- o_money <= 0;
- if(i_dat==5) o_goods <= 1;
- else o_goods <= 0;
- end
- S1:
- begin
- if(i_dat==5) begin o_money <= 1; o_goods <= 1; end
- else begin o_money <= 0; o_goods <= 0; end
- end
- S2:
- begin
- if(i_dat==5) begin o_money <= 2; o_goods <= 1; end
- else begin o_money <= 0; o_goods <= 0; end
- end
- S3:
- begin
- if(i_dat==5) begin o_money <= 3; o_goods <= 1; end
- else if (i_dat==2) begin o_money <= 0; o_goods <= 1; end
- else begin o_money <= 0; o_goods <= 0; end
- end
- S4:
- begin
- if(i_dat==5) begin o_money <= 4; o_goods <= 1; end
- else if (i_dat==2) begin o_money <= 1; o_goods <= 1; end
- else if (i_dat==1) begin o_money <= 0; o_goods <= 1; end
- end
- default :
- begin o_money <= 0; o_goods <= 0;end
- endcase
- end
- /***************************不采用状态机的方法**********************************/
- reg [3:0] add_in;//内部计算输入的钱的和
- reg [3:0] a_money;//找零
- reg a_goods;//商品
- always @(posedge clk or posedge asy_rst)
- begin
- if(asy_rst)
- begin
- add_in <= 0;
- a_money <= 0;
- a_goods <= 0;
- end
- else if(i_val)
- begin
- if(add_in+i_dat >=5)
- begin
- add_in <= 0;//清零
- a_money <= add_in + i_dat - 5;//找零
- a_goods <= 1;//输出
- end
- else
- begin
- add_in <= add_in + i_dat;
- a_money <= 0;
- a_goods <= 0;
- end
- end
- else
- begin
- add_in <= 0;
- a_money <= 0;
- a_goods <= 0;
- end
- end
- endmodule
- /testbench//
- module auto_sell_sim;
- parameter CLK_PERIOD = 10; //仿真周期10ns=100M
- parameter RST_CYCLE = 5; //复位周期数
- parameter RST_TIME = RST_CYCLE * CLK_PERIOD;
- reg sim_clk;
- reg sim_asy_rst;
- initial
- begin
- sim_clk = 0;
- sim_asy_rst = 1;
- #RST_TIME sim_asy_rst = 0;
- end
- always #(CLK_PERIOD/2) sim_clk = ~sim_clk;
- /******************************************************/
- parameter I_WD = 4;
- parameter O_WD = 4;
- reg [I_WD-1:0]sim_dat;
- reg [I_WD-1:0]sim_i_dat;
- reg sim_i_val;
- always@(posedge sim_clk or posedge sim_asy_rst)
- begin
- if(sim_asy_rst)
- begin
- sim_i_dat <= 0;
- sim_i_val <= 0;
- end
- else
- begin
- sim_dat <= {$random}%6;//产生0-5的随机数
- if( sim_dat== 1 || sim_dat ==2 || sim_dat==5)
- begin
- sim_i_dat <= sim_dat;
- sim_i_val <= 1;
- end
- else
- begin
- sim_i_dat <= 0;
- sim_i_val <= 1;
- end
- end
- end
- wire [O_WD-1:0] o_money;
- wire o_goods;
- auto_sell_better auto_sell_better_u( //auto_sell auto_sell_u (
- .clk( sim_clk ),
- .asy_rst( sim_asy_rst ),
- .i_dat( sim_i_dat ),
- .i_val( sim_i_val),
- .o_money(o_money),
- .o_goods(o_goods)
- );
2.2序列检测器
笔试题目:如果序列长度为8,需要8个状态,最少(3)个寄存器进行状态转换(mealy)。
题目:用状态机实现 101101 的序列检测。
思路:
画出mealy状态转换图,并进行化简[1],灰色表示合并为一个:
如果采用moore状态机,其状态就多了,且输出比mealy延时一个时钟参考[1]:
- //mealy状态机
- module seq_detect#(
- parameter I_WD = 1 , O_WD = 1
- )(
- input clk,
- input asy_rst,
- input [I_WD-1:0] i_dat,
- input i_val,
- output reg [O_WD-1:0] o_detect
- );
- parameter S0=6'b000001;
- parameter S1=6'b000010;
- parameter S2=6'b000100;
- parameter S3=6'b001000;
- parameter S4=6'b010000;
- parameter S5=6'b100000;
- //101101
- reg [5:0] curr_s;
- reg [5:0] next_s;
- //每个时钟只产生一次状态变化
- always @(posedge clk or posedge asy_rst)
- begin
- if(asy_rst)
- curr_s <= S0;
- else
- curr_s <= next_s;
- end
- //产生的下一状态的组合逻辑
- always @(*)
- begin
- next_s = 'dx;
- case(curr_s)
- S0: if(i_dat == 1) next_s = S1;
- else next_s = S0;
- S1: if(i_dat == 0) next_s = S2;
- else next_s = S1;
- S2: if(i_dat == 1) next_s = S3;
- else next_s = S0;
- S3: if(i_dat == 1) next_s = S4;
- else next_s = S2;// 1010---提取10
- S4: if(i_dat == 0) next_s = S5;
- else next_s = S1;
- S5: if(i_dat == 1) next_s = S0;
- else next_s = S0;
- default: next_s = S0;
- endcase
- end
- /**************************时序逻辑的输出*******************************/
- always @(posedge clk or posedge asy_rst)
- begin
- if(asy_rst)
- begin
- o_detect <= 0;
- end
- else
- case(curr_s)
- S0,S1,S2,S3,S4:
- begin
- o_detect <= 0;
- end
- S5:
- begin
- if(i_dat ==1 ) o_detect <= 1;
- end
- default :
- begin o_detect <= 0; end
- endcase
- end
- endmodule
- /testbench/
- module seq_detect_sim;
- parameter CLK_PERIOD = 10; //仿真周期10ns=100M
- parameter RST_CYCLE = 5; //复位周期数
- parameter RST_TIME = RST_CYCLE * CLK_PERIOD;
- reg sim_clk;
- reg sim_asy_rst;
- initial
- begin
- sim_clk = 0;
- sim_asy_rst = 1;
- #RST_TIME sim_asy_rst = 0;
- end
- always #(CLK_PERIOD/2) sim_clk = ~sim_clk;
- /******************************************************/
- parameter I_WD = 1;
- parameter O_WD = 1;
- parameter IN_SEQ = 32'b00101101_01011000_10110111_01010101;
- reg [4:0]cnt;
- reg sim_i_val;
- always @(posedge sim_clk or posedge sim_asy_rst)
- begin
- if(sim_asy_rst)
- begin
- cnt <= 0;
- sim_i_val <= 0;
- end
- else
- begin
- cnt <= cnt +1;
- sim_i_val <= 1;
- end
- end
- wire [O_WD-1:0] o_detect;
- seq_detect seq_detect_u (
- .clk(sim_clk ),
- .asy_rst(sim_asy_rst ),
- .i_dat(IN_SEQ[cnt] ),
- .i_val(sim_i_val),
- .o_detect(o_detect)
- );
- endmodule
参考资料
[1]“101101”序列检测器Verilog设计实例与VCS仿真(mealy型和moore型)
Verilog实现状态机与状态机经典示例——序列检测器、自动饮料售卖机相关推荐
- Verilog 自动饮料售卖机
设计一个自动饮料售卖机,共有两种饮料,其中饮料 A 每个 10 分钱,饮料 B 每个 5 分钱,硬币有 5 分和 10 分两种,并考虑找零. 要求用状态机实现,定义状态,画出状态转移图,并用 Veri ...
- 自动饮料售卖机Verilog设计
饮料为5美分,饮料机只能接收1美分,2美分,5美分的钱币,请设计一个Verilog电路表示 `timescale 1ns/10ps module sell(one,two,five,rset,clk, ...
- 序列检测器(两种设计方法和四种检测模式|verilog代码|Testbench|仿真结果)
序列检测器 一.前言 二.状态机法和寄存器法 2.1状态机法 2.11 使用状态机检测"1001" 2.12 verilog代码 2.13 testbench 2.14仿真结果 2 ...
- Verilog 实现111序列检测器——Moore和Mealy型状态机实现
111序列检测器 有限状态机简介 电路结构 '111'序列检测器 Moore状态机 代码实现 Mealy状态机 代码实现 有关三段式和两段式的对比 有关可重叠和不可重叠序列的对比 有限状态机简介 电路 ...
- verilog一二三段式状态机的标准区别和示例
状态机标准 状态机描述时关键是要描述清楚前面提到的几个状态机的要素,即如何进行状态转移:每个状态的输出是什么:状态转移是否和输入条件相关等. 具体描述时方法各种各样,有的设计者习惯将整个状态机写到1 ...
- 【 FPGA 】序列检测器的Moore状态机实现
设计一个序列检测器,检测序列1101,检测到输出1,否则输出0. 用状态机来实现序列检测器是非常合适的,下面先给出状态转移图,之后用Moore状态机来实现这个序列检测器: (注:此处所画为无重叠检测, ...
- 【 FPGA 】序列检测器的Mealy状态机实现
上篇博文讲了使用Moore状态机来设计一个序列检测器:序列检测器的Moore状态机实现 原理一致,这里只不过采用了Mealy状态机实现,快速给出: 状态转移图如下:被检测序列为1101,也就是说,如果 ...
- 序列检测器(三段式状态机)
Verilog HDL 学习笔记三 基于状态机的序列检测器 检测序列11001,其状态转移图如下所示: 三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用 ...
- IC/FPGA校招笔试题分析(四)再看Moore状态机实现序列检测器
参加了几次笔试,发现序列检测器是常考的内容,而之前认为序列检测器真的很简单,但是这次X疆的笔试题做完之后,我怀疑自己了. 画状态转移图的时候,我开始犹豫了,我怕我会没考虑全,甚至有点晕. 人家又问: ...
最新文章
- 【Qt开发】【VS开发】【Linux开发】OpenCV、Qt-MinGw、Qt-msvc、VS2010、VS2015、Ubuntu Linux、ARM Linux中几个特别容易混淆的内容...
- mysql构造函数_MySQL行构造器表达式优化(Row Constructor Expression)
- 【408预推免复习】计算机组成原理之控制单元的功能和控制单元的设计
- 在myeclipse当中使用正则表达式去除单行注释
- 产品经理如何开始数据分析之路?(基础知识)
- springboot使用webjars引入jquery
- linux常用命令:sudo 命令
- GPS定位冷启动和热启动的区别
- Given a list,rotate the list to right by k places, where k is nonegative.
- ocienvcreate php 失败_win7 homebasic下,.net2008 连接oracle,提示错误OCIEnvCreate
- 蒙特卡罗模拟计算定积分(R)
- sqldbx mysql 乱码_sqlDbx连接mysql 及乱码
- Postman请求报405错误
- Node.js与相关依赖的版本对照表
- outlook2007 配置
- Python3下的NLTK及nltk_data安装问题(Ubuntu环境)
- 2022广东深圳国际半导体分立器件产品与应用技术展览会
- kvm 模块加载时报错:insmod: error inserting 'kvm.ko': -1 Unknown symbol in module
- 你视人家为人脉,人家视你为韭菜
- 通过API发送信息到微信上
热门文章
- 视频相关的一些基本概念
- 计算机二战选学校,二战失败箴言:如何少走弯路直达终点!
- 流水灯实验报告c语言,PLC流水灯实验报告.pdf
- 人生第一次之首都图书馆
- 四年级计算机下册美术教案,新人教版小学美术四年级下册教案 (全册).doc...
- windows7安dns服务器_win7怎样安装dns服务器
- picker选择器的使用
- 使用开源软件和Tectonic,摆脱云服务供应商的锁定
- AutoCAD .NET开发大师Kean有价值的博客 2006年8月 .NET内容整理
- Django Rest Framework 创建机器学习 API