简单自动售饮料机 哪里错了?
//////////////////////////////////////////////////////////////////////////////////
// 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
