どうやって作ろうか方針を練ります。
光が移動していく速度は、とりあえず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の輝度の違いがわかりづらいですね。しかも撮影したビデオはフォーカスが合ってるのに、これはなんだかぼやけてしまっています。再エンコードされたからかしら。