Jump to content

    

Вопрос начинающего (VHDL)

type ac_array is array (0 to (slide_len - 1)) of std_logic_vector(9 downto 0);
signal	A_ac_buff : ac_array;	
attribute ram_style of A_ac_buff : signal is "bram";
---------------------------------
COMPONENT SR1024
PORT    (
    d    : IN  STD_LOGIC;
    clk    : IN  STD_LOGIC;
    ce    : IN  STD_LOGIC;
    q     : OUT STD_LOGIC
    );END COMPONENT;
-----------------------------------
begin
SR1024_0    : SR1024 PORT MAP (d => sr1k_0_in, clk => clk50, ce => sr1k_0_en, q => sr1k_0_out);
SR1024_1    : SR1024 PORT MAP (d => sr1k_1_in, clk => clk50, ce => sr1k_1_en, q => sr1k_1_out);
-----------------------------------

process(clk50)
begin
    if rising_edge(clk50) then

        if(...) then

                sampl_cntr <= 0;
                AQ1_cntr <= 0;
                AQ2_cntr <= 0;
                SHIFT_cntr <= 0;
                nestd_SH_cntr <= 0;
                nestd_SH2_cntr <= 0; end if

        if(sampl_cntr /= sampl) then
            A_buff(sampl_cntr) <= DA;
            sampl_cntr <= sampl_cntr + 1;
        elsif((sampl_cntr=sampl) AND (SHIFT_cntr /= slide_len)) then
            if(nestd_SH_cntr /= slide_len) then
                
                if((sr1k_0_out xor sr1k_1_out) = '1') then    ACC0 <= ACC0 + 1; end if;
                
                nestd_SH_cntr <= nestd_SH_cntr + 1;

            elsif((nestd_SH_cntr = slide_len) AND (nestd_SH2_cntr /= 1)) then -- здесь +1 такт для дополнительного сдвига (не описано)
                buff_10bit_std <= conv_std_logic_vector(ACC0,16)(11 downto 2);
                nestd_SH2_cntr <= nestd_SH2_cntr + 1;
            elsif((nestd_SH_cntr = slide_len) AND (nestd_SH2_cntr = 1)) then
                nestd_SH_cntr <= 0;
                nestd_SH2_cntr <= 0;
                ACC0 <= 0;
                SHIFT_cntr <= SHIFT_cntr + 1;
            end if;

            A_ac_buff(SHIFT_cntr) <= buff_10bit_std;   --conv_std_logic_vector(SHIFT_cntr,16)(9 downto 0);--   ВОТ ЗДЕСЬ!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        elsif(...)then
            divider <= divider + 1;
            if(...) then
                
                if(...) then Tx_data_int <= A_ac_buff(...);
                end if;
            end if;
        end if;

    end if;

end process;

 

Прошу прощения за длинные имена.

Почему синтезатор "внешний" счетчик (SHIFT_cntr) писать в память A_ac_buff() позволяет а buff_10bit_std - нет?

Не  позволяет - это значит синтезирует бесконечно.

sr1k_0_out и sr1k_1_out - выходы сдвиговых регистров.

Длина сдвиговых регистров не влияет на собираемость проекта.

Может быть что-то не так с моим сдвиговым?

 

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SR1024 is
--------------------------------------------------------------------------
generic ( n  : integer := 1024 );
port    (
        d      :        in  std_logic;
        clk    :        in  std_logic;
        ce     :        in     std_logic;
        q       :        out std_logic);
end SR1024;
architecture Behavioral of SR1024 is
signal tmp: std_logic_vector(n-1 downto 0) := (Others => '0');

begin
process (clk)
begin
    if (clk'event and clk = '1') then
        if (ce = '1') then
                tmp(0) <= d;
                for idx in 1 to n-1 loop tmp(idx) <= tmp(idx-1); end loop;
        end if;
    end if;
end process;

q <= tmp(n-1);

end Behavioral;

Share this post


Link to post
Share on other sites

Добрый день.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity top is
generic ( n  : integer := 1024 );
port    (
        d      :        in  std_logic;
        clk    :        in  std_logic;
        ce     :        in     std_logic;
        q       :        out std_logic);
end top;

architecture Behavioral of top is
signal tmp: std_logic_vector(n-1 downto 0) := (Others => '0');

begin
process (clk)
begin
    if (clk'event and clk = '1') then
        if (ce = '1') then

----------------------------------------------------------------------------------------------------------------

-- Вместо
----------------------------------------------------------------------------------------------------------------
--          tmp(0) <= d;
--          for idx in 1 to n-1 loop tmp(idx) <= tmp(idx-1); end loop;
----------------------------------------------------------------------------------------------------------------

-- вот это
----------------------------------------------------------------------------------------------------------------
             tmp      <= tmp(n-2 downto 0) & d;     
----------------------------------------------------------------------------------------------------------------
        end if;
    end if;
end process;

q <= tmp(n-1);

end Behavioral;

Удачи.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Я как-бы начинающий. И не очень понимаю что значит разбить на счетчики и автомат. Сигналы SHIFT_cntr, nestd_SH_cntr и nestd_SH2_cntr - это разве не счетчики?

Share this post


Link to post
Share on other sites
1 hour ago, nameless said:

разбить на счетчики и автомат

Это значит сделать, грубо говоря, в одном процессе описание поведения только одного сигнала (если есть очень схожие сигналы по поведению, то их можно добавить в этот процесс). В результате должно получится несколько процессов с 1-2мя условиями if-else не более. Иначе синтезатор может сойти с ума, а в ISE вообще могут вылезти "волшебные" приколы.

Sample_proc: process(clk50)
begin
	if rising_edge(clk50) then

		if reset = '1' then
			sampl_cntr <= 0;
		end if;

		if(sampl_cntr /= sampl) then
			sampl_cntr <= sampl_cntr + 1;
		end if;
	end if;
end process Sample_proc'

Nested_counter: process(clk50)
begin
	if rising_edge(clk50) then
		if reset = '1' then
			nestd_SH_cntr <= 0;
		end if;

		if(sampl_cntr=sampl) AND (SHIFT_cntr /= slide_len) AND (nestd_SH_cntr /= slide_len) then
			nestd_SH_cntr <= nestd_SH_cntr + 1;
		end if;
	end if;
end process Nested_counter;

// и так далее. Это просто пример, логика может быть не соблюдена.

Кстати, после "end if" нужно ставить точку с запятой. Возможно это Вы так вырезали непонятно кусками, а возможно и в коде ошибки (почему желательно приводить или полный исходный код или пример с аналогичной проблемой, но орбязательно ПОЛНОСТЬЮ).

Share this post


Link to post
Share on other sites
2 часа назад, Nick_K сказал:

Это значит сделать, грубо говоря, в одном процессе описание поведения только одного сигнала (если есть очень схожие сигналы по поведению, то их можно добавить в этот процесс). В результате должно получится несколько процессов с 1-2мя условиями if-else не более. Иначе синтезатор может сойти с ума, а в ISE вообще могут вылезти "волшебные" приколы.


Sample_proc: process(clk50)
begin
	if rising_edge(clk50) then

		if reset = '1' then
			sampl_cntr <= 0;
		end if;

		if(sampl_cntr /= sampl) then
			sampl_cntr <= sampl_cntr + 1;
		end if;
	end if;
end process Sample_proc'

Nested_counter: process(clk50)
begin
	if rising_edge(clk50) then
		if reset = '1' then
			nestd_SH_cntr <= 0;
		end if;

		if(sampl_cntr=sampl) AND (SHIFT_cntr /= slide_len) AND (nestd_SH_cntr /= slide_len) then
			nestd_SH_cntr <= nestd_SH_cntr + 1;
		end if;
	end if;
end process Nested_counter;

// и так далее. Это просто пример, логика может быть не соблюдена.

 

Именно так. Сложную задачу лучше разбить на несколько мелких. Хоть и количество строчек кода будет больше. Но главное качество, а не количество. Если алгоритм сложный - его, как правило проще реализовать не кучей условий if-else, а одним или несколькими конечными автоматами. Но надо понимать, что не все алгоритмы можно так реализовать... Пусть автор сперва озвучит свою задачу...

Share this post


Link to post
Share on other sites
On 9/23/2019 at 3:26 PM, nameless said:

Почему синтезатор "внешний" счетчик (SHIFT_cntr) писать в память A_ac_buff() позволяет а buff_10bit_std - нет?

Не  позволяет - это значит синтезирует бесконечно.

 

Если у вас память двух-портовая, опишите память отдельными процессами чтения и записи. 

UG901. Chapter 4: HDL Coding Techniques


 

process(clk)
begin
if clk'event and clk = '1' then
 if ena = '1' then
  if wea = '1' then
   RAM(conv_integer(addra)) := dia;
  end if;
 end if;
end if;
end process;


process(clk)
begin
 if clk'event and clk = '1' then
  if enb = '1' then
   dob <= RAM(conv_integer(addrb));
  end if;
end if;
end process;

 

Если одно-портовая, то одним отдельным процессом.

process(clk)
begin
if clk'event and clk = '1' then
if en = '1' then


  if we = '1' then
   RAM(conv_integer(addr)) <= di;
  end if;

  do <= RAM(conv_integer(addr));

end if;
end if;
end process;


 

И не нужно будет гадать - почему синтезатор не синтезирует.

 

 

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites
28 минут назад, nameless сказал:

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

 

Цифровой автомат Вам в помощь. Finit state machine - FSM

Share this post


Link to post
Share on other sites
28 минут назад, Flip-fl0p сказал:

Цифровой автомат Вам в помощь. Finit state machine - FSM

Я дополню.

У Вас nameless, неправильный подход к описанию. Вы пишите так, как это делается для программирования. Т.е. "условие - действие". И в случае программирования - это правильно. Но не в случае описания железа. Вы должны отдельно описать цифровые узлы, например вот такие счетчики - "sampl_cntr <= sampl_cntr + 1;" и для каждого узла сделать вывод разрешающий какое-то действие: счет, обнуление, хранение и тд.

А потом описать отдельный узел, который "ведет" процесс управления другими узлами, при этом он только активизирует сигналы управления. И как правильно сказал Flip-fl0p, удобнее это делать в виде автомата.

И видимо личное сообщение к Вам (ТС) не пришло...

Share this post


Link to post
Share on other sites
6 hours ago, Nick_K said:

 


Sample_proc: process(clk50)
begin
	if rising_edge(clk50) then

		if reset = '1' then
			sampl_cntr <= 0;
		end if;

		if(sampl_cntr /= sampl) then
			sampl_cntr <= sampl_cntr + 1;
		end if;
	end if;
end process Sample_proc'

Nested_counter: process(clk50)
begin
	if rising_edge(clk50) then
		if reset = '1' then
			nestd_SH_cntr <= 0;
		end if;

		if(sampl_cntr=sampl) AND (SHIFT_cntr /= slide_len) AND (nestd_SH_cntr /= slide_len) then
			nestd_SH_cntr <= nestd_SH_cntr + 1;
		end if;
	end if;
end process Nested_counter;

// и так далее. Это просто пример, логика может быть не соблюдена.

 

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

 

process (Clk) is
begin
    if  rising_edge(Clk)  then
        if  Reset = '1'  then
            Counter <= 0;
        elsif  Count_Enable = '1'  then
            Counter <= Counter + 1;
        end if;
    end if;
end process;

Ошибка в том, что, если не делать else, будут проверяться все условия, и в итоге счётчик получит значение, определяемое последним истинным условием.

1 hour ago, iosifk said:

У Вас nameless, неправильный подход к описанию. Вы пишите так, как это делается для программирования.

Это обычная беда начинающих, а временами и не очень-то начинающих "железописателей". Как по мне, осваивать электронику надо всё ж с рассыпухи -- реальных логических элементов, триггеров и т.п., чтоб на практике понять, а как оно в действительности работает, и приучить себя мыслить соответствующим образом. Заодно будешь понимать, во что примерно код на VHDL или другим "железном" языке будет синтезироваться.

Share this post


Link to post
Share on other sites
3 minutes ago, SII said:

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

Во-первых я написал, что

Это просто пример, логика может быть не соблюдена.

Я и не собирался писать абсолютно правильную конструкцию.

Во-вторых Xilinx рекомендует писать ваш пример так:

process (Clk) is
begin
	if  rising_edge(Clk)  then
		if  Reset = '1'  then
			Counter <= 0;
		else
			if Count_Enable = '1'  then
				Counter <= Counter + 1;
			end if;
		end if;
	end if;
end process;

Думаю альтера где-то так же.

В-третьих если написать так:

process (Clk) is
begin
	if  rising_edge(Clk)  then
		if Count_Enable = '1'  then
			Counter <= Counter + 1;
		end if;
		if  Reset = '1'  then
			Counter <= 0;
		end if;
	end if;
end process;

то конструкция всегда будет синтезирована правильно (как задумывается) даже если у вас будет нескколько условий сброса (например (Reset = '1' and Clear = '1')) чего не скажешь про первую конструкцию, которая может потребовать дополнительного сигнала Reset_and <= Reset and Clear либо воткнёт где ненужно мультиплексор. По крайней мере это было проверено неоднократно в ISE за многие годы разработки.

Share this post


Link to post
Share on other sites

Для начала открываем Template у каждого программного продукта он имеется.  + coding style guidelines   (например)

Берем оттуда готовые описания, подгоняем под свои нужды и делаем для каждого описания отдельные файлы.

Далее в топе просто их соединяем, как модули

Для начала думаю будет норм... 

 

Далее смотрит отчет синтезатора и смотрит RTL вьювер - что и как получилось.  Вместо рисования схемы на бумаге..

Далее можно попытаться объеденить базовые описания в одном (счетчики, дешифраторы мультиплексоры и т.д. описание памяти желательно оставить в отдельном файле) и посмотреть разницу...

Не забываем про симуляцию...

Иначе будет каша...

 

Share this post


Link to post
Share on other sites
14 hours ago, Nick_K said:

В-третьих если написать так:


process (Clk) is
begin
	if  rising_edge(Clk)  then
		if Count_Enable = '1'  then
			Counter <= Counter + 1;
		end if;
		if  Reset = '1'  then
			Counter <= 0;
		end if;
	end if;
end process;

то конструкция всегда будет синтезирована правильно (как задумывается) даже если у вас будет нескколько условий сброса (например (Reset = '1' and Clear = '1')) чего не скажешь про первую конструкцию, которая может потребовать дополнительного сигнала Reset_and <= Reset and Clear либо воткнёт где ненужно мультиплексор. По крайней мере это было проверено неоднократно в ISE за многие годы разработки.

Что вы понимаете под "правильно"? В коде есть неоднозначность, которая позволяет синтезатору по своему разумению расставить приритеты между сигналами reset и count_enable. Думаете он знает как "правильно" с вашей точки зрения? Что будет в случае если reset = 1 и count_enable = 1 ? Какое событие произойдёт и почему?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now