Commit 36b9c537 authored by yuki.yahagi's avatar yuki.yahagi

券売機の設計例

parent 2184317c
// お金は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
// kenbaiki_TB.v
`timescale 1ns/1fs
module kenbaiki_TB;
reg ticket, clk, reset_N; // input
reg [1:0] in; // input
wire [1:0] payback, out; // output
parameter CLOCK = 2.0; // クロック周期(ns)
kenbaiki kenbaiki(in, ticket, clk, reset_N, payback, out); // テストにかける回路の準備
initial clk = 1; // クロックの準備
always #(CLOCK/2) // クロックを作っている
clk <= ~clk;
initial // おまじない
begin
$dumpfile("rtl.dump"); // 出力されるダンプファイル(これを元に波形が見れます)
$dumpvars(0,kenbaiki_TB);
end
initial // おまじないらしいよ
begin
in <= 2'b00;
ticket <= 1'b0; //初期化
reset_N <= 1'b0; //resetは0入力でかかる
repeat(2) @(negedge clk); // 信号の変化はクロック立ち上がりでやってはよくない
// そのため2つクロックが立ち下がるまで待つ
reset_N <= 1'b1; //リセットを解除
//50円->待機->50円->発券
#(CLOCK) // 1クロック待機
in <= 2'b10;
#(CLOCK) // 1クロック待機
in <= 2'b00;
#(CLOCK) // 1クロック待機
in <= 2'b10;
#(CLOCK)
in <= 2'b00;
ticket <= 1'b1;
//50円->発券
#(CLOCK) // 1クロック待機
in <= 2'b10;
ticket <= 1'b0;
#(CLOCK)
in <= 2'b00;
ticket <= 1'b1;
//100円->50円->発券
#(CLOCK) // 1クロック待機
in <= 2'b11;
ticket <= 1'b0;
#(CLOCK) // 1クロック待機
in <= 2'b10;
#(CLOCK)
in <= 2'b00;
ticket <= 1'b1;
//50円->100円->発券
#(CLOCK) // 1クロック待機
in <= 2'b10;
ticket <= 1'b0;
#(CLOCK) // 1クロック待機
in <= 2'b11;
#(CLOCK)
in <= 2'b00;
ticket <= 1'b1;
#(CLOCK*6) //6クロック待機
$finish; //シミュレーション終了
end
endmodule
# kenbaikiについて
## ファイル一覧
kenbaiki.v : *券売機のRTLファイル*
kenbaiki_TB.v : *kenbaiki.vのテストベンチ*
## 設計について
50円券と100円券を売り出す券売機を考える.
お金は50円玉と100円玉だけを受け付け,投入された金額に応じた券を出す(100円分入ってたら50円券は買えず,必ず100円券が出てくる).
券売機は箱に,お金の投入口,発券ボタン1つ,発券口,余剰なお金の払い戻し口がついている構成.以下,入出力の詳細.
input [1:0] in; //お金の入力(2ビット),上位ビットがお金投入の有無,下位ビットがお金の種類
input ticket; //発券ボタンの入力,投入されている金額に応じた券を発券
output [1:0] payback; //余剰な投入金額の払い戻し出力,上位ビットが払い戻しの有無,下位ビットががお金の種類
output [1:0] out; //発券の出力,上位ビットが発券の有無,下位ビットが券の種類
input clk, reset_N; //クロック信号とリセット信号の入力
このように,何を入力で与え,それぞれのビット幅がいくつになるのか,それぞれのビットは何を表すのかをきちんと決めることが設計で重要になってくる.
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment