以前に多数のフリップフロップと加算器を用いて平均を計算する回路を設計しました。
今回は、少ない回路規模でほぼ平均の値を計算するフィルター回路を設計します。
回路でいうと最終課題のFMレシーバーの下記赤線で囲んだ部分に相当します。
ループフィルターは入力値に固定値α(=15/16=0.9375)を乗算したものを加算する回路になっています。したがって、c(t)がループフィルターに入力された時のループフィルターの出力は以下の式で与えられます。αは1以下の値なので、c(t)のこれまで平均のような演算です。ただし、古いデータほど影響力は小さくなります。
この回路では15/16の乗算が必要ですが、乗算は一般的に回路規模が大きいので、15/16 = 1 - 1/16 と考えて、16分の1すなわち、4ビット右シフト、と減算器で実現することができます。
ライブラリ宣言 | 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; |
ライブラリ宣言 | 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; |
今回は、前回の実習で使用した正弦波データが<8,0,t>フォーマットと仮定する。そうすると、前回の波形は-1から1の区間を振動する正弦波となる。この正弦波の平均値をループフィルターで平均化して滑らかな波形に変換する。
0) 作業ディレクトリに、上記3つのファイルをコピーする。
1) Sciroccoにて正常動作を確認せよ!
2) LOOPFのクロックピンを選択して、サイクルタイムのターゲットを 10 ns に設定する。
3) LOOPFを選択して、回路の合成を行う。
Tool -> Design Optimization
デフォルトの設定でOK
これで、以下のような回路が合成される。
4) TOPの回路の中にあるすべてのBOX(他の回路が違うレベルにある)を展開(同一レベルに)する。
BOXをクリックして選択、
edit -> ungroup
を用いて展開する。
これをすべてのBOXに対して行う。
以下のような回路が得られる。
5)回路のクリティカルパスを表示する
6)性能をレポートで確認する。
Analysis -> report で
area および timingをチェックしてApply
以上