同期FIFOの作り方

[] [] []


非同期FIFOを作る準備として、ライトとリードが同じクロックに同期している同期FIFOを作る。

FPGAには2つのアドレス/データで独立にアクセスできるデュアルポートメモリ(DPM)が備わっているので、これを使えば簡単で、1ワードをライトする毎にライトアドレス(wadr)をカウントアップし、1ワードをリードする毎にリードアドレス(radr)をカウントアップすればよい。

さらに、リード側から見てデータが入っているのか、ライト側から見てデータを書き込む余地があるのかがわかるように、現在FIFOに入っているワード数を数えるカウンタを設ければよい。このとき同時にライトとリードが起きた場合を抜かさないことと、FIFOがいっぱい(full)になったときのためカウンタはアドレスより1ビット大きくしておくことに注意

同期FIFORTL記述は次のようになる

/* 同期FIFO */

module fifo #(parameter WA=8,WD=16)

    (input  rst                 // reset

    ,input  clk                 // clock

    ,input  wen                 // write enable

    ,input[WD-1:0] wdat         // write data

    ,input  ren                 // read enable

    ,output reg[WD-1:0] rdat    // read data

    ,output reg[WA:0] count_reg // counter

    );

reg[WA-1:0] wadr_reg;

reg[WA-1:0] radr_reg;

reg[WD-1:0] ram[0:2**WA-1];

/* DPM */

always @(posedge clk)

    begin

    if(wen) ram[wadr_reg] <= wdat;

    if(ren) rdat <= ram[radr_reg];

    end

/* ライトアドレス */

always @(posedge clk or posedge rst)

    begin

    if(rst)

        wadr_reg <= {WA{1'b0}};

    else if(wen)

        wadr_reg <= wadr_reg + 1'b1;

    end

/* リードアドレス */

always @(posedge clk or posedge rst)

    begin

    if(rst)

        radr_reg <= {WA{1'b0}};

    else if(ren)

        radr_reg <= radr_reg + 1'b1;

    end

/* ワード数のカウンタ */

always @(posedge clk or posedge rst)

    begin

    if(rst)

        count_reg <= {(WA+1){1'b0}};

    else

        case({wen,ren})

        2'b00: count_reg <= count_reg;

        2'b01: count_reg <= count_reg -1'b1;

        2'b10: count_reg <= count_reg +1'b1;

        2'b11: count_reg <= count_reg;

        default:count_reg <= {(WA+1){1'bx}};

        endcase

    end

endmodule


[] [] []