Verilog写状态机的三种描述方式之二段式

Verilog写状态机的二段式描述方式

    • 1,门级代码
    • 2,门级代码生成的电路原理图
    • 3,测试代码
    • 4,测试代码生成的波形图,前仿真波形验证

参考文献1:FPGA学习之状态机的多种描述方式
参考文献2:本专栏的Verilog写状态机的三种描述方式(三段式、二段式和一段式)
参考文献3:本专栏的VL-39自动贩卖机

二段式描述:
即二个always。输出使用的是组合逻辑,很容易产生毛刺等不稳定因素。
其中第二个always@(*),此处不受clk的影响。
三段式描述
即三个always。根据下一个状态的判断,利用同步时序逻辑来寄存状态机的输出,从而消除了组合逻辑的不稳定性和毛刺的隐患,有利于时序路径分组。

1,门级代码


// 状态机两段式
// 自动售卖机
module auto_sell2(
input  clk,
input  rst_n,
input  half,        // 0.5元
input  one,         // 1.0元
output reg drink,   // 饮料售价2.5元,售出饮料信号
output reg flag,     // 找零信号

output c_state,
output n_state
);

reg [2:0] c_state;  // 投币信号
reg [2:0] n_state;  // 

parameter S0 = 3'd0;   // 无投币
parameter S1 = 3'd1;   // 投币0.5
parameter S2 = 3'd2;   // 投币1.0
parameter S3 = 3'd3;   // 投币1.5
parameter S4 = 3'd4;   // 投币2.0
parameter S5 = 3'd5;   // 投币2.5,拉高drink信号
parameter S6 = 3'd6;   // 找零

// 第一段
always@(posedge clk or negedge rst_n) begin
	if(!rst_n)
	   c_state <= S0;
	else 
	   c_state <= n_state;
end

// 第二段
always@(*) begin
	if(!rst_n) begin
		drink <= 0;
		flag  <= 0;
		n_state <= S0;
	end
	else begin
		case(c_state)
		  S0: begin               // 起始状态S0时,此时没钱
		  	if(half == 1'b1)      // 当0.5元,则进入S1状态
		  	  n_state <= S1;
		  	else if(one == 1'b1)  // 当1.0元,则进入S2状态 
		  	  n_state <= S2;
		  	else                  // 否则就是没有钱进入,停留在S0状态
		  	  n_state <= S0;
		   end
		  S1: begin               // 0.5元
		  	if(half == 1'b1)
		  	  n_state <= S2;
		  	else if(one == 1'b1)
		  	  n_state <= S3;
		  	else 
		  	  n_state <= S1;
		   end
          S2: begin               // 1.0元
          	 if(half == 1'b1)
          	  n_state <= S3;
          	 else if(one == 1'b1)
          	  n_state <= S4;
          	 else 
          	  n_state <= S2;
            end
          S3: begin               // 1.5元
          	if(half == 1'b1)
          	  n_state <= S4;
          	else if(one == 1'b1)
          	  n_state <= S5;
          	else 
          	  n_state <= S3;
            end
          S4: begin
          	if(half == 1'b1)
          	  n_state <= S5;
          	else if(one == 1'b1)
          	  n_state <= S6;
          	else 
          	  n_state <= S0;
          end
          S5: begin
          	  drink   <= 1;
          	  n_state <= S0;
          end
          S6: begin
          	  drink   <= 1;
          	  flag    <= 1;
          	  n_state <= S0;
          end
          default:n_state <= S0;
          endcase
	end
end

endmodule

2,门级代码生成的电路原理图

Verilog写状态机的三种描述方式之二段式_第1张图片

3,测试代码


// auto_sell3
// tb 测试信号


module tb;
reg   clk, rst_n, half, one;
wire  [2:0]  c_state, n_state;
wire  drink, flag;

//-----时钟---------
always #10 clk = ~clk;  // T=20

initial begin
	  rst_n = 0; clk = 1;
#15;  rst_n = 1;
end

initial begin
#0;   half = 0; one = 0;  // 在S0状态
#20;  half = 0; one = 0;
#20;  half = 1; one = 0;  // 进1个状态,S1
#20;  half = 1; one = 0;  // 进1
#20;  half = 0; one = 1;  // 进2
#20;  half = 0; one = 0; 
#20;  half = 1; one = 0;  // 进1  ,到S5状态,下一个S0状态
#20;  half = 0; one = 1;  // S2
#20;  half = 0; one = 1;  // S4
#20;  half = 0; one = 1;  // S6
#20;  half = 0; one = 1;  
#60;  half = 0; one = 0;
#100; $stop;
end

auto_sell2 uu(
.clk(clk),
.rst_n(rst_n),
.half(half),
.one(one),
.drink(drink),
.flag(flag),
.c_state(c_state),
.n_state(n_state)
	);

endmodule

4,测试代码生成的波形图,前仿真波形验证

Verilog写状态机的三种描述方式之二段式_第2张图片

你可能感兴趣的:(fpga开发)