Применение параметров при структурном описании проекта.

Представим, что у нас имеются следующая задача: Описать структурным стилем представленную на рисунке схему.

Тогда получается, что каждый логический элемент представляет собой отдельный процесс. Для решения данной задачи в лоб надо просто описать все уникальные элементы схемы, а у нас их получается три — 2-х входовых элементов И-НЕ и один 3-х входовой элемент И-НЕ. Описание их будет выглядеть следующим образом:
entity I_NE2 is 
  port( x0,x1 : in bit;
        y : out bit);
      end I_NE2;
      
architecture A_I_NE2 of I_NE2 is
  begin
   Y <= x0 nand x1;
  end A_I_NE2;

entity I_NE3 is
  port( x0,x1,x2 : in bit;
        y : out bit);
      end I_NE3;
      
architecture A_I_NE3 of I_NE3 is
  begin
   Y <= not (x0 and x1 and x2);
  end A_I_NE3;

Как видно, наше устройство имеет 4 входных порта и один выходной. Напишем программу описывающую структуру нашего устройства.
entity Sys is
  port( x : in bit_vector(3 downto 0);
        y : out bit);
      end Sys;
      
architecture A_Sys of Sys is

component I_NE2 is 
  port( x0,x1 : in bit;
        y : out bit);
      end component I_NE2;
      
  component I_NE3 is
  port( x0,x1,x2 : in bit;
        y : out bit);
      end component I_NE3;
      
  signal temp : bit_vector(2 downto 0); -- требуется для переноса сигнала от первых трех элементов к последнему 3-х входовому    
      
begin
  
  DD1: I_NE2 port map(x(0),x(1),temp(0));
  DD2: I_NE2 port map(x(2),x(3),temp(1));
  DD3: I_NE2 port map(x(0),x(3),temp(2));
  DD4: I_NE3 port map(temp(0),temp(1),temp(2),y);
  
end A_Sys;


Как то так будет выглядеть описание нашей системы структурным стилем. Строки кода не поясняю, так как уже много статей по VHDL, если будет не понятно допишу пояснения.

Посмотрим как можно при помощи параметров унифицировать написание такой программы, делается это при помощи ключевого слова generic.
Напишем универсальный элемент И-НЕ, его код будет выглядеть следующим образом:
entity I_NE is
  generic(W : natural := 2);
  port( X : in bit_vector(W downto 1);
        y : out bit);
      end I_NE;

architecture A_I_NE of I_NE is
begin
I_ne: process(X)
variable T : bit;
begin
  T := '1';
  F : for i in X'range 
    loop
    T := T and X(i);
  end loop;
  Y <= not T;
end process;
end A_I_NE;


Теперь опишем систему показанную на рисунке, состоящую из таких элементов:
entity Sys is
  port( x : in bit_vector(3 downto 0);
        y : out bit);
      end Sys;

architecture A_Sys of Sys is
component I_NE is
  generic(W : natural := 2);
  port( X : in bit_vector(W downto 1);
        y : out bit);
      end component I_NE;
signal temp : bit_vector(2 downto 0);
signal temp2 : bit_vector(1 downto 0);

begin
DD1 : I_NE generic map(2)
            port map(x(1 downto 0),temp(0));
DD2 : I_NE generic map(2)
            port map(x(3 downto 2),temp(1));
temp2 <= x(3) & x(0);
DD3 : I_NE generic map(2)
            port map(temp2,temp(2));
DD4 : I_NE generic map(3)
            port map(temp,y);
end A_Sys;


Получается так, единственное не знаю как красивей сделать в DD3, пришлось делать через дополнительный сигнал, может кто знает, подскажите.

Решил показать как решить тот же пример с использованием процедур, немного не в тему но по-моему интересно:

entity Sys is
  port( x : in bit_vector(3 downto 0);
        y : out bit);
      end Sys;
      
architecture A_Sys of Sys is
procedure I_NE( signal X : in bit_vector;
                signal Y : out bit) is
variable T : bit;
begin
  T := '1';
  F : for i in X'range 
    loop
    T := T and X(i);
  end loop;
  Y <= not T;
end I_NE;

signal temp : bit_vector(2 downto 0);
signal temp2 : bit_vector(1 downto 0);

begin
I_NE(x(1 downto 0),temp(0));
I_NE(x(3 downto 2),temp(1));
temp2 <= x(3) & x(0);
I_NE(temp2,temp(2));
I_NE(temp,y);
  
end A_Sys;


  • +4
  • 14 марта 2011, 15:36
  • opolo84

Комментарии (4)

RSS свернуть / развернуть
а у нас их получается два — 2-х входовой элемент И-НЕ
их три
0
спасибо, поправил.
0
лучше пользоваться только std_logic вместо bit. Почему так, написано уже много где.

дело каждого конечно, но я предпочитаю всегда придерживаться нумерации массива downto 0:
port( X: in bit_vector(W-1 downto 0);

когда проект побольше, легко сделать ошибку.

в этой статье простой пример, однако константа настраивающая generic может быть вычисляемой из другой константы через функцию, это очень удобно допустим для log2.

в общем случае я бы не одобрял использование процедур в синтезируемых схемах, не всегда очевидно какую схему сделает синтезатор, да и критический путь оптимизировать сложнее.
0
Нумерация downto 1 сделана для того, чтобы в скобках константа указывала количество входных портов, а не на единицу меньше, как раз это наоборот позволяет не запутаться. А так вообще имхо без разницы до 0 или до 1, главное везде придерживаться одного стиля и не делать кашу.
Не вижу проблем с процедурами, все операторы, что мы используем из пакетов есть функции. Какая разница, напишу я кусок кода или запихну его в процедуру и буду использовать ее. Например, когда у нас читал лекцию профессор из IBM, он везде использовал процедуры без какого либо напряга.
Если можете приведите программку с процедурой и просто с кодом, интересно посмотреть результаты синтеза для повышения грамотности :)
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.