Перейти к содержанию
    

Непонятки с VHDL

Доброго времени суток. Понадобилось сделать некий простенький самописный арбитр, коммутирующий N входных потоков на один выходной. После некоторых раздумий написал следующий код, для простоты восприятия вместо параметра подставил константу 3, соответствующую трем потокам на входе:

 

out_priority_mux_p : process(srio_clk, rst)
 variable curr_num : integer;
 variable loop_num : integer;
begin
 if (rst = '1') then
   curr_num    := 2;  -- чтобы начать с нулевого потока
   ireq_tvalid <= '0';
 else
   if (rising_edge(srio_clk)) then

     if (ireq_tready = '1') then

ireq_tvalid <= '0'; -- на случай, если не один из входов не готов 

       stream_fingering_l : for stream_num in 3 downto 1 loop

  loop_num    := (curr_num + stream_num) mod 3;

    if (ireq_tvalid_vect(loop_num) = '1') then

      curr_num    := loop_num;

      ireq_tvalid <= '1';
      ireq_tdata  <= ireq_tdata_vect(curr_num);

    end if;

        end loop; --stream_fingering_l

     else
ireq_tvalid <= '0';
     end if;

   else	
NULL;
   end if;
 end if;
end process; --out_priority_mux_p

 

Для теста подаю на вход готовности единички по всем потокам, но выход все время залочен на поток с индексом 1.

 

Вспомнил про exit, переписал так:

 

out_priority_mux_p : process(srio_clk, rst)
 variable curr_num : integer;
 variable loop_num : integer;
begin
 if (rst = '1') then
   curr_num    := 2;  -- чтобы начать с нулевого потока
   ireq_tvalid <= '0';
 else
   if (rising_edge(srio_clk)) then

     if (ireq_tready = '1') then

ireq_tvalid <= '0'; -- на случай, если не один из входов не готов 

       stream_fingering_l : for stream_num in 1 to 3 loop

  loop_num    := (curr_num + stream_num) mod 3;

    if (ireq_tvalid_vect(loop_num) = '1') then

      curr_num    := loop_num;

      ireq_tvalid <= '1';
      ireq_tdata  <= ireq_tdata_vect(curr_num);

             exit;

    end if;

        end loop; --stream_fingering_l

     else
ireq_tvalid <= '0';
     end if;

   else	
NULL;
   end if;
 end if;
end process; --out_priority_mux_p

 

В этом случае получаю на выходе то, что ожидал.

 

Подскажите пожалуйста, в чем разница между двумя этими процессами.

Изменено пользователем Tausinov

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго времени суток. Понадобилось сделать некий простенький самописный арбитр, коммутирующий N входных потоков на один выходной. После некоторых раздумий написал следующий код, для простоты восприятия вместо параметра подставил константу 3, соответствующую трем потокам на входе:

 

А что же так выкрутасно...

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

"Параллельный арбитр":

000 - нет запросов

001 - запрос от младшего

011 - два запроса

111 - три запроса

 

Ну и дальше останется только мультиплексор с обычным case..

А еще есть понятие "последовательный арбитр", как дала DEC

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну и дальше останется только мультиплексор с обычным case..

 

Если я правильно вас понял, то это ведь не совсем то - в вашем варианте один абонент сможет занять линию, условно говоря, навсегда. А в моем варианте идет коммутация слотами, т.е. одному и тому же абоненту не дадут занять слот дважды подряд, если есть ожидающие другие абоненты.

 

А еще есть понятие "последовательный арбитр", как дала DEC

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если я правильно вас понял, то это ведь не совсем то - в вашем варианте один абонент сможет занять линию, условно говоря, навсегда. А в моем варианте идет коммутация слотами, т.е. одному и тому же абоненту не дадут занять слот дважды подряд, если есть ожидающие другие абоненты.

 

 

 

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

Фиксированные приоритеты,

вращающиеся приоритеты,

равноприоритетный доступ

 

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

Да и сидеть "разгадывать" великую идею арбитража, которая Вам нужна - это тоже "не айс" :)

Ну... Сделайте сдвиговый регистр, и в него вталкивайте передние фронты запросов...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рассмотрим случай когда все 3 мастера ожидают передачи данных, т.е. ireq_tvalid_vect = "111":

1) По ресету инициализируется переменная curr_num := 2;

2) 1-я итерация цикла "stream_fingering_l : for stream_num in 3 downto 1 loop"

stream_num = 3;

=> loop_num = (curr_num + stream_num) mod 3 = (2 + 3) mod 3 = 2

curr_num := loop_num = 2

3) 2-я итерация цикла ...

stream_num = 2;

=> loop_num = (curr_num + stream_num) mod 3 = (2 + 2) mod 3 = 1

curr_num := loop_num = 1

4) 3-я итерация цикла ...

stream_num = 1;

=> loop_num = (curr_num + stream_num) mod 3 = (1 + 1) mod 3 = 2

curr_num := loop_num = 2

 

В итоге получаем, что на выход арбитра всегда коммутируется 2-ой мастер.

 

Второй пример работает корректно, т.к. перебирает циклически все индексы.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...