ナイトライダーを作ってみる。

さてそれではナイトライダー…っぽいLED Flasherです。
どうやって作ろうか方針を練ります。

光が移動していく速度は、とりあえずLEDが8個なので片道1秒とすれば125msecになります。まずはその線でいってみましょう。
LEDの輝度は、1000と30と1くらいでいいかしら。8個中3個が同時点灯という形で。

制御方法ですが、16ステップのシーケンサを作ってしまえばいいかな。4bitのフラグレジスタを用意して、125msecごとにフラグ値の処理を行い、フラグを+1する、という感じ。
125msecごとに起動するのは50MHzのクロックだと50000000/8=6250000なので、24bitのカウンタを用意して5F5E10hと比較すればいいかな。フラグが立ったらカウンタをリセット。

パターンはオール0から始まって、

0000 0001
0000 0012
0000 0123
0000 1230

0001 2300
0012 3000
0123 0000
1230 0000

2300 0000
3000 0000
1000 0000
2100 0000

3210 0000
0321 0000
0032 1000
0003 2100

0000 3210
0000 0321
0000 0032
0000 0003

ん、20パターンですねぇ。ちょっと美しくないけれどこれでやってみましょうか。

最初の100行ほどが変わるだけなので、その部分だけ貼り付けます。


// vim: set fenc=utf-8 filetype=verilog expandtab ts=4 sts=4 sw=4:
//
// generate 1000Hz clock from 50MHz osc input.
//
module LED_TOP(clk, reset,
    LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8);
    input clk;
    input reset;
    output LED1, LED2, LED3, LED4, LED5, LED6, LED7, LED8;
    wire c1kout;

    reg [7:0] count1;
    reg [7:0] count2;
    reg [7:0] count3;
    reg [7:0] count4;
    reg [7:0] count5;
    reg [7:0] count6;
    reg [7:0] count7;
    reg [7:0] count8;

    reg [9:0] duty1 = 1000;
    reg [9:0] duty2 = 0;
    reg [9:0] duty3 = 0;
    reg [9:0] duty4 = 0;
    reg [9:0] duty5 = 0;
    reg [9:0] duty6 = 0;
    reg [9:0] duty7 = 0;
    reg [9:0] duty8 = 0;

    reg  _out1;
    reg  _out2;
    reg  _out3;
    reg  _out4;
    reg  _out5;
    reg  _out6;
    reg  _out7;
    reg  _out8;
    
assign LED1 = _out1;
assign LED2 = _out2;
assign LED3 = _out3;
assign LED4 = _out4;
assign LED5 = _out5;
assign LED6 = _out6;
assign LED7 = _out7;
assign LED8 = _out8;

 reg [23:0] seq; // sequence counter
 reg [4:0] step; // sequence step flag

CLK10000HZ c1k(
    .clk(clk),
    .reset(reset),
    .clk1m(c1kout));

// sequencer
always @ (posedge clk or negedge reset) begin
    if (reset == 0)
    begin
        seq <= 0;
        step <= 0;
    end else
    if (seq < 24'h5F5E10 - 1)
    begin
        seq <= seq + 1;
    end
    else
    begin
        seq <= 0;
        case (step)
            5'b00000 : begin duty1 <=  1000; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b00001 : begin duty1 <=  30; duty2 <=  1000; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b00010 : begin duty1 <=  1; duty2 <=  30; duty3 <=  1000; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b00011 : begin duty1 <=  0; duty2 <=  1; duty3 <=  30; duty4 <=  1000; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b00100 : begin duty1 <=  0; duty2 <=  0; duty3 <=  1; duty4 <=  30; duty5 <=  1000; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b00101 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  1; duty5 <=  30; duty6 <=  1000; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b00110 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  1; duty6 <=  30; duty7 <=  1000; duty8 <=  0; step <=  step + 1; end
            5'b00111 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  1; duty7 <=  30; duty8 <=  1000; step <=  step + 1; end
            5'b01000 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  1; duty8 <=  30; step <=  step + 1; end
            5'b01001 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  1; step <=  step + 1; end
            5'b01010 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  1000; step <=  step + 1; end
            5'b01011 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  1000; duty8 <=  30; step <=  step + 1; end
            5'b01100 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  1000; duty7 <=  30; duty8 <=  1; step <=  step + 1; end
            5'b01101 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  1000; duty6 <=  30; duty7 <=  1; duty8 <=  0; step <=  step + 1; end
            5'b01110 : begin duty1 <=  0; duty2 <=  0; duty3 <=  0; duty4 <=  1000; duty5 <=  30; duty6 <=  1; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b01111 : begin duty1 <=  0; duty2 <=  0; duty3 <=  1000; duty4 <=  30; duty5 <=  1; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b10000 : begin duty1 <=  0; duty2 <=  1000; duty3 <=  30; duty4 <=  1; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b10001 : begin duty1 <=  1000; duty2 <=  30; duty3 <=  1; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b10010 : begin duty1 <=  30; duty2 <=  1; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  step + 1; end
            5'b10011 : begin duty1 <=  1; duty2 <=  0; duty3 <=  0; duty4 <=  0; duty5 <=  0; duty6 <=  0; duty7 <=  0; duty8 <=  0; step <=  0; end
        endcase
    end
end

case文のところはわかりやすく記述したかったので、貼り付けたらかえって見辛くなってしまいましたが、1000のところだけを追いかければ「行って戻って」を繰り返すような記述になっているのがわかると思います。

撮影してみました。


両端での折り返しはこんな感じでいいんですかね。あと、肉眼だとわかるんですが、ビデオだと露出の関係かLEDの輝度の違いがわかりづらいですね。しかも撮影したビデオはフォーカスが合ってるのに、これはなんだかぼやけてしまっています。再エンコードされたからかしら。

0 件のコメント:

コメントを投稿

Vimの補完プラグインをインストール。その4

Vimの補完プラグインをインストール。その3 で、 ddc-tabnine が使えそうです、などと書いたのですが、早速やってみました。 まず、tabnineのバイナリを用意しないといけません。がどうにもTabNineのサイトがわかりにくいので、 tabnine-nvim にあるダ...