続き。DE0 FPGAでFizzBuzz
前回は3進5進カウンターを使ってFizzBuzzを判定していたが、これはリセットと同期してカウントアップしなければならないという制限がある。では4桁の任意のBCD入力に対して簡単に判定することはできるか?
ソフトでは3の剰余を求めたりするがこれは除算でありそんな大げさなものは動かしたくない。ではテーブル?buzzなら5の倍数なので、最後の桁が0または5で判断できる。
では3の倍数であるfizzは?ちょっとこねくりまわしてみた。
3の倍数だけ取り出す。
$ awk 'BEGIN{for(i=1;i<10000;i++) printf("%04d\n",i)}' > fizz.txt
それぞれの桁をすべて足して3の剰余を求めると
$ awk '{print substr($1,1,1) substr($1,2,1) substr($1,3,1) substr($1,4,1)}' fizz.txt | gawk '{print $1%3}'
なんかいけそう。
組み合わせ回路で実現できる。
BCDの4桁それぞれに対して3の剰余を求める。それぞれの桁は0,1,2になる。これの総和は最大で8なので、これに対して3の剰余を求める。こうするとfizzが判定できる。
確認のためにトップモジュールではスライドスイッチによりBCDを入力してボタン2を押すと、その設定値からFizzBuzzのカウントを開始するようにした。
QuartusIIで[Project]→[Archive Project...]を選択するとプロジェクトをひとまとめにしてくれる。ダイアログで[Advanced]ボタンを押し、一番上のFileset:はService Requestを選択。これで出力するとoutout_filesディレクトリ以下にfizzbuzz.qarというようなファイルができる。これを他のQuartusIIがインストールされているマシンに持って行ってダブルクリックするとプロジェクトが展開される。
以下に置いてみました。
fizzbuzz.qar(Googls Docs)
追記:
それぞれの桁をa,b,c,dとおく。a+b+c+d=mod3なら1000a+100b+10c+dもmod3か?
999a+99b+9c + a+b+c+dとすると、9(111a+11b+c) + a+b+c+d で 3で割り切れて0 と + mod3となる。
ってことでよいのかな。中学二年の範囲。
前回は3進5進カウンターを使ってFizzBuzzを判定していたが、これはリセットと同期してカウントアップしなければならないという制限がある。では4桁の任意のBCD入力に対して簡単に判定することはできるか?
ソフトでは3の剰余を求めたりするがこれは除算でありそんな大げさなものは動かしたくない。ではテーブル?buzzなら5の倍数なので、最後の桁が0または5で判断できる。
では3の倍数であるfizzは?ちょっとこねくりまわしてみた。
3の倍数だけ取り出す。
$ awk 'BEGIN{for(i=1;i<10000;i++) printf("%04d\n",i)}' > fizz.txt
それぞれの桁をすべて足して3の剰余を求めると
$ awk '{print substr($1,1,1) substr($1,2,1) substr($1,3,1) substr($1,4,1)}' fizz.txt | gawk '{print $1%3}'
なんかいけそう。
組み合わせ回路で実現できる。
BCDの4桁それぞれに対して3の剰余を求める。それぞれの桁は0,1,2になる。これの総和は最大で8なので、これに対して3の剰余を求める。こうするとfizzが判定できる。
module bcdmod3(BCD,BCDout);
input [3:0] BCD;
output [3:0] BCDout;
function [3:0] mod3;
input [3:0] bcdin;
begin
case (bcdin)
1: mod3=1;
2: mod3=2;
4: mod3=1;
5: mod3=2;
7: mod3=1;
8: mod3=2;
default: mod3=0;
endcase
end
endfunction
assign BCDout=mod3(BCD);
endmodule
module chkfizz(BCD3,BCD2,BCD1,BCD0, fizz);
input [3:0] BCD3;
input [3:0] BCD2;
input [3:0] BCD1;
input [3:0] BCD0;
output fizz;
wire [3:0] sBCD3;
wire [3:0] sBCD2;
wire [3:0] sBCD1;
wire [3:0] sBCD0;
wire [3:0] tBCD;
wire [3:0] aBCD;
bcdmod3 bcdmod3_3(BCD3,sBCD3);
bcdmod3 bcdmod3_2(BCD2,sBCD2);
bcdmod3 bcdmod3_1(BCD1,sBCD1);
bcdmod3 bcdmod3_0(BCD0,sBCD0);
assign tBCD=sBCD3+sBCD2+sBCD1+sBCD0;
bcdmod3 bcdmod3_a(tBCD,aBCD);
assign fizz=(aBCD==4'd0);
endmodule
確認のためにトップモジュールではスライドスイッチによりBCDを入力してボタン2を押すと、その設定値からFizzBuzzのカウントを開始するようにした。
QuartusIIで[Project]→[Archive Project...]を選択するとプロジェクトをひとまとめにしてくれる。ダイアログで[Advanced]ボタンを押し、一番上のFileset:はService Requestを選択。これで出力するとoutout_filesディレクトリ以下にfizzbuzz.qarというようなファイルができる。これを他のQuartusIIがインストールされているマシンに持って行ってダブルクリックするとプロジェクトが展開される。
以下に置いてみました。
fizzbuzz.qar(Googls Docs)
追記:
それぞれの桁をa,b,c,dとおく。a+b+c+d=mod3なら1000a+100b+10c+dもmod3か?
999a+99b+9c + a+b+c+dとすると、9(111a+11b+c) + a+b+c+d で 3で割り切れて0 と + mod3となる。
ってことでよいのかな。中学二年の範囲。