同期FIFOの作り方

[] [] []


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

FPGAにはデュアルポートメモリ(DPM)が備わっているので、ライトとリードを2ポートに割り当てて1ワードをライト/リードする毎にライト/リードアドレス(wadr/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 // counter

  );

reg[WA-1:0] wadr;

reg[WA-1:0] radr;

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

/* DPM */

always @(posedge clk) begin

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

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

end

/* write address */

always @(posedge clk or posedge rst) begin

  if(rst)

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

  else if(wen)

    wadr <= wadr + 1'b1;

end

/* read address */

always @(posedge clk or posedge rst) begin

  if(rst)

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

  else if(ren)

    radr <= radr + 1'b1;

end

/* word count */

always @(posedge clk or posedge rst) begin

  if(rst)

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

  else

    case({wen,ren})

    2'b00: count <= count;

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

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

    2'b11: count <= count;

    endcase

end

endmodule


[] [] []