Threshold対応FIFO
- ビデオ入力・出力を例にします。これらは必要分量を必ず時間内に送受信する必要があります[1]。FIFOは、画像が保持してあるSDRAMなどの主記憶装置と入出力デバイスとを繋ぎ、タイミングを吸収します。
- デバイス側に繋がるFIFOの制御信号は基本的に不必要です。カメラからはFullであってもデータを受けざるを得ず、表示デバイスへはBusyでなくてもデータを出力せざるを得ないからです。ここでは、この不都合な事象はないものとします(対症法はFIFO自体の構成に関係ないので言及しない)。
- 一方SDRAMはバースト転送しないと性能が発揮できません。しかも、データ要求からリターンまでのレイテンシが存在するため、先行的に要求する必要もあります。FIFOの制御信号はワード単位(デバイスの送受信単位)なので、SDRAMの制御にはそのまま使用できません。バースト単位の制御信号が必要になります。
- 上記をまとめると、次の要件が満たされる必要があります。
- 転送量に関してデバイスは一定レート、SDRAMはシステム状況によってゆらぎ、タイミング変動をFIFOで吸収する必要がある
- デバイスの転送が滞らないようなFIFO容量にしなければならない
- SDRAMのバースト転送と先行要求を可能にするため、その分のFIFOに空き領域を確保しておかなければならない
- グラフにしてみると対策を考えるのに分かりやすいと思います。図は表示デバイスに対するFIFOのデータ保持量の時間変化(ブルー)です。赤矢印の始端はFIFO保持量を見て少なければSDRAMにデータ要求するタイミングで、矢印の先端はデータがFIFOに充填するタイミングです(ワードごとに充填しますが、スケール的には一挙に充填しているよう見えます)。
- ここからブルーの点線のように0点を越えるアンダーフローを起こさせないためには、SDRAMの最悪時のレイテンシ期間、デバイスにデータを供給できる分のFIFO保持量を確保しておくことです。従って最悪時のレイテンシが見積もれればFIFO全体容量も見積もれます。
- さて、肝心の制御の方は従来のFIFOとは異なった方式が必要です。デバイス側は上述したように制御不要なので、SDRAM側の制御がポイントになります。ところで、SDRAMもハンドシェークできないデバイスと同じですが、デバイスが1フレーム単位の制御なのに対しSDRAMはバースト単位の制御なので、バーストを単位としたFIFO制御を行えば従来のFull, Empty制御が使えます。
- しかし実際はそれだけでは駄目で、SDRAMへデータ要求をかけてデータが返ってくるまでのレイテンシ期間もデータ要求を行い、パイプライン実行させる必要があります。レイテンシ単位でGo/Stop制御すると、上図のようにオーバーラップ制御できず性能がでないことは明白です。ただし、SDRAMそのものはハンドシェークできないデバイスなので、要求分のデータを受け取るのに「待った」はできません。これはデータパイプラインにStallを発生させてはいけないことを示します。従って、FIFOにはデータ要求分の空きを確保しておく必要があります。
- これらを総合すると、SDRAMのレイテンシの最悪値分のデータを貯め、バーストx先行要求分のデータの空きを確保する[2]ことが必要になります。即ち、FIFOには蓄積量と空きの量を同時に満足するThresholdを定めることができ(静的もしくは動的に)、FIFOポインタとの比較で別途制御信号を生成することが要求されます。
- 一般的なFIFOにThresholdを追加します。汎用的にするため、Thresholdは外部からパラメータとして与えるものとします。また、入力数と出力数の差がThresholdを越えたことを示すTrigger信号をポートに加えます。
- コードは差分のみ解説を加えています。基本的に、ポインタの比較に"="ではなく">"か"<"を用いるだけです(当然、回路規模は増えます)。
コード(RTL)
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2011, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
module fifo (
iVld,
iStall,
iData,
oVld,
oStall,
oData,
thresh, // Threshold, Trigger信号はいずれの側にも使用可能
trig, // 複数必要な場合はセットで追加する
reset,
clk
);
// ************************ PARAMETER DECLARATIONS *****************************
parameter W = 32; // Data Length
parameter DR = 2; // Depth Radix
parameter D = 1<<DR;
// *************************** I/O DECLARATIONS ********************************
input iVld;
output iStall;
input [W-1:0] iData;
output oVld;
input oStall;
output [W-1:0] oData;
input [DR-1:0] thresh;
output trig;
input reset;
input clk;
// ************************** LOCAL DECLARATIONS *******************************
reg iStall;
wire iStallD;
reg oVld;
wire oVldD;
reg [DR:0] iPtr;
wire [DR:0] iPtrD;
reg [DR:0] oPtr;
wire [DR:0] oPtrD;
reg [W-1:0] oData;
wire [DR:0] diffD;
wire trigD;
reg trig;
wire iAlloc = iVld & !iStall;
wire oAlloc = oVld & !oStall;
reg [W-1:0] mem[0:D-1];
// ****************************** MODULE BODY **********************************
// -----------------------------------------------------------------------------
// Data FIFO
always @(posedge clk)
if (iAlloc & (iPtr[DR-1:0] == oPtrD[DR-1:0]))
oData <= #1 iData;
else if (!oStall)
oData <= #1 mem[oPtrD[DR-1:0]];
always @(posedge clk)
if (iAlloc)
mem[iPtr[DR-1:0]]
<= #1 iData;
// -----------------------------------------------------------------------------
// Data FIFO Pointer
always @(posedge clk)
if (reset) begin
iStall <= #1 1'b0;
oVld <= #1 1'b0;
end
else begin
iStall <= #1 iStallD;
oVld <= #1 oVldD;
end
always @(posedge clk)
if (reset) begin
iPtr <= #1 {DR+1{1'b0}};
oPtr <= #1 {DR+1{1'b0}};
end
else begin
iPtr <= #1 iPtrD;
oPtr <= #1 oPtrD;
end
assign iStallD = (iPtrD[DR] != oPtrD[DR])
& (iPtrD[DR-1:0] == oPtrD[DR-1:0]);
assign oVldD = (iPtrD != oPtrD);
assign iPtrD = iPtr + iAlloc;
assign oPtrD = oPtr + oAlloc;
// -----------------------------------------------------------------------------
// Threshold Control
always @(posedge clk)
if (reset)
trig <= #1 1'b0;
else
trig <= #1 trigD;
// 入出力ポインタの差分を計算、周期を示すMSBも保存
assign diffD = (iPtrD - oPtrD);
// ポインタの差分がThresholdを超えるとTrigger信号を出すようにする
// 説明分と整合させると、Triggerが'0'でSDRAMの連続アクセス
// Thresholdを動的に変化させる場合、Triggerは次のタイミングで反映することに注意
assign trigD = (diffD > {1'b0, thresh});
// ************************** FUNCTIONS and TASKS ******************************
endmodule
// *****************************************************************************
回路デザイン > 設計例 [FIFO] > Threshold対応FIFO 次のページ(SRAMを使用したFIFO) このページのTOP ▲