7 Параллельный оператор generate
Общий вид оператора generate(генерации):
метка : forпараметр генерации generate|
ifусловие generateпараллельные операторы endgenerate[метка];
Рассмотрим работу оператора на примерах сдвигового регистра и 7-разрядного сумматора, схема которого размещена ниже:
Параметр генерации - константа дискретного типа в определенном диапазоне. Параметром генерации не может быть декларированная переменная или сигнал.
Оператор генерации позволяет сокращенно (по существу используя цикл) описывать совокупности повторяющихся операторов, в том числе и операторов конкретизации компонентов, т. е. оператор генерации представляет собой механизм для проектирования (описания) регулярных (систолических) структур.
Например, структура регистра регулярна. Мы можем создать N экземпляров компонента DFF (D-триггера) и сделать N-битный сдвиговый регистр. Когда число N большое, значительно возрастает длина VHDL-кода. Оператор генерации представляет собой механизм для проектирования (описания) регулярных (систолических) структур.
Следующий пример показывает применение оператора генерации к описанию 8-битового сдвигового регистра.
entity SHIFT is
port (
RSTn, CLK, SI : in bit;
SO : out bit);
end SHIFT;
architecture RTL2 of SHIFT is
component DFF
port (
RSTn, CLK, D : in bit;
Q : out bit);
end component;
signal T : bit_vector(6 downto 0);
begin
g0 : for i in 7 downto 0 generate
g1 : if (i = 7) generate
bit7 : DFF
port map (RSTn => RSTn, CLK => CLK, D => SI, Q
=> T(6));
end generate;
g2 : if (i > 0) and (i < 7) generate
bitm : DFF
port map (RSTn, CLK, T(i), T(i-1));
end generate;
g3 : if (i = 0) generate
bit0 : DFF
port map (RSTn, CLK, T(0), SO);
end generate;
end generate;
end RTL2;
Проанализировав данное описание, можно заметить, что некоторое "неудобство", связанное с установлением связей схемы в целом с полюсами элементов, возникает при описании входного (метка bit7) и выходного триггера (метка bit0). Избежать этого неудобства можно, если увеличить размерность сигнала Т.
architecture RTL3 of SHIFT is
component DFF
port (
RSTn, CLK, D : in bit;
Q : out bit);
end component;
signal T : bit_vector(8 downto 0); -- декларация сигнала T
begin
T(8) <= SI;
SO <= T(0);
g0 : for i in 7 downto 0 generate
allbit : DFF
port map (RSTn => RSTn, CLK => CLK, D => T(i+1), Q
=> T(i));
end generate;
end RTL3;
Имеются два способа употребления оператора генерации.
Способ 1 - (способ for), синтаксис такой же, как у последовательного оператора forloop.
Способ 2 - (способ if) употребление подобно по синтаксису последовательному оператору if.
В архитектуре RTL2 способ ifупотреблен внутри способа for.
Укажем различия параллельного оператора генерации от последовательных операторов for, if.
1. Оператор генерации есть параллельный оператор, a if, for loopесть последовательные операторы.
2. Оператор генерации не имеет фраз else, elsif.
3. Необходима метка для оператора генерации.
4. Только параллельные операторы могут появляться внутри оператора генерации. Только последовательные операторы могут появляться внутри последовательного forloopоператора и последовательного ifоператора.
Архитектура DFF может быть декларирована в пакете и употреблена в архитектурах RTL1, RTL2, RTL3. Затем эта компонента может быть удалена из этих архитектур.
В архитектуре RTL3 параметр iне нуждается в декларации. Все три архитектуры RTL1, RTL2, RTL3 описывают то же самое поведение.
В следующем примере VHDL-кода оператор generate употребляется для спецификации N-разрядного сумматора adder_N.
entity adder_N is
generic (N : natural := 4);
port (a,b : in bit_vector (0 to N-1);
s : out bit_vector (0 to N-1);
c : out bit);
end adder_N;
architecture functional of adder_N is
component add1
port (b1,b2: in BIT;
c1,s1: out BIT);
end component;
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c_in : bit_vector (0 to N-1);
begin
adder: for i in 0 to N-1 generate
first_bit: if (i=0) generate
first_cell:
add1 port map (b1 => a(0), b2 => b(0), c1 => c_in(0), s1 => s(0) );
end generate first_bit;
middle_bit: if (i>0) and (i < N-1) generate
middle_cell:
add2 port map (c1 => c_in(i-1), a1 => a(i), a2 => b(i), c2 => c_in(i), s2 => s(i) );
end generate middle_bit;
end_bit: if (i=N-1) generate
end_cell:
add2 port map (c1 => c_in(i-1), a1 => a(i), a2 => b(i), c2 => c, s2 => s(i) );
end generate end_bit;
end generate adder;
end functional;
Изменяя число N в строке с ключевым словом generic, можно получать описание сумматора требуемой разрядности. В представленном ниже архитектурном теле func_l для N-разрядного сумматора используется только подсхема одноразрядного сумматора add2, при этом на вход переноса cl подсхемы add2 (в разряде с номером 0) подается нулевой сигнал, описание становится более компактным.
entity adder_N is
generic (N : natural := 4);
port (a,b : in bit_vector (0 to N-1);
s : out bit_vector (0 to N-1);
c : out bit);
end adder_N;
architecture func_1 of adder_N is
component add2
port(c1, a1,a2:in BIT;
c2,s2:out BIT);
end component;
signal c_in : bit_vector (0 to N);
begin -- в схеме все одноразрядные сумматоры - add2
c_in(0)<='0';
adder: for i in 0 to N-1 generate
i_bit_slice: add2 port map (c1 => c_in(i), a1 => a(i), a2 => b(i),
c2 => c_in(i+1), s2 => s(i) );
end generate adder;
c <= c_in(N);
end func_1;
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.