/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2011, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
module fft (
iVld, iStall,
oVld, oStall,
mRdStrb, mRdAck, mRdData,
mWrStrb, mWrAck, mWrData,
reset, clk
);
// ************************* PARAMETER DECLARATIONS ****************************
// 最大のポイント数の指数はカウンタ等のビット範囲を定める
parameter MRR = 10; // Max Radix Radix
// 処理するポイント数は予め指定、可変にする場合はiVldと同期させる
parameter RADIX = 4'd10;
// *************************** I/O DECLARATIONS ********************************
// Pipe Input
input iVld;
output iStall;
// Pipe Output
output oVld;
input oStall;
// データは16ビットの半精度浮動小数点が8つ並ぶ(4x2ペア)
// Memory Interface (Read Data)
output mRdStrb;
input mRdAck;
input [127:0] mRdData;
// Memory Interface (Write Data)
output mWrStrb;
input mWrAck;
output [127:0] mWrData;
// Utility
input reset;
input clk;
// ************************** LOCAL DECLARATIONS *******************************
// ここから各ユニットの入出力信号を定義する
// Load Data
wire oLoadDataVld;
wire oLoadDataStall;
wire [1:0] oLoadDataFlip;
wire ldRam0WE, ldRam1WE, ldRam2WE, ldRam3WE;
wire [7:0] ldRam0WA, ldRam1WA, ldRam2WA, ldRam3WA;
wire [31:0] ldRam0WD, ldRam1WD, ldRam2WD, ldRam3WD;
// Butterfly Calc FIFO
wire iBFIFOVld;
wire iBFIFOStall;
wire oBFIFOVld;
wire oBFIFOStall;
// Butterfly Calc
wire iBfCalcVld;
wire iBfCalcStall;
wire oBfCalcVld;
wire oBfCalcStall;
wire [1:0] bcRamRF;
reg [1:0] bcRamRFB;
wire bcRamRP;
wire bcRam0RE, bcRam1RE, bcRam2RE, bcRam3RE;
wire [7:0] bcRam0RA, bcRam1RA, bcRam2RA, bcRam3RA;
wire [31:0] bcRam0RD, bcRam1RD, bcRam2RD, bcRam3RD;
wire bcRamWP;
wire [1:0] bcRamWF;
wire bcRam0WE, bcRam1WE, bcRam2WE, bcRam3WE;
wire [7:0] bcRam0WA, bcRam1WA, bcRam2WA, bcRam3WA;
wire [31:0] bcRam0WD, bcRam1WD, bcRam2WD, bcRam3WD;
// Coefficients of Fourier
wire [MRR-3:0] wIndex;
wire [2:0] wPhase;
wire [15:0] wRe0, wIm0, wRe1, wIm1, wRe2, wIm2, wRe3, wIm3;
// Store Data FIFO
wire iSdFIFOVld;
wire iSdFIFOStall;
wire oSdFIFOVld;
wire oSdFIFOStall;
// Store Data
wire iStoreDataVld;
wire iStoreDataStall;
wire [1:0] oStoreDataFlip;
reg [1:0] oStoreDataFlipB;
wire stRam0RE, stRam1RE, stRam2RE, stRam3RE;
wire [7:0] stRam0RA, stRam1RA, stRam2RA, stRam3RA;
wire [31:0] stRam0RD, stRam1RD, stRam2RD, stRam3RD;
// 8つ(4Bank x2セット)あるSRAM信号の入出力信号を定義する
// アドレスレンジは4Bankに分かれていることから2を引く
// データには実数と虚数のペアが入る
// SRAM Signals
wire ram0WE0, ram0WE1, ram1WE0, ram1WE1,
ram2WE0, ram2WE1, ram3WE0, ram3WE1;
wire [MRR-2:0] ram0WA0, ram0WA1, ram1WA0, ram1WA1,
ram2WA0, ram2WA1, ram3WA0, ram3WA1;
wire [31:0] ram0WD0, ram0WD1, ram1WD0, ram1WD1,
ram2WD0, ram2WD1, ram3WD0, ram3WD1;
wire ram0RE0, ram0RE1, ram1RE0, ram1RE1,
ram2RE0, ram2RE1, ram3RE0, ram3RE1;
wire [MRR-2:0] ram0RA0, ram0RA1, ram1RA0, ram1RA1,
ram2RA0, ram2RA1, ram3RA0, ram3RA1;
wire [31:0] ram0RD0, ram0RD1, ram1RD0, ram1RD1,
ram2RD0, ram2RD1, ram3RD0, ram3RD1;
// ****************************** MODULE BODY **********************************
// -----------------------------------------------------------------------------
// Load Data
// RADIXが可変なら、iVldに同期させる
// iStallはLoadDataの処理がほぼ終わるまでアサートするため、突き放したい場合は前段にFIFOを入れる
fftLoadData #(MRR) loadData_0 (
.iVld (iVld),
.iStall (iStall),
.iRadix (RADIX),
.oVld (oLoadDataVld),
.oStall (oLoadDataStall),
.oFlip (oLoadDataFlip), // SRAMダブルバッファ制御に使用
.mStrb (mRdStrb),
.mAck (mRdAck),
.mData (mRdData),
.ram0WE (ldRam0WE), // SRAMへのWrite信号グループ
.ram0WA (ldRam0WA),
.ram0WD (ldRam0WD),
.ram1WE (ldRam1WE),
.ram1WA (ldRam1WA),
.ram1WD (ldRam1WD),
.ram2WE (ldRam2WE),
.ram2WA (ldRam2WA),
.ram2WD (ldRam2WD),
.ram3WE (ldRam3WE),
.ram3WA (ldRam3WA),
.ram3WD (ldRam3WD),
.reset (reset),
.clk (clk)
);
assign oLoadDataStall = iBFIFOStall;
// -----------------------------------------------------------------------------
// Butterfly Calc FIFO
// LoadDataとBcCalcを繋ぐFIFO、データがないのでSignalingだけ
sig_2 sig_0 (
.iVld (iBFIFOVld),
.iStall (iBFIFOStall),
.oVld (oBFIFOVld),
.oStall (oBFIFOStall),
.reset (reset),
.clk (clk)
);
assign iBFIFOVld = oLoadDataVld;
assign oBFIFOStall = iBfCalcStall;
// -----------------------------------------------------------------------------
// Butterfly Calculation
// RADIXが可変なら、iVldに同期させる
// 逆変換が必要な場合もiVldに同期したフラグが必要
fftBfCalc #(MRR) bfCalc_0 (
.iVld (iBfCalcVld),
.iStall (iBfCalcStall),
.iRadix (RADIX),
.oVld (oBfCalcVld),
.oStall (oBfCalcStall),
.wIndex (wIndex), // 係数テーブルへのインターフェイス
.wPhase (wPhase),
.wRe0 (wRe0),
.wIm0 (wIm0),
.wRe1 (wRe1),
.wIm1 (wIm1),
.wRe2 (wRe2),
.wIm2 (wIm2),
.wRe3 (wRe3),
.wIm3 (wIm3),
.ramRF (bcRamRF), // SRAMダブルバッファ制御に使用(Read)
.ramRP (bcRamRP), // SRAM領域制御に使用(Read)
.ram0RE (bcRam0RE), // SRAMへのRead信号グループ
.ram0RA (bcRam0RA),
.ram0RD (bcRam0RD),
.ram1RE (bcRam1RE),
.ram1RA (bcRam1RA),
.ram1RD (bcRam1RD),
.ram2RE (bcRam2RE),
.ram2RA (bcRam2RA),
.ram2RD (bcRam2RD),
.ram3RE (bcRam3RE),
.ram3RA (bcRam3RA),
.ram3RD (bcRam3RD),
.ramWF (bcRamWF), // SRAMダブルバッファ制御に使用(Write)
.ramWP (bcRamWP), // SRAM領域制御に使用(Write)
.ram0WE (bcRam0WE), // SRAMへのWrite信号グループ
.ram0WA (bcRam0WA),
.ram0WD (bcRam0WD),
.ram1WE (bcRam1WE),
.ram1WA (bcRam1WA),
.ram1WD (bcRam1WD),
.ram2WE (bcRam2WE),
.ram2WA (bcRam2WA),
.ram2WD (bcRam2WD),
.ram3WE (bcRam3WE),
.ram3WA (bcRam3WA),
.ram3WD (bcRam3WD),
.reset (reset),
.clk (clk)
);
assign iBfCalcVld = oBFIFOVld;
assign oBfCalcStall = iSdFIFOStall;
// -----------------------------------------------------------------------------
// Coefficients of Fourier
// 係数テーブルモジュール、レイテンシ0のROMとして振る舞う
fftCoef #(MRR) coef_0 (
.wIndex (wIndex),
.wPhase (wPhase),
.wRe0 (wRe0),
.wIm0 (wIm0),
.wRe1 (wRe1),
.wIm1 (wIm1),
.wRe2 (wRe2),
.wIm2 (wIm2),
.wRe3 (wRe3),
.wIm3 (wIm3)
);
// -----------------------------------------------------------------------------
// Store Data FIFO
// BcCalcとStoreDataを繋ぐFIFO、データがないのでSignalingだけ
sig_2 sig_1 (
.iVld (iSdFIFOVld),
.iStall (iSdFIFOStall),
.oVld (oSdFIFOVld),
.oStall (oSdFIFOStall),
.reset (reset),
.clk (clk)
);
assign iSdFIFOVld = oBfCalcVld;
assign oSdFIFOStall = iStoreDataStall;
// -----------------------------------------------------------------------------
// Store Data
// RADIXが可変なら、iVldに同期させる
// oVldは最後のデータを出し切った時点でアサート
// アサート期間以外でoStallをアサートしてもパイプラインは止まらない
fftStoreData #(MRR) storeData_0 (
.iVld (iStoreDataVld),
.iStall (iStoreDataStall),
.iRadix (RADIX),
.oVld (oVld),
.oStall (oStall),
.oFlip (oStoreDataFlip), // SRAMダブルバッファ制御に使用
.mStrb (mWrStrb),
.mAck (mWrAck),
.mData (mWrData),
.ram0RE (stRam0RE), // SRAMへのRead信号グループ
.ram0RA (stRam0RA),
.ram0RD (stRam0RD),
.ram1RE (stRam1RE),
.ram1RA (stRam1RA),
.ram1RD (stRam1RD),
.ram2RE (stRam2RE),
.ram2RA (stRam2RA),
.ram2RD (stRam2RD),
.ram3RE (stRam3RE),
.ram3RA (stRam3RA),
.ram3RD (stRam3RD),
.reset (reset),
.clk (clk)
);
assign iStoreDataVld = oSdFIFOVld;
// -----------------------------------------------------------------------------
// SRAM Signals
// LoadData, BcCalcのSRAM Write信号をマージ
// oLoadDataFlipとbcRamWFは0か排他的な関係になっているため信号は重ならない
// また、それぞれのMSBとLSBも排他的になっており、同じユニットが2セット同時アクセスすることはない
assign {
ram0WE0, ram0WA0, ram0WD0,
ram1WE0, ram1WA0, ram1WD0,
ram2WE0, ram2WA0, ram2WD0,
ram3WE0, ram3WA0, ram3WD0
} = {4*(MRR+32){oLoadDataFlip[0]}} & {
ldRam0WE, 1'b0, ldRam0WA, ldRam0WD,
ldRam1WE, 1'b0, ldRam1WA, ldRam1WD,
ldRam2WE, 1'b0, ldRam2WA, ldRam2WD,
ldRam3WE, 1'b0, ldRam3WA, ldRam3WD
}
| {4*(MRR+32){bcRamWF[0]}} & {
bcRam0WE, bcRamWP, bcRam0WA, bcRam0WD,
bcRam1WE, bcRamWP, bcRam1WA, bcRam1WD,
bcRam2WE, bcRamWP, bcRam2WA, bcRam2WD,
bcRam3WE, bcRamWP, bcRam3WA, bcRam3WD
};
assign {
ram0WE1, ram0WA1, ram0WD1,
ram1WE1, ram1WA1, ram1WD1,
ram2WE1, ram2WA1, ram2WD1,
ram3WE1, ram3WA1, ram3WD1
} = {4*(MRR+32){oLoadDataFlip[1]}} & {
ldRam0WE, 1'b0, ldRam0WA, ldRam0WD,
ldRam1WE, 1'b0, ldRam1WA, ldRam1WD,
ldRam2WE, 1'b0, ldRam2WA, ldRam2WD,
ldRam3WE, 1'b0, ldRam3WA, ldRam3WD
}
| {4*(MRR+32){bcRamWF[1]}} & {
bcRam0WE, bcRamWP, bcRam0WA, bcRam0WD,
bcRam1WE, bcRamWP, bcRam1WA, bcRam1WD,
bcRam2WE, bcRamWP, bcRam2WA, bcRam2WD,
bcRam3WE, bcRamWP, bcRam3WA, bcRam3WD
};
// BcCalc, StoreDataのSRAM Read信号をマージ
// 仕組みは上記Writeと同じ
assign {
ram0RE0, ram0RA0,
ram1RE0, ram1RA0,
ram2RE0, ram2RA0,
ram3RE0, ram3RA0
} = {4*MRR{oStoreDataFlip[0]}} & {
stRam0RE, 1'b1, stRam0RA,
stRam1RE, 1'b1, stRam1RA,
stRam2RE, 1'b1, stRam2RA,
stRam3RE, 1'b1, stRam3RA
}
| {4*MRR{bcRamRF[0]}} & {
bcRam0RE, bcRamRP, bcRam0RA,
bcRam1RE, bcRamRP, bcRam1RA,
bcRam2RE, bcRamRP, bcRam2RA,
bcRam3RE, bcRamRP, bcRam3RA
};
assign {
ram0RE1, ram0RA1,
ram1RE1, ram1RA1,
ram2RE1, ram2RA1,
ram3RE1, ram3RA1
} = {4*MRR{oStoreDataFlip[1]}} & {
stRam0RE, 1'b1, stRam0RA,
stRam1RE, 1'b1, stRam1RA,
stRam2RE, 1'b1, stRam2RA,
stRam3RE, 1'b1, stRam3RA
}
| {4*MRR{bcRamRF[1]}} & {
bcRam0RE, bcRamRP, bcRam0RA,
bcRam1RE, bcRamRP, bcRam1RA,
bcRam2RE, bcRamRP, bcRam2RA,
bcRam3RE, bcRamRP, bcRam3RA
};
// Readデータを分配
assign {stRam0RD, stRam1RD, stRam2RD, stRam3RD}
= {128{oStoreDataFlipB[0]}} & {ram0RD0, ram1RD0, ram2RD0, ram3RD0}
| {128{oStoreDataFlipB[1]}} & {ram0RD1, ram1RD1, ram2RD1, ram3RD1};
assign {bcRam0RD, bcRam1RD, bcRam2RD, bcRam3RD}
= {128{bcRamRFB[0]}} & {ram0RD0, ram1RD0, ram2RD0, ram3RD0}
| {128{bcRamRFB[1]}} & {ram0RD1, ram1RD1, ram2RD1, ram3RD1};
// Readデータはアクセスに対し遅延するため、データ配分に関わるbcRamRFとoStoreDataFlipのラッチが必要
always @(posedge clk)
if (reset)
bcRamRFB <= #1 2'h0;
else if (|bcRamRF) // パイプラインStallを加味(bcRamRFにStallが織り込まれている)
bcRamRFB <= #1 bcRamRF;
always @(posedge clk)
if (reset)
oStoreDataFlipB <= #1 2'h0;
else if (|oStoreDataFlip)
oStoreDataFlipB <= #1 oStoreDataFlip;
// -----------------------------------------------------------------------------
// SRAM #0
dualSRAM #(32, MRR-1) ram_00 (
.WE (ram0WE0),
.WA (ram0WA0),
.WD (ram0WD0),
.RE (ram0RE0),
.RA (ram0RA0),
.RD (ram0RD0),
.CK (clk)
);
dualSRAM #(32, MRR-1) ram_01 (
.WE (ram0WE1),
.WA (ram0WA1),
.WD (ram0WD1),
.RE (ram0RE1),
.RA (ram0RA1),
.RD (ram0RD1),
.CK (clk)
);
// -----------------------------------------------------------------------------
// SRAM #1
dualSRAM #(32, MRR-1) ram_10 (
.WE (ram1WE0),
.WA (ram1WA0),
.WD (ram1WD0),
.RE (ram1RE0),
.RA (ram1RA0),
.RD (ram1RD0),
.CK (clk)
);
dualSRAM #(32, MRR-1) ram_11 (
.WE (ram1WE1),
.WA (ram1WA1),
.WD (ram1WD1),
.RE (ram1RE1),
.RA (ram1RA1),
.RD (ram1RD1),
.CK (clk)
);
// -----------------------------------------------------------------------------
// SRAM #2
dualSRAM #(32, MRR-1) ram_20 (
.WE (ram2WE0),
.WA (ram2WA0),
.WD (ram2WD0),
.RE (ram2RE0),
.RA (ram2RA0),
.RD (ram2RD0),
.CK (clk)
);
dualSRAM #(32, MRR-1) ram_21 (
.WE (ram2WE1),
.WA (ram2WA1),
.WD (ram2WD1),
.RE (ram2RE1),
.RA (ram2RA1),
.RD (ram2RD1),
.CK (clk)
);
// -----------------------------------------------------------------------------
// SRAM #3
dualSRAM #(32, MRR-1) ram_30 (
.WE (ram3WE0),
.WA (ram3WA0),
.WD (ram3WD0),
.RE (ram3RE0),
.RA (ram3RA0),
.RD (ram3RD0),
.CK (clk)
);
dualSRAM #(32, MRR-1) ram_31 (
.WE (ram3WE1),
.WA (ram3WA1),
.WD (ram3WD1),
.RE (ram3RE1),
.RA (ram3RA1),
.RD (ram3RD1),
.CK (clk)
);
// ************************** FUNCTIONS and TASKS ******************************
endmodule
// *****************************************************************************