テスト
- テスト方法としてノイズの入った入力データをCICフィルタでデシメートするとどうなるかを見てみます。入力データは分かりやすくするために周波数が低く振幅の大きい正弦波にノイズを加えたものとします。ノイズは周波数が高く振幅の小さい正弦波を加えることにします。また出力は入力に対して1/4にデシメートします。
- ノイズ分が除去された1/4のデータが出てきていれば良いことになります。
- テストモジュール
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
`timescale 1ps / 1ps
// ***************************** MODULE HEADER *********************************
module test;
// ************************ PARAMETER DECLARATIONS *****************************
parameter DCLK = 5000;
parameter DCLK2 = DCLK/2;
// タップ数=3 微分器遅延数=1 デシメーション=1/4
// TAP_NUM = 3 DELAY_NUM = 1 RE_SAMP = 4
// BIT_W = Data bit + TAP_NUM * log2(RE_SAMP * DELAY_NUM)
// = 8 + 3 * log2(4 * 1)
// = 8 + 3 * 2 = 8 + 6 = 14
parameter TAP_NUM = 3;
parameter DELAY_NUM = 1;
parameter BIT_W = 14;
// 入力するデータの数
parameter DATA_SIZE = 1000;
// ************************** LOCAL DECLARATIONS *******************************
reg reset_n;
reg reset;
reg [1:0] rst;
reg clk; // 積分器のクロック
reg oClk; // 微分器のクロック
wire [BIT_W-1:0] outData;
integer cnt;
reg [BIT_W-1:0] testData[0:DATA_SIZE-1]; // 入力データ
reg [BIT_W-1:0] noise[0:DATA_SIZE-1]; // 入力データに付加するノイズ
// ****************************** MODULE BODY **********************************
// -----------------------------------------------------------------------------
// ---------- Create Clock ------------
// 積分器のクロックを生成
initial begin
clk=1'b0;
forever begin
#(DCLK2) clk=~clk;
end
end
// 積分器のクロックを生成
initial begin
oClk = #(DCLK2)1'b0;
forever begin
#(DCLK*2) oClk=~oClk;
end
end
// ---------- Create Reset and Test Time ------------
// リセットの生成とテスト時間の設定
initial begin
reset_n=1'b0;
#(DCLK*2) reset_n=1'b1;
#(DCLK*500) $finish;
end
// ---------- Create TestData ------------
// 入力用のデータとそこに追加するノイズの生成
initial begin
integer init_cnt;
// init_cntに乗算する値で周波数を調整
// $sinは-1〜1なので+1してノイズを加算したときの値が8ビットに収まるようにしている
for(init_cnt=0 ; init_cnt < DATA_SIZE ; init_cnt=init_cnt+1)
testData[init_cnt] = ($sin(((init_cnt*10)%360)*3.1415 / 180)+1)*63;
for(init_cnt=0 ; init_cnt < DATA_SIZE ; init_cnt=init_cnt+1)
noise[init_cnt] = ($sin(((init_cnt*100)%360)*3.1415 / 180)+1)*63;
end
// 入力データの配列をカウントアップするカウンタ
always @(posedge clk or negedge reset_n)
if (!reset_n)
cnt = 0;
else
cnt = cnt+1;
// リセット信号よりモジュールに渡す同期リセット信号を生成
always @(posedge clk or negedge reset_n)
if (!reset_n)
rst <= #1 2'b11;
else
rst <= #1 {rst[0], 1'b0};
always @(posedge clk or negedge reset_n)
if (!reset_n)
reset <= #1 1'b1;
else
reset <= #1 rst[1];
// -----------------------------------------------------------------------------
// ---------- Target Module ------------
// 指定のパラメータ生成したトップモジュールにデータを入力
comCIC
#(TAP_NUM, DELAY_NUM, BIT_W)
cic(
.iData (testData[cnt]+noise[cnt]),
.oData (outData),
.reset (reset),
.clk (clk),
.oClk (oClk)
);
// ************************** FUNCTIONS and TASKS ******************************
endmodule
// *****************************************************************************
テスト結果
テスト結果の波形を以下にあげます。入力データにあるノイズが除去され1/4にデシメートされていることが分かります。
考察(CSAによる高速化)
- これまでのCICフィルタの説明ではタップ数を3として入力データのビット幅も8ビットとしました。しかしながら実際の使用にあたってはタップ数をもっと多く使用することや入力データのビット幅も多くしたいこともあると思われます。
例えばタップ数を5で微分回路の遅延を2、デシメートを1/8、入力ビット幅を16ビットとした場合には(参照:「CIC Filter Introduction」)
Out bits =N × log2(R × M) + In Bits
= 5 × log2(8 × 2) + 16
= 5 × 4 + 16
= 36
となり加算を積分器5タップと微分器5タップ分の10回の36ビット加算が必要となってしまいます。
- 通信などの高い周波数を扱う場合通常の加算では速度的に問題となってくることが考えられるため加算処理をCSAに置き換えることをしました。まず見やすいように2タップで入力が4ビットの積分器を以下に示します。
4ビット同士の加算がタップ数分行われています。次に加算の部分をCSAに置き換えたものを示します。
加算器がCSAに置き換わっているのが分かりますがCSAの内部を以下に示します。
加算が増えているように見えますが一つの加算は2ビットでCarryが全ての桁に伝播しないようになっていることが分かります。4ビットの例で効果が薄く感じられますが8ビットにした場合の以下の図と比べてください。
ビット数が増えても加算が2段で終わっていることが分かります。実際にCICフィルタを使用する場合にはタップ数も増え入力データのビット幅が大きくなると思われます。大きなビット幅で上位のビットへのCarryの伝播を伴う通常の加算処理に比べCSAによる効果は大きいと考えられます。
回路デザイン > 設計例 [CICフィルタ] > テスト このページのTOP ▲