電子サイコロとは?
電子サイコロは、電源を入れるとサイコロの目を模した1~6のパタンが、高速に変化して表示され、しばらくするといずれかの目を表示しながら止まる。という電子玩具です。
こんなカンジ。
www.elekit.co.jp
ぼくが最初に見たのは、1978年ころ、多分「ラジオの製作」(現:電子工作マガジン)の記事で見た、嘉穂無線(現:EK_JAPAN)のエレキットのコロスケくん(だいすきット?サイコロン?)だったと思います。
上の写真は、同じメーカーの何代もあとの子孫になります。
紹介のキットや、初代のキットは、多分4000番台を使ったCMOS ICを使ってると思います。
しかし、最近知古本市通いで知ったんですが、CMOS IC以前にも、回路が知られていた様です。
TTL ICや、バイポーラ・トランジスタ-フリップフロップ構成のものは想像がついてましたが、
それ以前の非線形部品でも、作例があった様です。
まとめて本にしたいと思ってるんですが、ちゃんと詰めるのが難しいので、できそうな企画から、小出しにしてみます。
FPGA に code golf 実装してみた
CMOS ICでは70年代後半から80年代前半の回路ですが、近代版を考えると、モシモシアプリ版ということになるんでしょう。
それ以外にもFPGA版というのもありそうですね。
単にHDLで書いただけではつまらないので、今回はcode golfしてみました。
code
module D(input C,R,output X,output integer Q,L);always@(posedge C){L,Q}<={"N76321">>Q*8,R?Q:(Q+1)%6};assign X=~C;endmodule
122文字です。VHDLだと標準ライブラリのインクルードも終わらないかも?
C,R pinは シュミット指定してください。
BOM(部品表)とnet list(配線表)は以下
(説明のためのイメージです。実働試験はしていません)
== BOM : FPGA: any C0 :0.1uF R0 :10kohm C1 :10uF R1 :1Mohm PSW :push switch LED0 :any LED1 :any LED2 :any LED3 :any LED4 :any LED5 :any == net list FPGA.L[0],LE0.A FPGA.L[1],LED1.A,LED6.A FPGA.L[2],LED2.A,LED5.A FPGA.L[3],LED3.A,LED4.A FPGA.C,C0.A,R0.A FPGA.X,R0.B R1.B,PSW.B,C1.B VCC,LED0.K,LED1.k,LED2.k,KLED3.k,LED4.K,LED5.K,LED6.K,R1.A GND,C1.A,PSW.A,C0.B
結果
Quartus prime Lite :18.1.0 625で、10M08DAF484C8G用にコンパイルして
LE:86 FF:32 fck max : 77.3MHzでした。んーかなり無理がある。
sim結果はこんなカンジです
テストベンチは以下。
`timescale 1ns/1ns module TB ( ) ; wire [31:0] Q ; wire [31:0] L ; wire X ; wire #(1.0) C = X ; //clock net feed, image CR delay reg R ; D D ( .C ( C ) //rise edge clock input schumit trigger , .R ( R ) //H:dice stop L:dice roll ,schumit trigger //connect pull up , and through push sw GND , .X ( X ) //invert out clock C , .Q ( Q ) //dice face counter use [2:0] 0~5 , .L ( L ) //dice face use [6:0], H:On ,L:Off // face patter, // 1 2th bit // 3 0 4 // 5 6 ) ; wire [2:0] CTRs = Q[2:0] ; //pick up dice face counter bit wire [6:0] LEDs = { // dice face pattern make up L[1] , L[2] , L[3] , L[3] , L[2] , L[1] , L[0] } ; // count light on LED dots function [31:0] f_count ; input [31:0] DATs ; integer i ; begin f_count = 0 ; for(i=0;i<32;i=i+1) f_count = f_count + DATs[i] ; end endfunction wire [3:0] LIGHT_CTRs = f_count( LEDs ) ; initial begin R <= 1'b0 ; // the dice roll on force C =1 ; // innitial reg/wire , cancel unstable force D.C =1 ; force D.Q = 0 ; #(2) release C ; // auto running the circuit release D.C ; release D.Q ; #(100) R <= 1'b1 ; // stop rolling #(10) $stop ; $end ; end endmodule /* user radix face on Model sim // copy after part to file DICE_FASE.tcl // and load Modelsim.wave // 1 2 // 3 0 4 // 5 6 8<----------cut from here ------------- radix define DICE_FACEs { 6'b00_00_00_1 "1" -color red , 6'b01_00_10_0 "2" -color white , 6'b10_00_01_0 "2" -color white , 6'b01_00_10_1 "3" -color white , 6'b10_00_01_1 "3" -color white , 6'b11_00_11_0 "4" -color white , 6'b11_00_11_1 "5" -color white , 6'b11_11_11_0 "6" -color white , -default binary -defaultcolor purple } ----------------- to here ----------->8 */
simがmodelsimの場合後半のradix faceをインクルードすれば、それっぽい表示をしてくれます。
モジュロ(%)を6でなく12,48,96にして、LEDにつなぐpinをずらせば、すれば、動作中にサウンダーも鳴らせますね。1文字増えますが
問題
このままだと、カウンタストップのR pinがマルチステーブル/ラッチミス問題を起こし、
変な表示をしそうですね。code GOLF hack版ということで。