ループフィルター


以前に多数のフリップフロップと加算器を用いて平均を計算する回路を設計しました。

今回は、少ない回路規模でほぼ平均の値を計算するフィルター回路を設計します。

回路でいうと最終課題のFMレシーバーの下記赤線で囲んだ部分に相当します。

ループフィルターは入力値に固定値α(=15/16=0.9375)を乗算したものを加算する回路になっています。したがって、c(t)がループフィルターに入力された時のループフィルターの出力は以下の式で与えられます。αは1以下の値なので、c(t)のこれまで平均のような演算です。ただし、古いデータほど影響力は小さくなります。

この回路では15/16の乗算が必要ですが、乗算は一般的に回路規模が大きいので、15/16 = 1 - 1/16 と考えて、16分の1すなわち、4ビット右シフト、と減算器で実現することができます。


ループフィルターのVHDL記述

リスト loopf.vhd

テストベンチ test_loopf.vhd

入力信号 fm.txt

ライブラリ宣言 library IEEE; 
use IEEE.STD_LOGIC_1164.all; 
use IEEE.STD_LOGIC_ARITH.all;
エンティティ宣言 entity LOOPF is 
  port ( 
  CLK : in std_logic; 
  RESET : in std_logic; 
  SIN : in std_logic_vector(7 downto 0); -- <8,0,t> 
  SOUT : out std_logic_vector(11 downto 0) ); -- <12,4,t> 
end LOOPF;
アーキテクチャ宣言 architecture RTL of LOOPF is 
 signal sum : std_logic_vector(11 downto 0); -- <12,4,t> 
 signal dff : std_logic_vector(11 downto 0); -- <12,4,t> 
 signal shift : std_logic_vector(11 downto 0); -- <12,4,t> 
 signal sub : std_logic_vector(11 downto 0); -- <12,4,t> 
begin 

-- ADDER sum <= signed(sub)+signed(SIN(7)&SIN(7)&SIN(7)&SIN(7)&SIN); 

-- DFF 
process(CLK, RESET) begin 
 if(RESET = '1') then dff <= "000000000000"; 
 elsif(CLK'event and CLK = '1') then 
  dff <= sum; 
 end if; 
end process; 

-- 4 bit shifter 
shift <= dff(11)&dff(11)&dff(11)&dff(11)&dff(11 downto 4); 

-- SUBTRACTER 
sub <= signed(dff) - signed(shift); 

-- OUTPUT 
SOUT <= dff; end RTL;

 


テストベンチのVHDL記述

ライブラリ宣言 library STD, IEEE; 
use STD.TEXTIO.all; 
use IEEE.std_logic_1164.all; 
use IEEE.std_logic_arith.all; 
use IEEE.std_logic_textio.all;
エンティティ宣言 entity TESTBENCH_LOOPF is 
end TESTBENCH_LOOPF;
アーキテクチャ宣言 architecture SIM_DATA of TESTBENCH_LOOPF is 

component LOOPF is port ( 
 CLK : in std_logic; 
 RESET : in std_logic; 
 SIN : in std_logic_vector(7 downto 0); -- <8,0,t> 
 SOUT : out std_logic_vector(11 downto 0) ); -- <12,4,t> 
end component; 

signal FMINPUT : std_logic_vector(7 downto 0); -- <8,0,t> 
signal LOOPOUT : std_logic_vector(11 downto 0);-- <12,4,t> 
signal CLK : std_logic := '1'; 
signal RESET : std_logic := '1'; 

signal FMINPUT_REAL : real; 
signal LOOPOUT_REAL : real; 

begin 

-- CLOCK GENERATION 
CLK <= not CLK after 5 ns; 

-- RESET release 
P1: process begin 
 RESET <= '1'; 
 wait for 20 ns; 
 RESET <= '0'; 
 wait; 
end process; 

-- TEST VECTOR 
P2: process 
file TEST_IN : text is in "fm.txt"; 
variable LINE_IN : line; 
variable V_FMINPUT : std_logic_vector(7 downto 0); 
begin 
readline(TEST_IN, LINE_IN); 
read(LINE_IN, V_FMINPUT); 
FMINPUT <= V_FMINPUT; 
wait for 10 ns; 
if endfile(TEST_IN) then wait; 
end if; 
end process; 

-- DUT 
U1: LOOPF port map (CLK, RESET, FMINPUT, LOOPOUT); 

-- MONITOR F
MINPUT_REAL <= real(CONV_INTEGER(signed(FMINPUT))) /128.0; 
LOOPOUT_REAL <= real(CONV_INTEGER(signed(LOOPOUT))) /128.0; 

end SIM_DATA; 

configuration CFG_LOOPF of TESTBENCH_LOOPF is 
 for SIM_DATA 
 end for; 
end CFG_LOOPF;

 


実習7 ループフィルターの動作シミュレーション(1)

今回は、前回の実習で使用した正弦波データが<8,0,t>フォーマットと仮定する。そうすると、前回の波形は-1から1の区間を振動する正弦波となる。この正弦波の平均値をループフィルターで平均化して滑らかな波形に変換する。

リスト loopf.vhd

テストベンチ test_loopf.vhd

入力信号 fm.txt

0) 作業ディレクトリに、上記3つのファイルをコピーする。

1) Sciroccoにて正常動作を確認せよ!


実習5(2)

2) LOOPFのクロックピンを選択して、サイクルタイムのターゲットを 10 ns に設定する。

3) LOOPFを選択して、回路の合成を行う。

Tool -> Design Optimization

デフォルトの設定でOK

これで、以下のような回路が合成される。

4) TOPの回路の中にあるすべてのBOX(他の回路が違うレベルにある)を展開(同一レベルに)する。

BOXをクリックして選択、

edit -> ungroup

を用いて展開する。

これをすべてのBOXに対して行う。

以下のような回路が得られる。

5)回路のクリティカルパスを表示する

6)性能をレポートで確認する。

Analysis -> report で

area および timingをチェックしてApply

 


以上