Tausinov 0 20 июля, 2016 Опубликовано 20 июля, 2016 (изменено) · Жалоба Доброго времени суток. Понадобилось сделать некий простенький самописный арбитр, коммутирующий 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 В этом случае получаю на выходе то, что ожидал. Подскажите пожалуйста, в чем разница между двумя этими процессами. Изменено 20 июля, 2016 пользователем Tausinov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 20 июля, 2016 Опубликовано 20 июля, 2016 · Жалоба Доброго времени суток. Понадобилось сделать некий простенький самописный арбитр, коммутирующий N входных потоков на один выходной. После некоторых раздумий написал следующий код, для простоты восприятия вместо параметра подставил константу 3, соответствующую трем потокам на входе: А что же так выкрутасно... представьте, что каждый абонент, требующий доступа будет выставлять свою единичку на запрос доступа в отдельном разряде вектора... "Параллельный арбитр": 000 - нет запросов 001 - запрос от младшего 011 - два запроса 111 - три запроса Ну и дальше останется только мультиплексор с обычным case.. А еще есть понятие "последовательный арбитр", как дала DEC Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tausinov 0 20 июля, 2016 Опубликовано 20 июля, 2016 · Жалоба Ну и дальше останется только мультиплексор с обычным case.. Если я правильно вас понял, то это ведь не совсем то - в вашем варианте один абонент сможет занять линию, условно говоря, навсегда. А в моем варианте идет коммутация слотами, т.е. одному и тому же абоненту не дадут занять слот дважды подряд, если есть ожидающие другие абоненты. А еще есть понятие "последовательный арбитр", как дала DEC Нашел через гугл вашу статью, насколько я понял, там такая же ситуация с по сути вечным присвоением ресурсов себе одним абонентом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 20 июля, 2016 Опубликовано 20 июля, 2016 · Жалоба Если я правильно вас понял, то это ведь не совсем то - в вашем варианте один абонент сможет занять линию, условно говоря, навсегда. А в моем варианте идет коммутация слотами, т.е. одному и тому же абоненту не дадут занять слот дважды подряд, если есть ожидающие другие абоненты. Нашел через гугл вашу статью, насколько я понял, там такая же ситуация с по сути вечным присвоением ресурсов себе одним абонентом. Фиксированные приоритеты, вращающиеся приоритеты, равноприоритетный доступ это все от Вас зависит... Вот только гнать сюда тексты исходников без каких-либо пояснений и практически без комментариев как раз и говорит о том, что ошибки будут... Да и сидеть "разгадывать" великую идею арбитража, которая Вам нужна - это тоже "не айс" :) Ну... Сделайте сдвиговый регистр, и в него вталкивайте передние фронты запросов... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aT-DeviLru 0 20 июля, 2016 Опубликовано 20 июля, 2016 · Жалоба Рассмотрим случай когда все 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-ой мастер. Второй пример работает корректно, т.к. перебирает циклически все индексы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться