赞
踩
目录
设计一个自动贩售机,输入货币有三种,为0.5/1/2元,饮料价格是1.5元,要求进行找零,找零只会支付0.5元。
ps:
1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号
2、注意rst为低电平复位
信号示意图:
波形示意图:
- module seller1(
- input wire clk ,
- input wire rst ,
- input wire d1 , //0.5元
- input wire d2 , //1.0元
- input wire d3 , //2.0元
-
- output reg out1, //饮料
- output reg [1:0]out2 //零钱
- );
- //*************code***********//
-
-
- parameter [2:0] s0 = 3'b000,
- s1 = 3'b001,
- s2 = 3'b010,
- s3 = 3'b011,
- s4 = 3'b100,
- s5 = 3'b101,
- s6 = 3'b110;
-
- reg [2:0] curr_state;
- reg [2:0] next_state;
-
- //第一段 状态转移
- always @(posedge clk or negedge rst)begin
- if(!rst)
- curr_state <= s0;
- else
- curr_state <= next_state;
- end
-
- //第二段 转移状况
- always @(*)begin
- case(curr_state)
- s0:begin
- if(d1) next_state = s1;
- else if(d2) next_state = s2;
- else if(d3) next_state = s3;
- else next_state = next_state; //为什么保持原值next_state,而不是s0?
- end
- s1:begin
- if(d1) next_state = s2;
- else if(d2) next_state = s4;
- else if(d3) next_state = s5;
- else next_state = next_state;
- end
- s2:begin
- if(d1) next_state = s4;
- else if(d2) next_state = s3;
- else if(d3) next_state = s6;
- else next_state = next_state;
- end
- s3,s4,s5,s6:begin next_state = s0;end
- default: begin next_state = s0;end
- endcase
- end
-
- //第三段 状态输出 moore FSM
-
- always @(posedge clk or negedge rst)begin //为什么用时序电路,而不是组合电路?
- if(!rst)
- out1 <= 0;
- else if(
- next_state == s3 ||
- next_state == s4 ||
- next_state == s5 ||
- next_state == s6
- )
- out1 <= 1; //出货标志
- else
- out1 <= 0;
- end
-
- always @(posedge clk or negedge rst)begin //为什么用时序电路,而不是组合电路?
- if(!rst)
- out2 <= 0;
- else if(next_state == s3)
- out2 <= 2'd1; //找零5毛的数量
- else if(next_state == s5)
- out2 <= 2'd2;
- else if(next_state == s6)
- out2 <= 2'd3;
- else
- out2 <= 2'b0;
- end
-
- //*************code***********//
- endmodule

针对代码中的问题“为什么保持原值next_state,而不是s0?”
答:如下图所示,如果保持s0,因为是组合逻辑,且输入信号d1为半个时钟周期,那么就会导致next_state在s1和s0之间翻转,而不是保持正确的状态s1。
参考这个回答:
仿真图:
仿真代码:
- module tb_seller1;
-
- reg clk;
- reg rst;
- reg d1,d2,d3;
-
- wire out1;
- wire [1:0] out2;
-
- //1、初始化
- initial begin
- clk = 0;
- rst = 0;
- d1 = 0;
- d2 = 0;
- d3 = 0;
- end
-
- //2、产生激励
- always #5 clk = ~clk;
-
- initial begin
- #10;
- rst = 1'b1;
-
- #20;
- @(posedge clk); {d1,d2,d3}=3'b100; //0.5
- @(posedge clk); {d1,d2,d3}=3'b000;
- #50;
- @(posedge clk); {d1,d2,d3}=3'b010; //1.5
- @(posedge clk); {d1,d2,d3}=3'b000;
- #30;
- @(posedge clk); {d1,d2,d3}=3'b100; //0.5
- @(posedge clk); {d1,d2,d3}=3'b000;
- #60;
- @(posedge clk); {d1,d2,d3}=3'b100; //1
- @(posedge clk); {d1,d2,d3}=3'b000;
- #50;
- @(posedge clk); {d1,d2,d3}=3'b001; //3
- @(posedge clk); {d1,d2,d3}=3'b000;
- #50;
- @(posedge clk); {d1,d2,d3}=3'b001; //2
- @(posedge clk); {d1,d2,d3}=3'b000;
- #30;
- @(posedge clk); {d1,d2,d3}=3'b100; //0.5
- @(posedge clk); {d1,d2,d3}=3'b000;
- #60;
- @(posedge clk); {d1,d2,d3}=3'b001; //2.5
- @(posedge clk); {d1,d2,d3}=3'b000;
- #50;
- @(posedge clk); {d1,d2,d3}=3'b010; //1
- @(posedge clk); {d1,d2,d3}=3'b000;
- #60;
- @(posedge clk); {d1,d2,d3}=3'b010; //2
- @(posedge clk); {d1,d2,d3}=3'b000;
- end
-
- //3、仿真暂停
- initial begin
- #1000
- $finish();
- end
-
- //4、实例化
- seller1 u1_seller1(
- .clk(clk),
- .rst(rst),
- .d1 (d1), //0.5元
- .d2 (d2), //1.0元
- .d3 (d3), //2.0元
- .out1(out1), //饮料
- .out2(out2) //零钱
- );
-
- endmodule

设计一个自动贩售机,输入货币有两种,为0.5/1元,饮料价格是1.5/2.5元,要求进行找零,找零只会支付0.5元。
ps:
1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号
2、此题忽略出饮料后才能切换饮料的问题
注意rst为低电平复位
波形示意图:
- module seller2(
- input wire clk ,
- input wire rst ,
- input wire d1 , //0.5元
- input wire d2 , //1.0元
- input wire sel , //0选择1.5元、1选择2.5元
-
-
- output reg out1, //饮料1(1.5元)
- output reg out2, //饮料2(2.5元)
- output reg [1:0]out3 //零钱
-
- );
- //*************code***********//
-
-
- parameter [2:0] s0 = 3'b000,
- s1 = 3'b001,
- s2 = 3'b010,
- s3 = 3'b011,
- s4 = 3'b100,
- s5 = 3'b101,
- s6 = 3'b110;
-
- reg [2:0] curr_state;
- reg [2:0] next_state;
-
- //第一段 状态转移
- always @(posedge clk or negedge rst)begin
- if(!rst)
- curr_state <= s0;
- else
- curr_state <= next_state;
- end
-
- //第二段 转移状况
- always @(*)begin
- case(curr_state)
- s0: begin
- if(d1) next_state = s1;
- else if(d2) next_state = s2;
- else next_state = next_state;
- end
- s1: begin
- if(d1) next_state = s2;
- else if(d2) next_state = s3;
- else next_state = next_state;
- end
- s2: begin
- if(d1) next_state = s3;
- else if(d2) next_state = s4;
- else next_state = next_state;
- end
- s3: begin
- if(!sel) //选择饮料是1.5元还是2元
- begin next_state = s0; end
- else begin
- if(d1) next_state = s4;
- else if(d2) next_state = s5;
- else next_state = next_state;
- end
- end
- s4: begin
- if(!sel)
- begin next_state = s0; end
- else begin
- if(d1) next_state = s5;
- else if(d2) next_state = s6;
- else next_state = next_state;
- end
- end
- s5: begin next_state = s0; end
- s6: begin next_state = s0; end
- default: begin next_state = s0;end
- endcase
- end
-
- /********* 第三段 状态输出 moore FSM ************/
-
- //出货标志
- always @(posedge clk or negedge rst)begin
- if(!rst)begin
- out1 <= 0;
- out2 <= 0;
- end
- else if(sel==0 && (next_state == s3 || next_state == s4) )
- out1 <= 1; //饮料1
- else if(sel==1 && (next_state == s5 || next_state == s6) )
- out2 <= 1; //饮料2
- else begin
- out1 <= 0;
- out2 <= 0;
- end
- end
-
- //找零数量
- always @(posedge clk or negedge rst)begin
- if(!rst)
- out3 <= 0;
- else if(sel==0 && (next_state == s4) )
- out3 <= 2'd1; //饮料1
- else if(sel==1 && (next_state == s6) )
- out3 <= 2'd1; //饮料2
- else
- out3 <= 2'b0;
- end
-
- //*************code***********//
- endmodule

仿真图如下:
以上是mealy和moore型状态机的实现区别,注意在代码里理解!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。