Adder4 でインスタンス化された N 個の Adder1s を意図していた可能性に関する sharth の素晴らしい回答に敬意を表して:
ARCHITECTURE imp OF Adder4 IS
COMPONENT Adder1
PORT(
a, b, cIn : in STD_LOGIC;
sum, cOut : out STD_LOGIC);
END COMPONENT;
SIGNAL carry_sig: std_logic_vector(N-1 DOWNTO 0);
signal carry_in: std_logic_vector(N-1 DOWNTO 0);
BEGIN
-- What to write here?
carry_in <= ((carry_sig(N-2 downto 0)) &'0');
Adders:
for i in 0 to N-1 generate
begin
ADD1:
Adder1 port map (
a => a(i),
b => b(i),
cIn => carry_in(i),
sum => sum(i),
cOut => carry_sig(i)
);
end generate;
Carry_Out:
cOut <= carry_sig(N-1);
END imp;
ARCHITECTURE gen OF Adder4 IS
COMPONENT Adder1
PORT(
a, b, cIn : in STD_LOGIC;
sum, cOut : out STD_LOGIC);
END COMPONENT;
SIGNAL carry_sig: std_logic_vector(N-1 DOWNTO 0);
BEGIN
-- What to write here?
Adders:
for i in 0 to N-1 generate
ADD0:
if i = 0 generate
Add1:
Adder1 port map (
a => a(i),
b => b(i),
cIn => '0',
sum => sum(i),
cOut => carry_sig(i)
);
end generate;
ADDN:
if i /= 0 generate
Add1:
Adder1 port map (
a => a(i),
b => b(i),
cIn => carry_sig(i-1),
sum => sum(i),
cOut => carry_sig(i)
);
end generate;
end generate;
Carry_Out:
cOut <= carry_sig(N-1);
END architecture;
私自身は最初のアーキテクチャ (imp) を好みます。carry_in には 2 番目の std_logic_vector が必要ですが、生成構造が大幅に簡素化されます。両者には階層の違いがあり、最初の方が読みやすいです。
最初のアーキテクチャ (imp) は、Adder1 を手動で 4 回インスタンス化する方法も示しています。生成構造を削除し、すべての (i) 範囲式をそれぞれの Adder1 インスタンスの範囲式 ((0),(1),(2),(3) に置き換えます。 )、 それぞれ)。
手動でインスタンス化された adder1 は次のようになります。
-- Note in this case you'd likely declare all the std_logic_vector with
-- ranges (3 downto 0)
SIGNAL carry_sig: std_logic_vector(3 DOWNTO 0);
signal carry_in: std_logic_vector(3 downto 0);
BEGIN
-- What to write here?
carry_in <= ((carry_sig(2 downto 0)) &'0');
ADD0:
Adder1 port map (
a => a(0),
b => b(0),
cIn => carry_in(0),
sum => sum(0),
cOut => carry_sig(0)
);
...
ADD3:
Adder1 port map (
a => a(3),
b => b(3),
cIn => carry_in(3),
sum => sum(3),
cOut => carry_sig(3)
);
cOut <= carry_sig(3); -- or connect directly to cOut in ADD3 above
最下位の「0」のキャリ_インで上向きに調整されたキャリ_sig を使用する追加のキャリ_イン ベクトルにより、書き込みが簡単になります。また、キャリー イン信号とキャリー アウト信号に別々の名前を付けると、キャリー ルック アヘッド メソッドを実装した方が読みやすくなります。
テスト ベンチは幅 N Adder4 にも対応できます。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder4_tb is
constant N: natural := 4;
end entity;
architecture tb of adder4_tb is
signal a,b,sum: std_logic_vector (N-1 downto 0);
signal carryout: std_logic;
begin
DUT: entity work.Adder4
generic map (N => N) -- associates formal N with actual N (a constant)
port map (
a => a,
b => b,
sum => sum,
cOut => carryout
);
STIMULUS:
process
variable i,j: integer;
begin
for i in 0 to N*N-1 loop
for j in 0 to N*N-1 loop
a <= std_logic_vector(to_unsigned(i,N));
b <= std_logic_vector(to_unsigned(j,N));
wait for 10 ns; -- so we can view waveform display
end loop;
end loop;
wait; -- end the simulation
end process;
end architecture;
これらすべては、実装または高速キャリー回路 (例: キャリー先読み) の使用によって影響を受ける可能性があるキャリー ツリーの遅延時間とは関係ありません。
これにより、次のようなシミュレーションが得られます。
または、詳しく見るには:
生成ステートメント ベースのアーキテクチャを使用する場合、N の宣言を変更すると、リップル キャリーが入力データ レート (現在テストベンチ)。
テストベンチで宣言された実際の N とジェネリック N フォーマルのジェネリック マップの関連付けは、この場合、テストベンチで宣言された N が Adder4 の幅 N も設定することを意味することに注意してください。