CLKがHighの時に、入力Dは出力Qへインバータ2段で接続され、
CLKがLowの時に、インバータ2段がリング接続になり、値を保持する。
シンボル | 名称 | 意味 |
tC | サイクルタイム | 動作する周期、スペックでは最小値が規定される。 |
tS | セットアップタイム | クロックエッジに対するデータを用意する時間、スペックでは最小値が規定される。 |
tH | ホールドタイム | クロックエッジに対してデータを保持する時間、スペックでは最小値が規定される。 |
tKQ | アクセスタイム | クロックエッジからデータ出力までの時間、スペックでは最大値が規定される。 |
以下のように3つ(もしくは3人)の計算機があったとする。
3人はそれぞれ計算の仕事を同時に行う。例えば、計算1は加算、計算2は掛算、計算3は割算である。
この3人が計算結果をグルグル回すことで、1つの大きな仕事ができるとする。
この場合以下のようなことがおきる
1) 計算1は5nsごとに計算結果を計算2に渡そうとするが、計算2は10nsごとにしか仕事もらえない。
2) 計算1は計算2が空いたことを教えてもらってから、計算2へ仕事を渡す。
3) 同様に計算2も計算3が空いたことを知らされて、計算3へ結果を渡し、その後計算1へ自分が空いたことを伝える。
4) 要するに、隣接ユニット間で知らせ合い(ユニット間の通信)を行う必要がある。
同期回路では、このユニットごとの通信を不要にするために、ユニット間にフリップフロップを入れて、同一のクロック信号で同期させる。
1) クロックの立ち上がりエッジで、セイノで、(同時に)各ユニットへ入力データが入力される。
2) その後、計算1は7ns
(CLK立ち上がりエッジからFFの出力までの遅延を2nsとする)で計算が終わるが
3) 次の入力を得るまで、20nsぐらいの間そのまま待たされる。
4) 一番遅い計算3も22ns
後には計算を終える。
5) そして、25ns
後のクロックの立ち上がりエッジで各FFは前のユニットの結果を次のユニットへ伝える。
FFの働きは、各ユニットばらばらの計算時間をクロックにより遅らせて、計算時間をそろえている。
理想的には、最も低速な計算3の計算時間20nsのサイクル時間が使えそうであるが、実際にはFFのセットアップタイムとアクセスタイムの分だけサイクル時間を延ばす必要がある。
一見、同期回路は効率が悪そうであるが、最大のメリットは非同期回路のユニット間の通信が不要になることにある。
非同期の場合でも、計算のスループットは結局最も遅い計算3で決まり、それに、ユニット間通信の遅延が加算される。ユニット間通信の遅延がFFのセットアップ+アクセス時間以上なら、同期の方が性能はよくなる。
1)3人の学生A,B,Cさんはそれぞれ以下の仕事をするとする
A: 紙に書かれた数字を見て、その数字に1を加えたもの計算し、紙に答えを書く
B: 紙に書かれた数字を見て、その数字を2倍したもの計算し、紙に答えを書く
C: 紙に書かれた数字を見て、その数字を5倍し、それから3を引き算したもの計算し、紙に答えを書く
最初、Aさん、Bさん、Cさんにそれぞれ、「1」、「2」、「3」と書かれた紙を渡す。
そして、A,B,Cさんはすぐに自分の仕事をする。
先生の「ハイ!」という合図で、AさんはBさんに紙を渡し、BさんはCさんに紙を渡し、CさんはAさんに紙を渡すとする。
先生が「ハイ!」と5回言った後に、Aさん、Bさん、Cさんの紙の数字はそれぞれ幾らか?
2) 以下の波形をそれぞれ、DラッチとDフリップフロップに入力した時の波形を描け
ライブラリ宣言 | library IEEE; use IEEE.std_logic_1164.all; |
いつもどおり |
エンティティ宣言 | entity PET_D_FF is port( CK, D : in std_logic; Q : out std_logic ); end PET_D_FF; |
クロック入力:CK データ入力:D データ出力:Q |
アーキテクチャ宣言 | architecture BEHAVIOR of PET_D_FF
is begin process ( CK ) begin if ( CK'event and CK = '1' ) then Q <= D; end if; end process; end BEHAVIOR; |
1) 記述は出力信号Qの動作を記述すればよい
2) FFの出力QはクロックのLow->High変化時のみ変化するので、 2-1)
センシティビティリストにCKのみを入れる。 2-2) if文でクロックのLow->High変化に限定 |
process文の中で、wait文やif文でエッジを検出する記述を行えば、FFが生成される。
エッジ検出記述 教科書のP111 コラム8参照のこと
Clock'event and Clock= '1' | 'eventアトリビュートを用いた立ち上りエッジの検出 |
Clock'event and Clock= '0' | 'eventアトリビュートを用いた立ち下りエッジの検出 |
not Clock'stable and Clock = '1' | 'stableアトリビュートを用いた立ち上りエッジの検出 |
not Clock'stable and Clock = '0' | 'stableアトリビュートを用いた立ち下りエッジの検出 |
rising_edge(Clock) | ファンクションコールを用いた立ち上りエッジの検出 |
falling_edge(Clock) | ファンクションコールを用いた立ち下がりエッジの検出 |
関数rising_edge, falling_edgeは'X'から'1'への変化を検知しない。
P1: process (Clock)
begin
if ( Clock'event
and Clock= '1') then
Y1 <= A1;
end if;
if ( Clock'event and Clock= '1') then
Y2
<= A2;
end if;
end process P1;
立ち上りエッジのDFF、if文は繰り返し書けるで複数のFFを生成できる。
P2: process
begin
wait until (Clock'event and
Clock= '1');
Y3 <= A3;
end process P2;
wait文はそこでブロックして止まるので、複数のwait文を一つのprocess文に書けない。
P3: process (Clock)
begin
if
rising_edge(Clock) then
Y4 <= A4;
end if;
end process
P3;
if文中でrising_edge関数を用いた場合。記述がコンパクトでGOOD!
P4: process
begin
wait until
rising_edge(Clock);
Y5 <= A5;
end process P4:
wait文に関数rising_edgeを用いた記述。
process文を用いて、組み合わせ回路を記述する場合、その組み合わせ回路の全ての入力信号をセンシティビティ・リストに記述すればよかった・一方、process文を用いてフリップフロップや順序回路を記述する場合には、センシティビティ・リストに記述する信号を選択する必要がある。
ライブラリ宣言 | library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; |
今回は入力信号として、2の補数表現を用いた正・負混合の信号を用いるので、P63コラム4の算術演算用パー-ケージで説明されているように、std_logic_arithを用いる。 |
エンティティ宣言 | entity AVG4 is port(CLK : in std_logic; FMINPUT : in std_logic_vector(7 downto 0); AVGOUT : out std_logic_vector(7 downto 0)); end AVG4; |
クロック入力:CLK データ入力:FMINPUT(8ビット) データ出力:AVGOUT(8ビット) |
アーキテクチャ宣言 | architecture RTL of AVG4 is signal FF1, FF2, FF3, FF4 : std_logic_vector(7 downto 0); signal SUM : std_logic_vector(9 downto 0); begin |
4つのFF出力を定義
加算した信号を定義 |
-- SHIFT REGISTER process(CLK) begin if (CLK'event and CLK = '1') then FF1 <= FMINPUT; FF2 <= FF1; FF3 <= FF2; FF4 <= FF3; end if; end process; |
このような記述で4つのFFが生成される。
FF1 :=FMINPUT; とすると、 FF4 :=FMINPUT; と等価となり、FFは1個しか生成されない。 |
|
-- SUM SUM <= signed(FF1(7)&FF1(7)&FF1) +signed(FF2(7)&FF2(7)&FF2) +signed(FF3(7)&FF3(7)&FF3) +signed(FF4(7)&FF4(7)&FF4); |
std_logic_arithを用いているので、P63コラム4の算術演算用パー-ケージで説明されているように、signedで型変換を行っている。
8ビットを10ビットに拡張する時に、”00”を前につけると、全て正の数になってしまうので、MSBを2ビットコピーしている。 |
|
-- DIVIDE BY 4 (SHIFT 2 bit), OUTPUT
REGISTER process(CLK) begin if (CLK'event and CLK='1') then AVGOUT <= SUM(9 downto 2); end if; end process; end RTL; |
出力のレジスタを記述している。
4の割り算を2ビット右シフトで実現している。 ここでは、四捨五入は用いず、切り捨てしている。 |
ライブラリ宣言 | library STD, IEEE; use STD.TEXTIO.all; use IEEE.std_logic_1164.all; use IEEE.std_logic_textio.all; |
教科書P85にTEXTIOパッケージの説明がある。
今回、テスト入力として他のテキストファイルに書かれた値を用いるので、ライブラリSTDを指定し、パッケージTEXTIOを呼び出している。 |
エンティティ宣言 | entity TESTBENCH_FF1 is end TESTBENCH_FF1; |
テストベンチであるので、中味は空である。 |
アーキテクチャ宣言 | architecture SIM_DATA of
TESTBENCH_FF1 is component AVG4 port(CLK : in std_logic; FMINPUT : in std_logic_vector(7 downto 0); AVGOUT : out std_logic_vector(7 downto 0)); end component; signal FMINPUT : std_logic_vector(7 downto 0); signal AVGOUT : std_logic_vector(7 downto 0); signal CLK : std_logic := '0'; begin |
今回テストされるAVG4回路(移動平均回路)をコンポーネント(部品)宣言している。
その他用いる信号を宣言している。 |
-- Sysetem CLK generation CLK <= not CLK after 5 ns; |
システムクロックを発生している。
5nsごとに変化するので、クロック周期は10nsである。 CLKの初期値はsignal宣言のところで、定義されている。 |
|
-- DUT U1: AVG4 port map (CLK, FMINPUT, AVGOUT); |
テストされる回路AVG4を置いている。 | |
-- TEST VECTOR P1: 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; end SIM_DATA; |
詳しくは、P85ページの説明とP87ページのリスト4.14を参考にしてください。
fm.txt の値を読み込んで、10nsすなわち、毎サイクルごとに値をFMINPUT信号に代入している。 if文は終了条件。 |
|
configuration CFG_FF1 of
TESTBENCH_FF1 is for SIM_DATA end for; end CFG_FF1; |
VHDLではひとつのエンティティに複数のアーキテクチャを 持たせることができるので、その割り当ての宣言。 必ず最上位階層に記述する必要がある。 |
0) 作業ディレクトリに、上記3つのファイルをコピーする。
1) Sciroccoにて正常動作を確認せよ!
2) クロック信号とその周期を指定する。
クロック入力端子をダブルクリックで選択し、
Attributes -> Clock -> Specify
Periodの欄に数値(たとえば50)を入力し、Apply
この数値がサイクルタイムの合成時の目標値になるので、面積重視で、サイクルタイムが長くてよい場合は大きな値を入れる。
逆に、サイクルタイムを小さくしたければ、小さな値をいれる。
3) 回路の合成を行う。
Tool -> Design Optimization
デフォルトの設定でOK
これで、以下のような回路が合成される。
4) TOPの回路の中にあるすべてのBOX(他の回路が違うレベルにある)を展開(同一レベルに)する。
BOXをクリックして選択、
edit -> ungroup
を用いて展開する。
これをすべてのBOXに対して行う。
以下のような回路が得られる。
5)回路のクリティカルパスを表示する
が正常動作する条件である。
6)性能をレポートで確認する。
Analysis -> report で
area および timingをチェックしてApply
全体として、
が成立する必要性を
で上記リストはチェックしている。
tC:サイクルタイムで CLK と示されている
tS:フリップフロップのセットアップタイムで リストでは -tSを library setup time としている。
上記リストでは
として、これが正であれば条件を満たしているので、 MET(満たした)という表示になっている。
上記リストでは、50−40.8=9.2ns となる。
7) クロックの周期のターゲット値を1として、再合成する。(なるべく、最小サイクル時間の小さい回路を合成せよ)
8) この時の最小の動作サイクル時間はいくらか?
9) 回路を改造して、16ポイントの平均を計算する回路を設計せよ。
以下のものを提出すること。
以上