SRAMを使用したFIFO
// -----------------------------------------------------------------------------
// Data FIFO
dualSRAM #(W, DR) sram_0 (
.WE (iAlloc),
.WA (iPtr[DR-1:0]),
.WD (iData),
.RE (!oStall),
.RA (oPtr[DR-1:0]),
.RD (oData),
.CK (clk)
);
記述を見て分かるように、データの出力遅延はSRAM[2]に依存してしまってることが分かります。単純にFFで受けるには、例えば深さ2の従来のFIFOを外部に設置することで一応解決します。
しかしながら、見かけ上のレイテンシが1から2に増えます。こうなると、他の部分との整合性が取れない場合が出てきます。ここでは、従来のレイテンシでSRAMを用いながら、データをFF出力するFIFOを示します。
先行したデータ取得
- 問題はデータをSRAMに格納してから取り出そうとすると、どうしてもSRAMに依存した遅延特性が表に出てしまうことです。そこで、SRAMからデータを取り出す場合にポインタ1つ先行させてFF受けすることを考えます。ただし、入出力ポインタが同一になる場合が生じます。SRAMによってはこれを禁止しているためさらに工夫が必要です。
- ここで、入力データ、入力データをFF受けしたもの、1つ進んだポインタで示されるSRAM出力の3つを用意し、必要に応じて使い分けることを考えます。3つのデータから1つを選択してFF受けするものとします。
- 選択の条件を考えると、FIFOが空の場合は入力データ、ポインタが衝突しなかった場合はSRAM出力、衝突した場合はFF受けした入力データが適することになります。
コード(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,
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 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;
reg [W-1:0] lData;
reg ramHD;
// SRAMポートを定義、SRAMをモジュール外に置く場合は外部ポートに変更
wire ramWE;
wire [DR-1:0] ramWA;
wire [W-1:0] ramWD;
wire ramRE;
wire [DR-1:0] ramRA;
wire [W-1:0] ramRD;
wire iAlloc = iVld & !iStall;
wire oAlloc = oVld & !oStall;
// ****************************** MODULE BODY **********************************
// -----------------------------------------------------------------------------
// Data FIFO
// FIFOが空の場合は入力データが直接、そうでない場合はポインタの衝突信号を見てラッチ
always @(posedge clk)
if (iAlloc & (iPtr[DR-1:0] == oPtrD[DR-1:0]))
oData <= #1 iData;
else if (!oStall)
oData <= #1 ramHD ? ramRD : lData;
// 入力データを一旦FF受け(衝突時のみ)
always @(posedge clk)
if (!ramRE)
lData <= #1 iData;
// ポインタの非衝突を保持
always @(posedge clk)
if (reset)
ramHD <= #1 1'b0;
else
ramHD <= #1 ramRE;
assign ramWE = iAlloc;
assign ramWA = iPtr[DR-1:0];
assign ramWD = iData;
// Read Enableが非衝突を示し、衝突時はReadをしない
// 衝突はFIFOが空の場合にしか発生しないので、SRAMに格納しなくても取りこぼしはない
assign ramRE = !ramWE | (ramWA != ramRA);
// ポインタを1つ先行してReadする
assign ramRA = oPtrD[DR-1:0] + 1'b1;
// 2ポートSRAMをコール、モジュール名は説明のため簡単化
dualSRAM #(W, DR) sram_0 (
.WE (ramWE),
.WA (ramWA),
.WD (ramWD),
.RE (ramRE),
.RA (ramRA),
.RD (ramRD),
.CK (clk)
);
// -----------------------------------------------------------------------------
// 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;
// ************************** FUNCTIONS and TASKS ******************************
endmodule
// *****************************************************************************
回路デザイン > 設計例 [FIFO] > >SRAMを使用したFIFO 次のページ(非同期FIFO) このページのTOP ▲