微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 简单自动售饮料机 哪里错了?

简单自动售饮料机 哪里错了?

时间:10-02 整理:3721RD 点击:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:   
//
// Create Date:    20:13:02 05/19/2010
// Design Name:   
// Module Name:    drink_machine
// Project Name:   drink_machine
// Target Devices:  xc2s300e
// Tool versions:  Xilinx ISE 9.1
// Description:   简单的自动售饮料机,假定一瓶饮料价格为2元5角,投币分别为一元和五角两种硬币。
//       每次投入硬币为一元或者五角,如果投入金币的总和是两元五角时,输出一瓶饮料;
//       如果投币总和是三元时,输出一瓶饮料,并且找回五角。
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module drink_machine(onedollar_in,fifty_in,fifty_out,drink_out,rst,clk);
parameter IDLE   = 0;
parameter ZERO_FIFTY = 1;
parameter ONE   = 2;
parameter ONE_FIFTY = 3;
parameter TWO   = 4;
input  fifty_in,onedollar_in,rst,clk;
output fifty_out,drink_out;
reg fifty_out,drink_out;
reg[2:0] state,next_state;
always@(onedollar_in[/email] or fifty_in or rst)
begin
fifty_out <= 0;
drink_out <= 0;
if(!rst)
  state  <= IDLE;
else
  begin
  state  <= next_state;
  case(next_state)
  IDLE:
    if(fifty_in)
    state <= ZERO_FIFTY;
    else if(onedollar_in)
    state <=  ONE_FIFTY;
  ZERO_FIFTY:
    if(fifty_in)
    state <= ONE;
    else if(onedollar_in)
    state <= ONE_FIFTY;
  ONE:
    if(fifty_in)
    state <= ONE_FIFTY;
    else if(onedollar_in)
    state <= TWO;
  ONE_FIFTY:
    if(fifty_in)
    state <= TWO;
    else if(onedollar_in)
    begin
     state   <= IDLE;
     drink_out <= 1;
    end
  TWO:
    if(fifty_in)
    begin
    state   <= IDLE;
    drink_out <= 1;
    end
    else if(onedollar_in)
    begin
     state   <= IDLE;
     drink_out <= 1;
     fifty_out <= 1;
    end
  endcase
end
end
always@(posedge[/email] clk)
begin
next_state <= state;
end
endmodule

case每个分支最好都对相同的一些寄存器赋值,case一定要加default。if else最好一一配对。有一个if就要一个else而且if里赋值的寄存器。在else里也要写出来。这些是容易产生latch的。
在这里你的状态机和输出最好分开两个always来写。
fifty_out <= 0;
drink_out <= 0;
if(!rst)
  state  <= IDLE;
else
  begin
  state  <= next_state;
红色语句是不需要的。

"<= " need to modify to " = " in combination block.

后一个always语句是干什么的?有必要吗?

第二个always block是用来把将上一个状态(nxt_state)在clk positive posedge来时,变成现在的状况(state).属於sequence circuit.
第一个always block是用根据目前的输入讯号来决定下一个状态是什么.属於combination circuit.

这样写的话,仿真没问题,在综合中就会碰到问题,因为next_state分别在2个always中进行了赋值所以不可综合,我认为你只要保留前面的组合逻辑就可以了。还请高手指点!

module drink_machine(rst,clk,onedollar_in,fifty_in,fifty_out,drink_out);
parameter IDLE   = 0;
parameter ZERO_FIFTY = 1;
parameter ONE   = 2;
parameter ONE_FIFTY = 3;
parameter TWO   = 4;
input  clk;
input  fifty_in;
input  onedollar_in;
input  rst;
output fifty_out;
output drink_out;
reg fifty_out,drink_out;
reg[2:0] state,next_state;
always@(onedollar_in or fifty_in or rst)
begin
if(!rst)
begin
  fifty_out = 0;
  drink_out = 0;
  state = IDLE;
end
else
  begin
  case(next_state)
  IDLE:
    begin
    fifty_out = 0;
    drink_out = 0;
    if(fifty_in)
    state = ZERO_FIFTY;
    else if(onedollar_in)
    state =  ONE_FIFTY;
    end
  ZERO_FIFTY:
    if(fifty_in)
    state = ONE;
    else if(onedollar_in)
    state = ONE_FIFTY;
  ONE:
    if(fifty_in)
    state = ONE_FIFTY;
    else if(onedollar_in)
    state = TWO;
  ONE_FIFTY:
    if(fifty_in)
    state = TWO;
    else if(onedollar_in)
    begin
     state   = IDLE;
     drink_out = 1;
    end
  TWO:
    if(fifty_in)
    begin
    state   = IDLE;
    drink_out = 1;
    end
    else if(onedollar_in)
    begin
     state   = IDLE;
     drink_out = 1;
     fifty_out = 1;
    end
   default: state = IDLE;
  endcase
  end
end
always@(posedge clk)
begin
next_state <= state;
end
endmodule

改了下,你再试试

谢谢啊哈,借鉴2楼的建议,我已经解决了这个问题!~

// Description:   简单的自动售饮料机,假定一瓶饮料价格为2元5角,投币分别为一元和五角两种硬币。
//       每次投入硬币为一元或者五角,如果投入金币的总和是两元五角时,输出一瓶饮料;
//       如果投币总和是三元时,输出一瓶饮料,并且找回五角。
//
//   三段式方法

module drink_machine(rst,clk,onedollar_in,fifty_in,fifty_out,drink_out);
parameter IDLE   = 0;
parameter ZERO_FIFTY = 1;
parameter ONE   = 2;
parameter ONE_FIFTY = 3;
parameter TWO   = 4;
input  clk;
input  fifty_in;
input  onedollar_in;
input  rst;
output fifty_out;
output drink_out;
reg fifty_out,drink_out;
reg[2:0] state,next_state;
//state switch each cycle
always@(posedge clk or negedge rst)
begin
  if(!rst)
     state <= IDLE;
  else
     state <= next_state;
end
//next_state judge
always@(onedollar_in or fifty_in or rst)
begin
if(!rst)
begin
  next_state = IDLE;
end
else
  begin
  case(state)
  IDLE:
    begin
      if(fifty_in)
        next_state = ZERO_FIFTY;
      else if(onedollar_in)
        next_state =  ONE;
    end
  ZERO_FIFTY:
    begin
      if(fifty_in)
        next_state = ONE;
      else if(onedollar_in)
        next_state = ONE_FIFTY;
    end
  ONE:
    begin
      if(fifty_in)
        next_state = ONE_FIFTY;
      else if(onedollar_in)
        next_state = TWO;
    end
  ONE_FIFTY:
    begin
      if(fifty_in)
        next_state = TWO;
      else if(onedollar_in)
        next_state   = IDLE;
    end
  TWO:
    begin
        next_state   = IDLE;
    end
  default: next_state = IDLE;
  endcase
  end
//reg output to remove glitch
always@(posedge clk or negedge rst)
begin
  if(!rst)
     begin
       drink_out <= 0;
     end
  else if (next_state==TWO)
     begin
       drink_out <= 1;
     end
end
always@(posedge clk or negedge rst)
begin
  if(!rst)
     begin
       fifty_out <= 0;
     end
  else if ((next_state==TWO)&&(onedollar_in))
     begin
       fifty_out <= 1;
     end
end   


endmodule

// Description:   简单的自动售饮料机,假定一瓶饮料价格为2元5角,投币分别为一元和五角两种硬币。
//       每次投入硬币为一元或者五角,如果投入金币的总和是两元五角时,输出一瓶饮料;
//       如果投币总和是三元时,输出一瓶饮料,并且找回五角。
//
// 三段式方法
// 消除state latch
module drink_machine(rst,clk,onedollar_in,fifty_in,fifty_out,drink_out);
parameter IDLE   = 0;
parameter ZERO_FIFTY = 1;
parameter ONE   = 2;
parameter ONE_FIFTY = 3;
parameter TWO   = 4;
input  clk;
input  fifty_in;
input  onedollar_in;
input  rst;
output fifty_out;
output drink_out;
reg fifty_out,drink_out;
reg[2:0] state,next_state;
//state switch each cycle
always@(posedge clk or negedge rst)
begin
  if(!rst)
     state <= IDLE;
  else
     state <= next_state;
end
//next_state judge
always@(onedollar_in or fifty_in or rst)
begin
if(!rst)
begin
  next_state = IDLE;
end
else
  begin
  case(state)
  IDLE:
    begin
      if(fifty_in)
        next_state = ZERO_FIFTY;
      else if(onedollar_in)
        next_state =  ONE;
      else
        next_state = IDLE;
    end
  ZERO_FIFTY:
    begin
      if(fifty_in)
        next_state = ONE;
      else if(onedollar_in)
        next_state = ONE_FIFTY;
      else
        next_state = ZERO_FIFTY;
    end
  ONE:
    begin
      if(fifty_in)
        next_state = ONE_FIFTY;
      else if(onedollar_in)
        next_state = TWO;
      else
        next_state = ONE;
    end
  ONE_FIFTY:
    begin
      if(fifty_in)
        next_state = TWO;
      else if(onedollar_in)
        next_state = IDLE;
      else
        next_state = ONE_FIFTY;
    end
  TWO:
    begin
       if(fifty_in || onedollar_in)
        next_state = IDLE;
       else
        next_state = TWO;
    end
  default: next_state = IDLE;
  endcase
  end
//reg output to remove glitch
always@(posedge clk or negedge rst)
begin
  if(!rst)
     begin
       drink_out <= 0;
     end
  else if (next_state==TWO)
     begin
       drink_out <= 1;
     end
end
always@(posedge clk or negedge rst)
begin
  if(!rst)
     begin
       fifty_out <= 0;
     end
  else if ((next_state==TWO)&&(onedollar_in))
     begin
       fifty_out <= 1;
     end
end   


endmodule

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top