Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблемы с VHDL кодом.
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
styuf
Доброе время суток!
Возник у меня вопрос, связанный с проектированием в FPGA. Суть вопроса такова: кто виноват и что делать, если при прочих равных условиях программа сбоит раз примерно в тысячу подходов.
Сбоит - это не опускается в '0' сигнал fft_cycle. Кусок кода, где все происходит вот:
CODE
PROCESS (clk120, clk25)

BEGIN

IF rising_edge(clk120) THEN
-- IF ( comp_turns = '1' AND comp_end_cycle = '1') THEN
IF ( q_turns_mem1 = '0' AND q_turns_mem3 = '1') THEN
k <= k+1;
ext_start <= '1';
ELSIF (k >= 1 AND k < 120) THEN
k<= k+1;
ext_start <= '1';
ELSIF (k = 120) THEN
k <= 0;
ext_start <= '0';
END IF;
END IF;

-----------------------алгоритм ффт блока -------------------------------------------------
IF rising_edge(clk25) THEN
glob_start_last<= glob_start;
ext_start_last <= ext_start;
ext_start_2_last <= ext_start_2;
ready_gen_last <= ready_gen;
start_pll_cycle_last <= start_pll_cycle;




IF (reset_n = '1') THEN

IF (fft_cycle = '0' AND (adr_rom_integer = 0) AND ((ext_start_last = '1') OR (ext_start_2 = '1'))) THEN
fft_cycle <= '1';
ext_start_2 <= '0';
adr_rom_integer <= adr_rom_integer + 1 ;
flag <= 1;
accum_clk_ena <= '0';
accum_aclr <= '1';
ramturnaddr_switcher <= '1';
ELSIF (adr_rom_integer >= 1 AND adr_rom_integer < 2050 ) THEN
flag <= 1;
accum_aclr <= '0';
adr_rom_integer <= adr_rom_integer + 1;
IF (adr_rom_integer >= 1024+2 ) THEN
accum_clk_ena <= '0';
start_fht <= '0';
if (fft_number = 1) then
signal_ram_wren_1 <= '1';
elsif (fft_number = 2) then
signal_ram_wren_2 <= '1';
end if;
ELSIF (adr_rom_integer < 1024+1 AND adr_rom_integer >= 1+1) THEN
accum_clk_ena <= '1';
start_fht <= '0';
if (fft_number = 1) then
signal_ram_wren_1 <= '1';
elsif (fft_number = 2) then
signal_ram_wren_2 <= '1';
end if;
ELSIF (adr_rom_integer = 1024+1) THEN
start_fht <= '1';
accum_clk_ena <= '1';
ELSE
start_fht <= '0';
accum_clk_ena <= '0';
END IF;
ELSIF (adr_rom_integer >= 2050 AND adr_rom_integer < 2053) THEN
accum_aclr <= '1';
flag <= 0;
signal_ram_wren_1 <= '0';
signal_ram_wren_2 <= '0';
ramturnaddr_switcher <= '0';
adr_rom_integer <= 0;
ELSIF (adr_rom_integer = 2053 ) THEN
adr_rom_integer <= 0;
accum_aclr <= '1';
flag <= 0;
END IF;
------------------------------------------------------------------------------
IF (adr_ram_integer = 0 AND ready_fht = '1') THEN
adr_ram_integer <= adr_ram_integer + 1;
if (fft_number = 1) then
write_ena_1 <= '1';
else
write_ena_2 <= '1';
end if;
flag <= 2;
start_gen <= '0';
ELSIF (adr_ram_integer >= 1 AND adr_ram_integer < 1024 AND flag = 2) THEN
adr_ram_integer <= adr_ram_integer + 1;
if (fft_number = 1) then
write_ena_1 <= '1';
elsif (fft_number = 2) then
write_ena_2 <= '1';
end if;
flag <= 2;
start_gen <= '0';
ELSIF (adr_ram_integer = 1024 ) THEN
adr_ram_integer <= 0;
write_ena_1 <= '0';
write_ena_2 <= '0';
start_sr_vz <= '1';
start_gen <= '0';
flag <= 0;
END IF;
----------------------------------------------------------------------------------
IF (start_sr_vz = '1' AND adr_ram_data_integer = 0) THEN
flag <= 3;
start_sr_vz <= '0';
adr_ram_data_integer <= adr_ram_data_integer + 1;
ELSIF (adr_ram_data_integer >= 1 AND adr_ram_data_integer < 512) THEN
adr_ram_data_integer <= adr_ram_data_integer + 1;
flag <= 3;
ELSIF (adr_ram_data_integer = 512) THEN
adr_ram_data_integer <= 0;
flag <= 0;
ram_d_wren <= '0';
count_ram_data <= 0;
END IF;
----------------------------------------------------------------------------------
IF (ready_sr_vz = '1' AND count_ram_data = 0) THEN
flag <= 4;
ram_d_wren <= '1';
count_ram_data <= count_ram_data + 1;
ram_d <= (others => '0');

ELSIF ( count_ram_data = 1 ) THEN
flag <= 4;
ram_d_wren <= '1';
count_ram_data <= count_ram_data + 1;
ram_d <= result_sr_vz_1;
if (fft_number = 1) then
freq1_1 <= result_sr_vz_1;
elsif (fft_number = 2) then
freq2_1 <= result_sr_vz_1;
end if;
ELSIF ( count_ram_data = 2 ) THEN
flag <= 4;
ram_d_wren <= '1';
count_ram_data <= count_ram_data + 1;
ram_d <= result_sr_vz_2;
if (fft_number = 1) then
freq1_2 <= result_sr_vz_2;
else
freq2_2 <= result_sr_vz_2;
end if;
ELSIF ( count_ram_data = 3 ) THEN
flag <= 4;
ram_d_wren <= '1';
count_ram_data <= count_ram_data + 1;
ram_d <= result_sr_vz_3;
if (fft_number = 1) then
max_zn1_1 <= result_sr_vz_3;
elsif (fft_number = 2) then
max_zn2_1 <= result_sr_vz_3;
end if;
ELSIF ( count_ram_data = 4 ) THEN
flag <= 4;
ram_d_wren <= '1';
count_ram_data <= count_ram_data + 1;
ram_d <= result_sr_vz_4;
if (fft_number = 1) then
max_zn1_2 <= result_sr_vz_4;
elsif (fft_number = 2) then
max_zn2_2 <= result_sr_vz_4;
end if;
ELsIF (count_ram_data = 5) THEN
flag <= 0;
fft_cycle <= '0';
ram_d_wren <= '0';
count_ram_data <= 0;
ram_d <= (others => '0');
if (fft_number = 1) then
fft_number <= 2;
ext_start_2 <= '1';
elsif (fft_number = 2) then
fft_number <= 1;
ext_start_2 <= '0';
end if;

END IF;
ELSE
reset_n <= '1';

END IF;

------------------------------------------------------------------------------
END IF;
-----------------------------конец алгоритма ффт блока-----------------------------------------------

END PROCESS;


END HEAD;

Проблема явно возникает из-за гонки фронтов сигналов, но так-как частота не большая, а FPGA - Cyclone III, то выглядит это весьма странно. Если есть вопросы по коду или еще чему - спрашивайте. Замучился уже искать причину, а слабое место программы найти не могу crying.gif
_Anatoliy
Цитата(styuf @ Jan 19 2011, 14:18) *

Какие уж тут вопросы - метастабильность налицо.

Попробуйте так:
Код
        ext_start_last_temp <= ext_start;
        ext_start_last <= ext_start_last_temp;


Одного триггера явно мало,нужно как минимум два.
Остальные места посмотрите сами.
bogaev_roman
Цитата(styuf @ Jan 19 2011, 15:18) *
Проблема явно возникает из-за гонки фронтов сигналов, но так-как частота не большая, а FPGA - Cyclone III, то выглядит это весьма странно. Если есть вопросы по коду или еще чему - спрашивайте. Замучился уже искать причину, а слабое место программы найти не могу crying.gif

Частота то небольшая, только логики комбинационной наворотили хотя бы в этом куске - кучу(1 компаратор+and+мультиплексор с управляющим входом на компараторе с сумматором+мультиплексор):
Код
ELSIF (adr_rom_integer >= 1 AND adr_rom_integer < 2050 ) THEN
flag <= 1;
accum_aclr <= '0';
adr_rom_integer <= adr_rom_integer + 1;
IF (adr_rom_integer >= 1024+2 ) THEN
accum_clk_ena <= '0';
start_fht <= '0';
if (fft_number = 1) then
signal_ram_wren_1 <= '1';

Советую сначала удостовериться, что возникают временные ошибки (у меня сомнений в этом нет), а потом либо распараллелить, либо оптимизировать код. Ну и то, что советовал _Anatoliy
DW0
clk120, clk25 120 и 25 это в МГц???
если да, то для больших комбинационных структур 120 это совсем не мало, еще 120 и 25 не очень кратны, все время фронт с фронтом пересекаются, это может вызвать гонки, например по фронту clk120 сформировались данные, и тут же фронт clk25, а комбинационная логика не успела переключиться и в регистрах всякий мусор зафиксировался.
какая разрядность adr_ram_integer??? если вы просто описали signal adr_ram_integer : interger;, то переменная adr_ram_integer имеет 32 разряда, можете себе представить сколько комбинационной логике пойдет на компараторы, мультиплексоры и прочее.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.