shtaxxx日記

コンピュータアーキテクチャについて研究している研究者の日記や技術紹介

Verilog-HDLのtask文を回路記述に使ってみよう -まず手始めに-

taskでVerilogをCっぽく書いてみる・・・がしかし

ハードウェア記述言語のVerilog-HDLにはtask文という構文がある.
task文中では逐次的にreg変数への代入が記述できる.
通常,task文はテストベンチ中でテストターゲットの操作を行うために利用するが,
これをなんとかうまくつかって,逐次処理の記述を楽に行うことは出来ないだろうか.

「4ビットのLEDでナイトライダー」を普通に書く

まずは普通に書いてみる.

module led(CLK, RST_X, O_ULED);
    input CLK;
    input RST_X;
    output reg [3:0] O_ULED;
    parameter skip_max = 1024*1024*45;
    parameter state_max = 5;
    reg [26:0] skip_cnt;
    reg [2:0] state;
    
    always @(posedge CLK or negedge RST_X) begin
        if(!RST_X) begin
            O_ULED <= 4'b0101;
            state <= 0;
            skip_cnt <= 0;
        end else begin
            skip_cnt <= (skip_cnt==skip_max)? 0:skip_cnt +1;
            if(skip_cnt == skip_max) begin
                state <= (state == state_max)? 0: state +1;
                case(state)
                    0: O_ULED <= 4'b0001;
                    1: O_ULED <= 4'b0010;
                    2: O_ULED <= 4'b0100;
                    3: O_ULED <= 4'b1000;
                    4: O_ULED <= 4'b0100;
                    5: O_ULED <= 4'b0010;
                    default: O_ULED <= 4'b0000;
                endcase 
            end
        end
    end
endmodule

もちろんちゃんと動作する.
(シミュレーションではskip_maxの値は変更している)

「4ビットのLEDでナイトライダー」をこんな風に書きたい

module led(CLK, RST_X, O_ULED);
    input CLK, RST_X;
    output reg [3:0] O_ULED;
    parameter skip_max = 1024*1024*45;

    task nclk;
        begin
            @(posedge CLK);
        end
    endtask

    task skip;
        input integer step;
        integer i;
        begin
            for(i=0;i<step;i=i+1) nclk();
        end
    endtask
    
    task flash;
        O_ULED = 4'b0001;
        skip(skip_max);
        O_ULED = 4'b0010;
        skip(skip_max);
        O_ULED = 4'b0100;
        skip(skip_max);
        O_ULED = 4'b1000;
        skip(skip_max);
        O_ULED = 4'b0100;
        skip(skip_max);
        O_ULED = 4'b0010;
        skip(skip_max);
        O_ULED = 4'b0001;
        skip(skip_max);
    endtask

    initial begin
        O_ULED = 0;
        flash();
    end
endmodule

もちろん,
シミュレーションでは動いても,ISEさんは合成してくれないよ!!

task文中で"1クロック待つ"ということが実現できれば,
なんとかなりそうなのに.

でもreg変数への代入の競合を避けなければいけないから,
結局同じことかなぁ.