Я новичок в VHDL и изучаю его сам.
На практике я выполняю обработку данных (вычисление средних пространственных данных) для графических данных 320 * 240.
Я рассматриваю способ, как это:
1. Создайте кластер из 10 * 10 однородных простых элементов, где каждый элемент вычисляет среднее значение одного пикселя.
2. Каждый раз подключайте одну часть графических данных к кластеру 10 * 10, выполняйте расчеты, затем меняйте соединение. И после 32 * 24 раз работы, работа закончена.
Но я получил синтезирующую проблему на шаге 2. Чтобы динамически изменять соединения, я должен использовать переменные, отличные от i, j, в операторе FOR. Но, похоже, это невозможно синтезировать для этой схемы использования цикла FOR (время синтеза не ограничено).
Кто-нибудь мне поможет?
Проблемный сегмент кода выглядит следующим образом:
FSM1: process(clk) is
variable cnt1 : integer range 0 to 5 := 0;
variable cnt2 : integer range 0 to 32-1 := 0;
variable cnt3 : integer range 0 to 24-1 := 0;
variable BlockBaseX : integer range 0 to 310 := 0;
variable BlockBaseY : integer range 0 to 230 := 0;
variable varPRLLc_ave_indata : std_logic_vector(400*8-1 downto 0) :=(others=>'0');
begin
if rising_edge(clk) then
PRLLc_ave_indata <= varPRLLc_ave_indata;
if stateFSM2A = s3 then
case stateFSM1 is
when s1 =>
if do_InitCopy = '1' then
workGD <= baseGD;
end if;
stateFSM1 <= s2;
when s2 =>
if do_NumProc = '1' then
case cnt1 is
when 0 =>
BlockBaseX := cnt2*10; -- 10, 20, ..., 310
BlockBaseY := cnt3*10; -- 10, 20, ..., 230
for i in 0 to 9 loop
for j in 0 to 9 loop -- PRLLc_ave_indata (400*8-1 downto 0);
if i = 9 then
if j = 9 then
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j-1) & workGD(BlockBaseY+i-1, BlockBaseX+j) & workGD(BlockBaseY+i-1, BlockBaseX+j-1);
else
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j+1) & workGD(BlockBaseY+i-1, BlockBaseX+j) & workGD(BlockBaseY+i-1, BlockBaseX+j+1);
end if;
else
if j = 9 then
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j-1) & workGD(BlockBaseY+i+1, BlockBaseX+j) & workGD(BlockBaseY+i+1, BlockBaseX+j-1);
else
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j+1) & workGD(BlockBaseY+i+1, BlockBaseX+j) & workGD(BlockBaseY+i+1, BlockBaseX+j+1);
end if;
end if;
end loop;
end loop;
-- If the above For loop is replaced with the following one(BlockBaseX,BlockBaseY are removed), the synthesis can be accomplished.
-- for i in 0 to 9 loop
-- for j in 0 to 9 loop -- PRLLc_ave_indata (400*8-1 downto 0);
-- if i = 9 then
-- if j = 9 then
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j-1) & workGD(i-1, j) & workGD(i-1, j-1);
-- else
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j+1) & workGD(i-1, j) & workGD(i-1, j+1);
-- end if;
-- else
-- if j = 9 then
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j-1) & workGD(i+1, j) & workGD(i+1, j-1);
-- else
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j+1) & workGD(i+1, j) & workGD(i+1, j+1);
-- end if;
-- end if;
-- end loop;
-- end loop;
when 1 =>
when 2 =>
when 3 => -- got answer
when 4 =>
when others =>
end case;
if cnt1 < 5 then
cnt1 := cnt1 + 1;
else
cnt1 := 0;
if cnt2 < 32 then
cnt2 := cnt2 + 1;
else
cnt2 := 0;
if cnt3 < 24 then
cnt3 := cnt3 + 1;
else
cnt3 := 0;
stateFSM1 <= s3;
end if;
end if;
end if;
else
end if;
when s3 => -- after detecting a signal indicating OV7670 module has come to the requested point,
-- launch the pump out function - pump data from WorkGD to a stream
when others =>
end case;
else
stateFSM1 <= s1;
end if;
end if;
end process FSM1;