Jump to content
    

Странные вопросы по VHDL

Вы самообучались на деньги работодателя на рабочем месте, почти наверняка. А работодатель наверняка в явную на это не соглашался )))

Соглашался, участвовал, и был заинтересован. Никто не хочет менять работников раз в год и заново объяснять им чем занимается фирма. Так что держат морально устаревших пока они хоть как-то тянут. А если везет так что работник развивается и остается современным - то это бонус за который все цепляются.

 

Но не переживайте, развивающихся процентов 30 всего, 70% - стандартный вариант, сидят, стареют, цепляются за прошлое, брюзжат... В советское время посылали на курсы переподготовки, и доводили цифру прогрессивных до 40%, сейчас нет. Может быть в большинстве и не плохо... удачи вам.

Share this post


Link to post
Share on other sites

Ладно, невозможность ссылки дженериков друг на друга будет ещё одним гвоздём в крышке гроба VHDL

Как же дженерик может вычисляться из другого дженерика, когда дженерики задаются при вставке компонента? Если представить такую ситуацию, что есть два дженерика: a и b, и b = a * 2, то что делать если при вставке компонента мы железно определили a = 3, b = 7? Выстрел в ногу получается.

 

И да, можно сделать так:

 

entity cm_add_m is generic (
    BW_IN : natural; -- разрядность
    SUB : natural;  -- если 1, то вычитание, если 0 - то сложение
    WRAP_PROD_BITS : natural; -- число старших откидываемых битов от внутреннего произведения
    RND_PROD_BITS : natural; -- число округляемых битов от внутреннего произведения
    PP_INT : natural   -- внутренние пайплайны, между каждыми DSP-блоками
); port (
    clk : in std_logic; -- Клок работы модуля
    -- Входные данные
    add1, add2 : in std_logic_vector(BW_IN-1 downto 0);
    mult : in std_logic_vector(BW_IN-1 downto 0);
    -- Выходные данные
    p: out std_logic_vector(BW_IN * 2 - RND_PROD_BITS - WRAP_PROD_BITS-1 downto 0)
); end cm_add_m;

Edited by Amurak

Share this post


Link to post
Share on other sites

Если дженерик соотвествует ширине какого-нибудь порта, то такой дженерик вообще не нужен, достаточно сделать этот порт unconstrained, и узнавать его фактическую размерность через стандартные атрибуты. В этом VHDL даже удобнее Верилога.

не понял, можно простой пример с портом unconstrained?

пример с генерик:

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

use ieee.std_logic_unsigned.all;

 

entity ADDER is

 

generic(n: natural :=2);

port(

A: in std_logic_vector(n-1 downto 0);

B: in std_logic_vector(n-1 downto 0);

sum: out std_logic_vector(n-1 downto 0);

carry: out std_logic );

 

end ADDER;

 

architecture behv of ADDER is

 

signal result: std_logic_vector(n downto 0);

 

begin

 

result <= ('0' & A)+('0' & B);

sum <= result(n-1 downto 0);

carry <= result(n);

 

end behv;

 

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

Share this post


Link to post
Share on other sites

не понял, можно простой пример с портом unconstrained?

вот для примера с генерик:

ЕМНИП std_logic_vector не ограниченный тип, ограничиваете вы его в момент задания размеров. В итоге будет что-то вроде этого :

entity ADDER is
port(    
    A:    in std_logic_vector;
    B:    in std_logic_vector;
    sum:    out std_logic_vector;
    carry:    out std_logic    );

end ADDER;

architecture behv of ADDER is

signal result: std_logic_vector(A'high+1 downto A'low);

begin                      
       
    result <= ('0' & A)+('0' & B);
    sum <= result(sum'range);
    carry <= result(result'high);

end behv;

 

Ну и естественно модули подобного типа не могут быть top ами, только подмодулями по очевидным причинам.

Share this post


Link to post
Share on other sites

ЕМНИП std_logic_vector не ограниченный тип, ограничиваете вы его в момент задания размеров. В итоге будет что-то вроде этого :

entity ADDER is
port(    
    A:    in std_logic_vector;
    B:    in std_logic_vector;
    sum:    out std_logic_vector;
    carry:    out std_logic    );

end ADDER;

architecture behv of ADDER is

signal result: std_logic_vector(A'high+1 downto A'low);

begin                      
       
    result <= ('0' & A)+('0' & B);
    sum <= result(sum'range);
    carry <= result(result'high);

end behv;

 

Ну и естественно модули подобного типа не могут быть top ами, только подмодулями по очевидным причинам.

понял, спасибо

 

Share this post


Link to post
Share on other sites

Соглашался, участвовал, и был заинтересован.
Вам повезло с работодателем, это прогрессивный, продвинутый работодатель. А другой работодатель скажет: "Кааааааааааак? Обучаться да ещё и за мои деееньги? А в это время проекты будут стоять? Не умеешь - понизим зп на время обучения. Либо найдём кто умеет". Некоторым нужен сразу готовый специалист, чтобы он всё знал и умел.

 

Никто не хочет менять работников раз в год и заново объяснять им чем занимается фирма
А вот у нас в Томске в некоторых предприятиях меняют работников... город студенческих, демпинг, студенты-конкуренты вытесняют )))

 

Соглашался, участвовал, и был заинтересован. Никто не хочет менять работников раз в год и заново объяснять им чем занимается фирма. Так что держат морально устаревших пока они хоть как-то тянут. А если везет так что работник развивается и остается современным - то это бонус за который все цепляются.
Даже если пожилой в годах специалист является продвинутым, прошаренным и находится на пике современных тенденций, всё равно к нему отношение со стороны работодателя уже настороженное... увы. И работу уже в годах побаиваются менять, даже если много что из себя представляют, ибо априорное недоверие типа старпёр, и всё ))

 

Как же дженерик может вычисляться из другого дженерика, когда дженерики задаются при вставке компонента? Если представить такую ситуацию, что есть два дженерика: a и b, и b = a * 2, то что делать если при вставке компонента мы железно определили a = 3, b = 7? Выстрел в ногу получается.
Ну в верилоге же можно. Принцип как и при любых последовательных присвоениях переменных в любых языках программирования: если выше переменная уже определена, она может быть подставлена при вычислении результата ниже. И да, самое главное: не забывайте, что мы говорим о параметрах по умолчанию, т.е. когда они не заданы в вышестоящем модуле. Если они заданы - то и формулы не действуют, значения заменяются на те, которые напрямую заданы в вышестоящем модуле.

 

И да, можно сделать так:

p: out std_logic_vector(BW_IN * 2 - RND_PROD_BITS - WRAP_PROD_BITS-1 downto 0)

Да, я уже тоже так попробовал - но это не чисто, т.к. может быть неудобно при длинных формулах, можно запутаться. Чтобы не запутаться, желательно разбить на несколько промежуточных переменных. А VHDL это не даёт...

 

 

 

Если дженерик соотвествует ширине какого-нибудь порта, то такой дженерик вообще не нужен, достаточно сделать этот порт unconstrained, и узнавать его фактическую размерность через стандартные атрибуты. В этом VHDL даже удобнее Верилога.
Спасибо, вот это пожалуй самое полноценное решение моей проблемы. В виду новичковости в VHDL я просто об этом не знал, что можно сделать unconstrained ))) Тогда определяю эти параметры

    WRAP_PROD_BITS : natural; -- число старших откидываемых битов от внутреннего произведения
    RND_PROD_BITS : natural; -- число округляемых битов от внутреннего произведения
    BW_PROD : natural := BW_IN * 2 - RND_PROD_BITS; --  разрядность внутреннего произведения
    BW_OUT : natural := BW_PROD - WRAP_PROD_BITS; --  разрядность выхода общей части

как константы в вышестоящем модуле, они, естественно, имеют право рассчитываться по формулам.

Всё, пожалуй, мой вопрос закрыт и решён.

Гвоздик в крышку гроба пока придётся приберечь... )))

Share this post


Link to post
Share on other sites

Созрел ещё вопросик как претендент на гвоздика в крышку гроба VHDL ))

Есть линия задержки:

    del_lat_i : delay generic map (
        DATA_BW => BW_P,
        DEL => DUT_LAT
    ) port map (
        clk => clk,       -- clock
        -- Входные данные
        data_in => p_mat_i,
        -- Выходные данные
        data_out => p_mat_d_i
    );

 

Есть сигналы входа и выхода этой линии задержки:

    signal y1_mat_i, y1_mat_d_i,
           y1_mat_q, y1_mat_d_q  : std_logic_vector(EXT_DATA_BW-5 downto 0);
           
    signal y2_mat_i, y2_mat_d_i,
           y2_mat_q, y2_mat_d_q : std_logic_vector(EXT_DATA_BW-1 downto 0);

При том для общности случая ширина шин разная.

 

Я бы хотел использовать один компонент линии задержки для задержки сразу всех сигналов, чтобы не нагромождать исходник.

В верилоге я бы сделал примерно так (ниже будет симбиоз верилога и VHDL):

    del_lat_i : delay generic map (
        DATA_BW => BW_P,
        DEL => DUT_LAT
    ) port map (
        clk => clk,       -- clock
        -- Входные данные
        data_in => {y1_mat_i,
                    y1_mat_q,
                    y2_mat_i,
                    y2_mat_q},
        -- Выходные данные
        data_out => {y1_mat_d_i,
                     y1_mat_d_q,
                     y2_mat_d_i,
                     y2_mat_d_q}
    );

Фишка в том, что очень удобно не оперировать разрядностями отдельных шин при стыковке и расстыковке входа и выхода линии задержки. Как сделать нечто подобное на VHDL? Я знаю, что вход можно собрать в одну шину через значок &. Т.е. объявить общий сигнал входа, ему присвоить конкатенацию всех составляющих сигналов. Нет проблем. Проблема, как потом разобрать выходную шину на отдельные составляющие?

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

Share this post


Link to post
Share on other sites

Фишка в том, что очень удобно не оперировать разрядностями отдельных шин при стыковке и расстыковке входа и выхода линии задержки. Как сделать нечто подобное на VHDL? Я знаю, что вход можно собрать в одну шину через значок &. Т.е. объявить общий сигнал входа, ему присвоить конкатенацию всех составляющих сигналов. Нет проблем. Проблема, как потом разобрать выходную шину на отдельные составляющие?

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

В VHDL 2008 можно легко разобрать сигнал на части, примерно как в Верилоге, с помощью агрегата. Однако это нельзя сделать прямо в порт мэппинге, требуется использовать промежуточный сигнал.

Разработчики стандарта явно не знакомы с принципом бритвы Оккама.

 

Share this post


Link to post
Share on other sites

Спасибо. А если у меня VHDL 2002, то получается никак?..

Мысль возникла: а не получится ли так сделать через процедуры? Написать процедуру, в которую подставить исходную широкую шину и затем её составляющие, а процедура заполнит составляющие в порядке их перечисления в качестве аргументов процедуры.

Я понимаю, что при заранее известном количестве аргументов это вполне возможно. Но возможно ли это для заранее неизвестного количества аргументов? Было бы довольно-таки красиво.

 

...Ещё как вариант - написать их штук 10 для количества аргументов в диапазоне 1..10 ))) И пусть перезагружается, какая процедура нужна в данном случае. Смущает только, что все 10 раз нужно будет прикладывать мозги и вручную описывать разбор по индексам. Лучше конечно, чтобы по предыдущему варианту, для заранее неизвестного числа аргументов. Если это возможно.

 

... А ещё если возможно как идея: такую же процедуру навроде

  function "-"(L : UNRESOLVED_SIGNED; R : STD_ULOGIC) return UNRESOLVED_SIGNED;

, т.е. когда аргументы перечисляются не в скобках, а слева и справа от значка. Но приведённый выше пример - это функция. Можно ли так для процедур? Если так можно, тоже было бы красиво. Например, называем процедуру ":" и записываем:

delay_out : y1_mat_d_i : y1_mat_d_q : y2_mat_d_i : y2_mat_d_q;

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

Либо это должна быть не процедура, а функция. Но тогда другой вопрос: умеет ли функция менять один из аргументов (чтобы он был inout как бы).

Share this post


Link to post
Share on other sites

Созрел ещё вопросик как претендент на гвоздика в крышку гроба VHDL ))

Зачем изучать то что не нравиться?

и постоянно "ругаться" что оно плохое...

Пишите на том языке, который Вам нравиться!

Зачем постоянно об этом писать??? Не понимаю...

Share this post


Link to post
Share on other sites

кто платит, тот и заказывает музыку. Так что пишу, на том, что используется на предприятии

Share this post


Link to post
Share on other sites

кто платит, тот и заказывает музыку. Так что пишу, на том, что используется на предприятии

случайно не ЛЭМЗ ?

Share this post


Link to post
Share on other sites

Спасибо. А если у меня VHDL 2002, то получается никак?..

Мысль возникла: а не получится ли так сделать через процедуры? Написать процедуру, в которую подставить исходную широкую шину и затем её составляющие, а процедура заполнит составляющие в порядке их перечисления в качестве аргументов процедуры.

Я понимаю, что при заранее известном количестве аргументов это вполне возможно. Но возможно ли это для заранее неизвестного количества аргументов? Было бы довольно-таки красиво.

 

...Ещё как вариант - написать их штук 10 для количества аргументов в диапазоне 1..10 ))) И пусть перезагружается, какая процедура нужна в данном случае. Смущает только, что все 10 раз нужно будет прикладывать мозги и вручную описывать разбор по индексам. Лучше конечно, чтобы по предыдущему варианту, для заранее неизвестного числа аргументов. Если это возможно.

Такая идея у меня тоже была, но реально разбивку приходится делать не так часто, чтобы писать для этого кучу процедур. Причём для out сигналов и переменных нужны отдельные процедуры:). И для всех возможных сочетаний сигналов и переменных :biggrin: .

Для автоматической разбивки я использую многократный вызов процедуры с передвижением индекса:

    procedure get_bits_s(signal v:out std_logic_vector;s:std_logic_vector;i:inout integer) is
    begin
        v <= s(i+v'length-1 downto i);
        i := i+v'length;
    end procedure;
...
    i := 0;
    get_bits_s(strobe_out, s, i);
    get_bits_s(addsub_sel, s, i);
    get_bits_s(const_adr, s, i);
    get_bits_s(regs_wa, s, i);
    get_bits_s(regs_ra, s, i);

В функциях использовать out параметры, к сожалению, нельзя, а то можно было бы лучше сделать.

Share this post


Link to post
Share on other sites

Спасибо за конкретное решение. Пожалуй приму себе на вооружение как единственный рабочий вариант, если не в лоб.

разбивку приходится делать не так часто, чтобы писать для этого кучу процедур
У меня прям часто. Я просто обожал на верилоге так задерживать кучу сигналов одним разом. Очень экономит время и строчки кода (читай наглядность).

 

 

Причём для out сигналов и переменных нужны отдельные процедуры:)
Что Вы имеете в виду?

И для всех возможных сочетаний сигналов и переменных
Ну тут написать штук 10. Ну 20. Т.е. для диапазона 2..20. "Всех возможных" - это Вы запугиваете ))) Тип сигнала один и тот же, разное только число аргументов процедуры, обработка одинакова.

А это идея. Пишем десяток однотипных функций, в которой полностью повторяем Ваш код с той разницей, что меняется число аргументов и с каждым новым аргументом добавляется один лишний вызов Вашей процедуры.

Щас попробую.

 

В функциях использовать out параметры, к сожалению, нельзя, а то можно было бы лучше сделать.
А можно делать процедуры не для аргументов в скобках, а как будто для математических операций, типа а + в? Или так только функции можно?

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...