同期FIFOの作り方
非同期FIFOを作る準備として、ライトとリードが同じクロックで動く同期FIFOを作る。
◇
FPGAにはデュアルポートメモリ(DPM)が備わっているので、ライトとリードを2ポートに割り当てて、1ワードをライト/リードする毎にライト/リードアドレス(wadr/radr)をカウントアップすればよい。さらに、リード側から見てデータかあるのか、ライト側から見て書き込む余地があるのかがわかるように、FIFOに溜まっているワード数を数えるカウンタを設ければよい。このとき、ライトとリードが同時に起きた場合を抜かさないことと、FIFOが満杯(full)になったときのためカウンタはアドレスより1ビット大きくしておくことに注意。
◇◇
同期FIFOのRTL記述は次のようになる。
/* 同期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 |