たくさんLチカ。

Lチカはできたんですが、どうせなら8個あるLEDを全部、適当にばらばらな間隔で点滅させてみようか、などと思い立ち、ちょっと遠回り。巫女さんと遊ぶのはもうちょっと先にしましょう。

方針としては、1msecクロックはそのままで、カウンタを8個に増やし、それぞれのLEDごとに判定ループを作ります。

まずはCLK1000HZ.vを再掲。CNT - 1に修正してあります。


// vim: set fenc=utf-8 filetype=verilog expandtab ts=4 sts=0 sw=4:
//
// generate 1000Hz clock from 50MHz osc input.
//

module CLK1000HZ (clk, reset, clk1m);
    parameter CNT = 25000;

    input clk;
    input reset;
    output clk1m;
    reg clk1m;
    reg [15:0] count;

    always @ (posedge clk or negedge reset) begin
        if (reset == 0)
        begin
            count <= 0;
            clk1m <= 0;
        end else
        if (count < CNT - 1)
        begin
            count <= count + 1;
        end
        else begin
            count <= 0;
            clk1m <= ~clk1m;
        end
    end
endmodule
1行目の // vim: はvimで編集するときにこの設定でやってよね、というおまじないないので、vimを使わない人は不要です。
16行目の if (reset == 0) は if (!reset) でもいいかもです。

次はtwincle_led.vです。これがトップモジュールになり、LEDを駆動します。


// vim: set fenc=utf-8 filetype=verilog expandtab ts=4 sts=0 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 [15:0] count1;
    reg [15:0] count2;
    reg [15:0] count3;
    reg [15:0] count4;
    reg [15:0] count5;
    reg [15:0] count6;
    reg [15:0] count7;
    reg [15:0] count8;
    
    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;

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

// LED1
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out1 <= 0;
        count1 <= 0;
    end else
    if (count1 < 100 - 1)
    begin
        count1 <= count1 + 1;
    end
    else begin
        count1 <= 0;
        _out1 <= ~_out1;
    end
end

// LED2
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out2 <= 0;
        count2 <= 0;
    end else
    if (count2 < 50 - 1)
    begin
        count2 <= count2 + 1;
    end
    else begin
        count2 <= 0;
        _out2 <= ~_out2;
    end
end

// LED3
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out3 <= 0;
        count3 <= 0;
    end else
    if (count3 < 300 - 1)
    begin
        count3 <= count3 + 1;
    end
    else begin
        count3 <= 0;
        _out3 <= ~_out3;
    end
end

// LED4
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out4 <= 0;
        count4 <= 0;
    end else
    if (count4 < 1000 - 1)
    begin
        count4 <= count4 + 1;
    end
    else begin
        count4 <= 0;
        _out4 <= ~_out4;
    end
end

// LED5
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out5 <= 0;
        count5 <= 0;
    end else
    if (count5 < 20 - 1)
    begin
        count5 <= count5 + 1;
    end
    else begin
        count5 <= 0;
        _out5 <= ~_out5;
    end
end

// LED6
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out6 <= 0;
        count6 <= 0;
    end else
    if (count6 < 2500 - 1)
    begin
        count6 <= count6 + 1;
    end
    else begin
        count6 <= 0;
        _out6 <= ~_out6;
    end
end

// LED7
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out7 <= 0;
        count7 <= 0;
    end else
    if (count7 < 100 - 1)
    begin
        count7 <= count7 + 1;
    end
    else begin
        count7 <= 0;
        _out7 <= ~_out7;
    end
end

// LED8
always @ (posedge c1kout or negedge reset) begin
    if (reset == 0)
    begin
        _out8 <= 0;
        count8 <= 0;
    end else
    if (count8 < 720 - 1)
    begin
        count8 <= count8 + 1;
    end
    else begin
        count8 <= 0;
        _out8 <= ~_out8;
    end
end

endmodule
見てわかるとおり、LEDを1から8まで増やし、それに応じてカウンタと出力信号も増やしています。

ところでVerilogの記法って、なにかスタンダードがあるんでしょうかね。たとえばモジュール定義の信号名は大文字にするとかCamelCaseにするとか、モジュール名はどう書く、とか。ここらへん、今ひとつわかりませんでした。
そしてピン定義ファイル LED.lpf。

BLOCK RESETPATHS ;
BLOCK ASYNCPATHS ;
IOBUF ALLPORTS IO_TYPE=LVTTL33 ;
LOCATE COMP "LED1" SITE "46" ;
LOCATE COMP "LED2" SITE "45" ;
LOCATE COMP "LED3" SITE "44" ;
LOCATE COMP "LED4" SITE "43" ;
LOCATE COMP "LED5" SITE "40" ;
LOCATE COMP "LED6" SITE "39" ;
LOCATE COMP "LED7" SITE "38" ;
LOCATE COMP "LED8" SITE "37" ;
LOCATE COMP "clk" SITE "21" ;
LOCATE COMP "reset" SITE "19" ;
IOBUF PORT "clk" IO_TYPE=LVTTL33 PULLMODE=NONE ;
IOBUF PORT "reset" IO_TYPE=LVTTL33 PULLMODE=UP ;
なにやら大文字小文字が混ざっていて気持ち悪い部分がありますが、ここではキニシナイことにしましょう。

ソースの修正が終わったらコンパイルとプログラムです。
そうしたら、オレンジ色でこんなメッセージが表示されました。

@W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[7] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[8] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[9] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[10] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[11] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[12] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[13] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[14] to a constant 0 @W: CL190 :"D:\Users\chiyo\lattice_projects\LED\twincle_led.v":45:0:45:5|Optimizing register bit count1[15] to a constant 0

カウンタループの中での判定値が16bit幅では余るため、上位ビットは0に固定しましたよ、というメッセージです。こんな最適化もしてくれるんですね。 

プログラムしてみると、8個のLEDがワザワサと動き始めました。

0 件のコメント:

コメントを投稿

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

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