// お金は50円と100円,券は50円券と100円券. // in, payback, outは,上位ビットで有(1)無(0), // 下位ビットで50円(0)か100円(1)を判断. // 払い戻しは余剰にお金が入った時のみの鬼畜仕様. // 券発行よりもお金投入を優先する. module kenbaiki(in, ticket, clk, reset_N, payback, out); input [1:0] in; //上位ビットがお金投入,下位ビットがお金の種類 input ticket, clk, reset_N; //順にチケット発行,クロック,リセット信号(0入力でリセット) output [1:0] payback; //上位ビットが払い戻し有り無し,下位ビットがお金の種類 output [1:0] out; //上位ビットがお金投入,下位ビットがお金の種類 reg s1,s2,s3; //現在のステートを記憶 //s1は料金0円の初期状態,s2は50円投入,s3は100円投入 reg [1:0] rpay, rout; //wireにはassign文でしか値を代入できない //regにはalways構文中でしか値を代入できない //outputはwireなので,always構文で動作するステートマシンの出力をする時は, //always構文中で使うregを経由してからassign文で出力する. assign payback = rpay; assign out = rout; always @(posedge clk or negedge reset_N) begin if(!reset_N) begin //reset_N = 0でリセットをかける {s1, s2, s3} = 3'b100; //初期状態にする,{}はverilogで複数の変数をまとめて扱うことに使う rpay = 2'b00; rout = 2'b00; end else begin if (s1) begin //投入金額0円 case (in) //金額の投入を判断 8'b10: {s1, s2, s3} = 3'b010; //50円投入 8'b11: {s1, s2, s3} = 3'b001; //100円投入 default: {s1, s2, s3} = 3'b100; //それ以外 endcase rpay = 2'b00; rout = 2'b00; end else if (s2) begin //投入金額50円 if (in[1]) begin //お金が投入されていた場合 case (in) 8'b10: //50円投入 begin {s1, s2, s3} = 3'b001; rpay = 2'b00; end 8'b11: //100円投入 begin {s1, s2, s3} = 3'b001; rpay = 2'b10; //50円払い戻し end default: //それ以外 begin {s1, s2, s3} = 3'b010; rpay = 2'b00; end endcase rout = 2'b00; end else if (ticket) begin //発券信号有りのとき {s1, s2, s3} = 3'b100; //初期状態に戻して rpay = 2'b00; rout = 2'b10; // 50円券発行 end else begin //何もされていなかったとき {s1, s2, s3} = 3'b010; rpay = 2'b00; rout = 2'b00; end end else if (s3) begin //投入金額100円 if (in[1]) begin //お金が投入されていた場合 case (in) 8'b10: //50円投入 begin {s1, s2, s3} = 3'b001; rpay = 2'b10; //50円払い戻し end 8'b11: //100円投入 begin {s1, s2, s3} = 3'b001; rpay = 2'b11; //100円払い戻し end default: //それ以外 begin {s1, s2, s3} = 3'b001; rpay = 2'b00; end endcase rout = 2'b00; end else if (ticket) begin //発券信号有りの時 {s1, s2, s3} = 3'b100; //初期状態に戻して rpay = 2'b00; rout = 2'b11; // 100円券発行 end else begin //何もされていなかったとき {s1, s2, s3} = 3'b001; rpay = 2'b00; rout = 2'b00; end end else begin //ステートがおかしくなっていた時 {s1, s2, s3} = 3'b100; //初期状態にする rpay = 2'b00; rout = 2'b00; end end end endmodule