有限状态机FSM(自动售报机Verilog实现)
FSM
- 状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法。
状态机有两大类:Mealy型和Moore型。
Moore型状态机的输出只与当前状态有关,而Mealy型状态机的输出不仅取决于当前状态,还受到输入的直接控制,并且可能与状态无关。
当使用Verilog来描述一个简单状态机的设计时,应将状态寄存器的控制器的控制和状态机状态里的组合逻辑分开。
- 分离功能使得在逻辑部分的代码中可以使用阻塞赋值语句
状态更新逻辑包含状态寄存器,不能被外设读取。组合逻辑使用输入和当前状态值来对输出赋值,并改变状态机的下一状态。
同步时序电路的设计方法
- 逻辑抽象,得出电路的状态转换图或者状态转换表
- 状态化简
- 状态分配(状态编码:Binary,Gray,One-Hot)
- Verilog根据最简状态转换图编程,检查设计的电路能否自启动
四个要素
- 当前输入
- 当前状态
- 下一状态
- 当前输出值
代码风格
一段式
当前状态、下一状态、当前输出值都写在一个always块中
二段式
当前状态、下一状态、当前输出值写在两个always块中
- 注意:这样三种组合方式,及有三种方式写这两个always块。
三段式
当前状态、下一状态、当前输出值分别写在各自的always块中,这样需要3个always块。
自动售报机Verilog实现
设计说明
设计一个简单的数字电路用于电子的报纸售卖机的投币器。
- 假设报纸的价格为15分。
- 投币器只能接受5分和1角的硬币。
- 必须提供适当的数目的零钱,投币器不找零。
- 合法的硬币组合包括1个5分的硬币和1个一角的硬币,3个5分的硬币,1个1角的硬币和1个5分的硬币。2个1角的硬币是合法的,但是投币器不找零。
电路说明
- 当投入硬币时,一个两位的信号coin[1:0]被传送到数字电路。该信号在全局clock信号的下一个下降沿取值,并且准确地保持一个始终周期。
- 数字电路的输出是一位的。每次当投入硬币总数为15分或者超过15分时,输出信号newspaper变为高电平,并且保持一个时钟周期。售卖机的门也被打开。
- 可以用一个reset信号复位有限状态机。假设为同步复位。
有限状态机FSM
可以用有限状态机表示该数字电路的功能。
- 输入:2位,coin[1:0]。没有硬币时,x0 = 2'b00;有一个5分的硬币时,x5 = 2'b01;有一个1角的硬币时,x10 = 2'b10。
- 输出:1位,newspaper。当newspaper = 1'b1时,打开门。
- 状态:4个状态。s0 = 0分,s5 = 5分,s10 = 10分,s15 = 15分。
状态机转换图
状态 | 钱数 | 输入 | 硬币[1:0] |
---|---|---|---|
s0 | 0分 | x0 | 2'b00 |
s5 | 5分 | x5 | 2'b01 |
s10 | 10分 | x10 | 2'b10 |
s15 | 15分 | - | 无关 |
verilog描述
design code
module vend( input [1:0] coin, input clock, input reset, output newspaper ); //声明有限状态机的内部状态 wire [1:0] NEXT_STATE; reg [1:0] PRES_STATE; //状态编码 parameter s0 = 2'b00; parameter s5 = 2'b01; parameter s10 = 2'b10; parameter s15 = 2'b11; //用同步复位、时钟正跳变沿触发的状态触发器 always@(posedge clock) begin if(reset == 1'b1) PRES_STATE <= s0; else PRES_STATE <= NEXT_STATE; end //组合逻辑 function [2:0] fsm; //状态变化及输出组合逻辑 input [1:0] fsm_coin; input [1:0] fsm_PRES_STATE; reg fsm_newspaper; reg [1:0] fsm_NEXT_STATE; begin case(fsm_PRES_STATE) s0: //状态为s0 begin if(fsm_coin == 2'b10) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s10; end else if(fsm_coin == 2'b01) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s5; end else begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s0; end end s5: //状态为s5 begin if(fsm_coin == 2'b10) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s15; end else if(fsm_coin == 2'b01) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s10; end else begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s5; end end s10: //状态为s10 begin if(fsm_coin == 2'b10) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s15; end else if(fsm_coin == 2'b01) begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s15; end else begin fsm_newspaper = 1'b0; fsm_NEXT_STATE = s10; end end s15: //状态为s15 begin fsm_newspaper = 1'b1; fsm_NEXT_STATE = s0; end endcase fsm = {fsm_newspaper,fsm_NEXT_STATE}; end endfunction //每当硬币放入或当前状态改变时,组合逻辑动作 assign {newspaper,NEXT_STATE} = fsm(coin,PRES_STATE); endmodule
testbench
module vend_tb; reg clock; reg reset; reg [1:0] coin; wire newspaper; always #20 clock = ~clock; initial begin clock = 0; reset = 1; #100; reset = 0; @(posedge clock) coin[1:0] = 2'b00; @(posedge clock); @(posedge clock) coin[1:0] = 2'b01; @(posedge clock); @(posedge clock) coin[1:0] = 2'b10; @(posedge clock); @(posedge clock) coin[1:0] = 2'b10; @(posedge clock); @(posedge clock) coin[1:0] = 2'b10; @(posedge clock); @(posedge clock) coin[1:0] = 2'b00; @(posedge clock); @(posedge clock) coin[1:0] = 2'b01; @(posedge clock); @(posedge clock) coin[1:0] = 2'b01; @(posedge clock); @(posedge clock) coin[1:0] = 2'b01; #200 $finish; end initial begin $fsdbDumpfile("test.fsdb"); $fsdbDumpvars(); end vend u_vend( .coin(coin), .clock(clock), .reset(reset), .newspaper(newspaper) ); endmodule
仿真结果
参考资料
[1]. Verilog HDL数字设计与综合(第二版) [美]Simir Palnitkar 著 夏宇闻 等译
[2]. Verilog 数字VLSI设计教程 [美] John Willianms 著 李林 等译
[3]. 有限状态机 FSM 设计
[4]. 有限狀態機FSM coding style整理 (SOC) (Verilog)
来源:https://www.cnblogs.com/OneFri/p/6189422.html