原创 125自动售货机

2009-11-28 18:00 2427 11 11 分类: FPGA/CPLD

  最近在看笔试面试题,发现这个“自动售货机”的题目挺是经典。觉得自己应该能应付的过来,做起来才发现,没那么简单——明明不用状态机就能实现的,逼着自己往状态机那边跑,脑汁差不多被榨干了。 或许新手就是这样子...经验不行。


大概写了3个版本,也模仿了某书上的模式写了个 Mealy状态机,结果发现貌似Quartus2 并不认可这个状态机,直接提示 NO STATE MACHINE。为了能在Quartus里面看到状态机{(— —#)有点心理那个...},折磨半天,最后弄成这个版本


----------- 回归主题


假设存在投币检测装置,能输出 触发脉冲信号clk_coin,及 当次投币种类coin。


并假设 clk_coin 宽度<coin宽度。


当投币金额>=5时,asignal翻转一次,表示可以投递出一瓶可乐。


balance实时表示余额。


------------------------------本来已经设计好 写完 投递控制器的代码,及退币的代码,想起还要帮同学做 PLD设计的结课论文(又是电子时钟!)...搁置~ing



module monsta(
 clk_coin,
 coin,
 balance,
 asignal
 );


input clk_coin;  //投币检测装置产生的时钟
input [2:0] coin; //投币类型 (0,1,2,5)-- “0”表示无效的投币
output [4:0] balance; //余额
output asignal;  // 当投币金额数目满足>=5时,输出跳变一次


reg [4:0] balance = 4'b0000;
reg asignal;
reg [4:0] money = 4'b0000;


wire clk_coin_n;
reg [3:0] state;    //最好不要初始化state


//表示状态
parameter m0 = 4'b0000,   
    m1 = 4'b0001,
    m2 = 4'b0010,
    m3 = 4'b0011,
    m4 = 4'b0100;


//------------------------------------------


assign clk_coin_n = ~clk_coin;       //产生一个反相时钟


always @ (posedge clk_coin or posedge clk_coin_n) 
begin
 if(clk_coin)         //正相时钟上沿统计金额
 begin
  money <= coin + balance;  //结果的位宽可能为4位(最大为9-即1001)
 end
 else            //反相时钟上沿计算状态
 begin
 
  case(state)   
//-------------------
  m0:
  begin
   if(money > 4'b0100)    //金额>=5
   begin
    balance <= m0;    //计算余额 ,这里balance的值肯定是0,不存在其他情况
    asignal <= ~asignal;    //输出跳变
    state <= m0;      //下一个状态
   end
   else
   begin
    balance <= money;   //当前金额<5时,该值作为余额
    if(money == m1)   //如果投入的硬币是1,则状态是1
     state <= m1;
    else if(money == m2)  //如果投入的硬币是2,则状态是2
     state <= m2;
    else
     state <= m0;
   end
  end
//-------------------  
  m1:
  begin
   if(money > 4'b0100)
   begin
    balance <= m1;
    asignal <= ~asignal;
    state <= m1;
   end
   else
   begin
    balance <= money;
    if(money == m2)
     state <= m2;
    else if(money == m3)
     state <= m3;
    else
     state <= m1;
   end
  end
//-------------------  
  m2:
  begin
 
   if(money > 4'b0100)
   begin
    balance <= m2;
    asignal <= ~asignal;
    state <= m2;
   end
   else
   begin
    balance <= money;
    if(money == m3)
     state <= m3;
    else if(money == m4)
     state <= m4;
    else
     state <= m2;
   end
  end
//-------------------  
  m3:
  begin
   if(money > 4'b0100)   // 当次投入的是2或者5
   begin
    if(money - 4'b0101 == m0)    // 当次投入的是2
    begin
     balance <= m0;
     asignal <= ~asignal;
     state <= m0;
    end
    else  //当次投入的是5
    begin
     balance <= m3;
     asignal <= ~asignal;
     state <= m3;
    end
    
   end
   else   // 当次投入的是1 或者 0
   begin
    balance <= money;
    if(money == m4)   //当次投入的是1
     state <= m4;
    else
     state <= m3;
   end
  end
//-------------------  
  m4:
  begin
   if(money > 4'b0100)   // +1 or +2 or +5
   begin
    if(money - 4'b0101 == m0)    // money="5"
    begin
     balance <= m0;
     asignal <= ~asignal;
     state <= m0;
    end
    else if(money - 3'b101 == m1)  //money =6
    begin
     balance <= m1;
     asignal <= ~asignal;
     state <= m1;
    end
    else  //money = 9
    begin
     balance <= m4;
     asignal <= ~asignal;
     state <= m4;
    end
    
   end
   else   // money = 4
   begin
    balance <= m4;
    state <= m4;
   end
  end
//-------------------  
  default:
  begin
   balance <= m0;
   asignal <= 1'b0;
   state <= m0;
  end
  
 endcase
 end
end
  


endmodule


=========================


仿真波形-- (— —#)偶不会test bench


点击看大图


------


可爱的状态图


点击看大图


 


============= THE END =============== 没时间注释了 ,日后再说

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /3 下一条