最近在看笔试面试题,发现这个“自动售货机”的题目挺是经典。觉得自己应该能应付的过来,做起来才发现,没那么简单——明明不用状态机就能实现的,逼着自己往状态机那边跑,脑汁差不多被榨干了。 或许新手就是这样子...经验不行。
大概写了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 =============== 没时间注释了 ,日后再说
文章评论(0条评论)
登录后参与讨论