备战秋招之Verilog状态机代码

状态机分为

摩尔状态机:组合逻辑的输出只取决于当前状态

米勒状态机:组合逻辑的输出不仅取决于当前状态,还取决于输入状态

三段式状态机的基本格式是:

第一个Always语句实现同步状态跳转(基本是固定的模板)

第二个Always语句采用组合逻辑判断状态转移条件(根据状态转移图写)

第三个Always语句描述状态输出(可以采用组合逻辑输出,也可以时序电路时输出) 

Example:

例1.设计一个自动售饮料的逻辑电路。它的投币口每次只能投入一枚五角或一元的硬币。投入一元五角后给出饮料,投入两元硬币时给出饮料并找回五角。

分析:首先确定输入输出

投入一元硬币 A=1 ,投入五角硬币 B=1,给出饮料 Y=1 ,找回五角 Z=1 ;

然后确定电路的状态数,画出状态转移表

投币前初始状态为 S0 ,投入五角硬币为 S1 ,投入一元硬币为 S2 。

由于每次只能投一枚,因此除了AB=00, AB=01 , AB=10 三种状态为合法状态。画出状态转移表为:


画出状态转移图

最后根据状态转移图写出代码

Moudle Drink_sell(

input  clk,rst_n;
input  A,B;
output Y,Z;

);

reg [2:0] curr_st;
reg [2:0] next_st;
 
parameter S0 = 3'b001;  
parameter S1 = 3'b010;  
parameter S2 = 3'b100; 


//第一个always块描述状态跳转

always @(posedge clk or negedge rst_n)begin  
  if(!rst_n)begin
    curr_st <= S0 ;
  end
  else begin
    curr_st <= next_st;
   end
end
 
   
//第二个always块采用组合逻辑判断状态转移条件

always @(*)begin
  if(!rst_n)begin
    next_st <= S0 ;
  end
else begin
 case(curr_st)
   S0:     if(A==0 && B==1)  next_st = S1;
       else if(A==1 && B==0)  next_st = S2;
          else next_st = S0;
   S1:      if(A==0 && B==1)  next_st = S2;
       else if(A==1 && B==0)  next_st = S0;
          else next_st = S1;
   S2:      if(A==0 && B==0)  next_st = S2;
          else next_st = S0;
  default: next_st = S0;

  endcase
end 
end      

//第三个always块描述状态输出

always @(posedge clk or negedge rst_n)begin
  if(!rst_n)begin
    Y <= 1'b0;
    Z <= 1'b0;
   end

  else bigin
    case(curr_st)
    
      S0: Y <= 1'b0;
          Z <= 1'b0;
      S1: if(A==1 && B==0)begin
          Y <= 1'b1;
          Z <= 1'b0;
          end
      S2: if(A==0 && B==1)begin
          Y <= 1'b1;
          Z <= 1'b0;
          end
         else(A==1 && B==0)begin
          Y <= 1'b1;
          Z <= 1'b1;
          end
      default: Y <= 1'b0;
               Z <= 1'b0;
   
   endcase
end 
end
endmodule



例2:根据状态转移图写出Verilog代码(2020华为勇敢星FPGA岗位面试题)

代码如下:

module dec(
  input clk,
  input rst_n,
  input Go,Ws,
  output result

);

  reg [3:0] curr_st;
  reg [3:0] next_st;
 
parameter S_IDLE = 4'b0001;  
parameter S_READ = 4'b0010; 
parameter S_DELAY = 4'b0100; 
parameter S_DONE = 4'b1000; 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
      curr_st <= S_IDLE ;
     end
    else begin
      curr_st <= next_st;
         end
    end

 always @(*)begin
 if(!rst_n)begin
  next_st = 4'b0000;
   end
 else begin
 case (curr_st)
   S_IDLE :if(Go) next_st = S_READ ;
           else   next_st = S_IDLE ;
   S_READ :  next_st =S_DELAY ;
            
   S_DELAY:if(!Ws) next_st = S_DONE ;
            else   next_st = S_READ ;
   S_DONE :  next_st = S_IDLE ;
  default:  next_st = S_IDLE ;
endcase
end 
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
       result <= 1'0;
    end
    else begin 
    case(curr_st ==S_DONE  )
   result <= 1'b1;
  endcase
end
end
end 
endmodule
  










猜你喜欢

转载自blog.csdn.net/weixin_42166536/article/details/107590405