|
Оптимальная реализация мультиплексора |
|
|
|
Jan 15 2008, 13:25
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 3-02-05
Пользователь №: 2 391

|
Ситуация такая - в проекте имеется большой мультиплексор к которому подключена куча регистров. Timing Analyzer показывает, что это самое тормознутое место в проекте. Сейчас проект растет, при этом Fmax падает. Т.е. необходимо оптимизировать узкие места. Я пробовал несколько способов описания мультиплексора (с помощью case, if, tri-state), но особого изменения по скорости нет. Сейчас использую такое описание: Код -- DATA output MX process(nand_busy, sreg_test_sel, sreg_pfd0_sel, sreg_pfd1_sel, sreg_pw0_sel, sreg_pw1_sel, sreg_pctl_sel, sreg_ncmd_sel, sreg_nsta_sel, sreg_nrwc_sel, sreg_nadr1_sel, sreg_nadr2_sel, sreg_nadr3_sel, sreg_nadr4_sel, sreg_nadr5_sel, sreg_nid1_sel, sreg_nid2_sel, sreg_nid3_sel, sreg_nid4_sel, sreg_nid5_sel, nand_buf_sel, nand_dout) begin if(sreg_test_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_test(7 downto 0); elsif(sreg_pfd0_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pfd0(7 downto 0); elsif(sreg_pfd1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pfd1(7 downto 0); elsif(sreg_pw0_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pw0(7 downto 0); elsif(sreg_pw1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pw1(7 downto 0); elsif(sreg_pctl_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pctl(7 downto 0); elsif(sreg_ncmd_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_ncmd(7 downto 0); elsif(sreg_nsta_sel='1') then dataout_mx(15 downto 0)<=sreg_ncsta(7 downto 0) & sreg_nsta(7 downto 0); elsif(sreg_nrwc_sel='1') then dataout_mx(15 downto 0)<=sreg_nrwc(15 downto 0); -- 16 bits elsif(sreg_nadr1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr1(7 downto 0); elsif(sreg_nadr2_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr2(7 downto 0); elsif(sreg_nadr3_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr3(7 downto 0); elsif(sreg_nadr4_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr4(7 downto 0); elsif(sreg_nadr5_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr5(7 downto 0); elsif(sreg_nid1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid1(7 downto 0); elsif(sreg_nid2_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid2(7 downto 0); elsif(sreg_nid3_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid3(7 downto 0); elsif(sreg_nid4_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid4(7 downto 0); elsif(sreg_nid5_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid5(7 downto 0); elsif(nand_buf_sel='1') then dataout_mx(15 downto 0)<=x"00" & nand_dout(7 downto 0); else dataout_mx(15 downto 0)<=x"FFFF"; end if; end process;
-- DATA output reg process(CLK100, dataout_mx) begin if(rising_edge(CLK100)) then dataout_reg(15 downto 0)<=dataout_mx(15 downto 0); end if; end process; Как можно соптимизировать этого монстра - разбить на кучу маленьких и запайплайнить? Или как? Сейчас Fmax=106MHz и очень не хочется делать ее меньше. Кстати, использую Spartan-3E(-4). Принимаются любые соображения.
|
|
|
|
|
Jan 15 2008, 15:13
|

Lazy
     
Группа: Свой
Сообщений: 2 070
Регистрация: 21-06-04
Из: Ukraine
Пользователь №: 76

|
Цитата(DeadMoroz @ Jan 15 2008, 17:25)  Ситуация такая - в проекте имеется большой мультиплексор к которому подключена куча регистров. Timing Analyzer показывает, что это самое тормознутое место в проекте. Сейчас проект растет, при этом Fmax падает. Т.е. необходимо оптимизировать узкие места. Я пробовал несколько способов описания мультиплексора (с помощью case, if, tri-state), но особого изменения по скорости нет. Сейчас использую такое описание: Код -- DATA output MX process(nand_busy, sreg_test_sel, sreg_pfd0_sel, sreg_pfd1_sel, sreg_pw0_sel, sreg_pw1_sel, sreg_pctl_sel, sreg_ncmd_sel, sreg_nsta_sel, sreg_nrwc_sel, sreg_nadr1_sel, sreg_nadr2_sel, sreg_nadr3_sel, sreg_nadr4_sel, sreg_nadr5_sel, sreg_nid1_sel, sreg_nid2_sel, sreg_nid3_sel, sreg_nid4_sel, sreg_nid5_sel, nand_buf_sel, nand_dout) begin if(sreg_test_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_test(7 downto 0); elsif(sreg_pfd0_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pfd0(7 downto 0); elsif(sreg_pfd1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pfd1(7 downto 0); elsif(sreg_pw0_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pw0(7 downto 0); elsif(sreg_pw1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pw1(7 downto 0); elsif(sreg_pctl_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_pctl(7 downto 0); elsif(sreg_ncmd_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_ncmd(7 downto 0); elsif(sreg_nsta_sel='1') then dataout_mx(15 downto 0)<=sreg_ncsta(7 downto 0) & sreg_nsta(7 downto 0); elsif(sreg_nrwc_sel='1') then dataout_mx(15 downto 0)<=sreg_nrwc(15 downto 0); -- 16 bits elsif(sreg_nadr1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr1(7 downto 0); elsif(sreg_nadr2_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr2(7 downto 0); elsif(sreg_nadr3_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr3(7 downto 0); elsif(sreg_nadr4_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr4(7 downto 0); elsif(sreg_nadr5_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nadr5(7 downto 0); elsif(sreg_nid1_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid1(7 downto 0); elsif(sreg_nid2_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid2(7 downto 0); elsif(sreg_nid3_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid3(7 downto 0); elsif(sreg_nid4_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid4(7 downto 0); elsif(sreg_nid5_sel='1') then dataout_mx(15 downto 0)<=x"00" & sreg_nid5(7 downto 0); elsif(nand_buf_sel='1') then dataout_mx(15 downto 0)<=x"00" & nand_dout(7 downto 0); else dataout_mx(15 downto 0)<=x"FFFF"; end if; end process;
-- DATA output reg process(CLK100, dataout_mx) begin if(rising_edge(CLK100)) then dataout_reg(15 downto 0)<=dataout_mx(15 downto 0); end if; end process; Как можно соптимизировать этого монстра - разбить на кучу маленьких и запайплайнить? Или как? Сейчас Fmax=106MHz и очень не хочется делать ее меньше. Кстати, использую Spartan-3E(-4). Принимаются любые соображения. Кстати, осторожно, конвейер может Вам форму сигнала изменить... Точнее, д-триггеры, из которых он состоит. Если конечно, данные не синхронны с частотой конвейера....
--------------------
"Everything should be made as simple as possible, but not simpler." - Albert Einstein
|
|
|
|
|
Jan 15 2008, 15:52
|
Участник

Группа: Новичок
Сообщений: 20
Регистрация: 13-10-06
Пользователь №: 21 281

|
Цитата(DeadMoroz @ Jan 15 2008, 17:25)  Ситуация такая - в проекте имеется большой мультиплексор к которому подключена куча регистров. Timing Analyzer показывает, что это самое тормознутое место в проекте. Сейчас проект растет, при этом Fmax падает. Т.е. необходимо оптимизировать узкие места. Я пробовал несколько способов описания мультиплексора (с помощью case, if, tri-state), но особого изменения по скорости нет. Сейчас использую такое описание:
Как можно соптимизировать этого монстра - разбить на кучу маленьких и запайплайнить? Или как? Сейчас Fmax=106MHz и очень не хочется делать ее меньше. Кстати, использую Spartan-3E(-4). Принимаются любые соображения. При любом описании (if-else, tri-state, case) и т.д. реализация получится прблизительно одинаковой. Однако могу вам предложить несколько другой подход. Если в вашем проекте последовательность формирования сигналов селекции, а следовательно и последовательность выдачи данных одна и таже, можно все данные вначале выгружать в буферный конвейерный регистр, а затем выдавать их на внешнюю шину. Конечно такая реализация "съест" много рессурсов, но производительность получится максимальной. Кроме того в этом случае вы получите информацию о статусе системы в момент переноса данных в буферный регистр, т.е. не совсем реальное время. Насколько это подойдет определяется конечно же конкретными требованиями системы.
|
|
|
|
|
Jan 16 2008, 04:47
|

МедвеД Инженер I
   
Группа: Свой
Сообщений: 816
Регистрация: 21-10-04
Пользователь №: 951

|
Цитата(DeadMoroz @ Jan 15 2008, 22:25)  Ситуация такая - в проекте имеется большой мультиплексор к которому подключена куча регистров. Timing Analyzer показывает, что это самое тормознутое место в проекте. Сейчас проект растет, при этом Fmax падает. Т.е. необходимо оптимизировать узкие места. Я пробовал несколько способов описания мультиплексора (с помощью case, if, tri-state), но особого изменения по скорости нет. Сейчас использую такое описание: ................ Как можно соптимизировать этого монстра - разбить на кучу маленьких и запайплайнить? Или как? Сейчас Fmax=106MHz и очень не хочется делать ее меньше. Кстати, использую Spartan-3E(-4). Принимаются любые соображения. У меня "дурацкое" предложение, а что если регистры запихать в память(2-х портоувую)? предполагаю Ваш ответ, памяти мало и её жалко Если так, то вариантов не так уж и много, их уже все перечислили
--------------------
Cogito ergo sum
|
|
|
|
|
Jan 16 2008, 07:50
|

Lazy
     
Группа: Свой
Сообщений: 2 070
Регистрация: 21-06-04
Из: Ukraine
Пользователь №: 76

|
Цитата(DeadMoroz @ Jan 16 2008, 03:38)  Victor - не пойму, почему форма сигнала может измениться? ведь конвеер только добавит задержку на n тактов?
sazh - Вы имеете ввиду сделать отдельные mx для каждого разряда?
alex5991- такой подход неприменим, т.к. внешний CPU может обращаться к регистрам FPGA в произвольном порядке. Привет! Посмотрите рисунок... сравните D и Q. Естественно, чем выше частота тактирования относительно D, тем меньше эффект проявляется
Эскизы прикрепленных изображений
--------------------
"Everything should be made as simple as possible, but not simpler." - Albert Einstein
|
|
|
|
|
Jan 16 2008, 14:11
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 3-02-05
Пользователь №: 2 391

|
des00 - так сразу не скажу где затык - в цепи данных или декодирования, позже посмотрю, но насколько я помню, Static Timing Analyzer показывал 5 слоев логики. Использую я кстати Spartan-3E 500ку + XST, не альтеру.
Postoroniy_V - да я думал насчет такого варианта, и память еще есть и ее даже не жалко, но не получится же получить побитовый доступ к этой двухпортовке. А чтобы получить - придецца забабахать какую нибудь FSM которая будет гонять данные между памятью и регистрами, я так понимаю.
Евгений Николаев - да, конечно, 8ми битные регистры можно объединить, только это временное улучшение, т.к. мне надо будет добавить еще кучу новых.
Victor® - ага, я понял, но вроде мне это не грозит - все внутренние данные синхронны, домен один.
|
|
|
|
|
Jan 17 2008, 03:57
|
Вечный ламер
     
Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453

|
Цитата(DeadMoroz @ Jan 16 2008, 09:11)  des00 - так сразу не скажу где затык - в цепи данных или декодирования, позже посмотрю, но насколько я помню, Static Timing Analyzer показывал 5 слоев логики. Использую я кстати Spartan-3E 500ку + XST, не альтеру. если платформа от хилых, тогда 32 в 1 должен ложится в LUT-> MUXF4->MUXF5->MUXF6->MUXF7 см refer to the “Using Dedicated Multiplexers” chapter in UG331. при этом задержки разводки должны отсутствовать, т.к. все идет в пределах CLB. Все сильно похоже на задержку по цепи управления, определяется это легко. В логах на тайминги указываются начальные и конечные точки измерения задержки. описывайте мультиплексор через case. если можно играть с адресами, то можно попробывать разбить регистры на группы, что бы выиграть немного в ресурсе. И ИМХО если есть возможность откажитесь от ohehot кодирования сигналов адреса мультиплексора в пользу бинарных. либо держите их 2 такта ( + multicycle constrain 2) и получите бинарный адрес на регистре. Удачи.
--------------------
|
|
|
|
|
Jan 17 2008, 08:39
|
Местный
  
Группа: Свой
Сообщений: 292
Регистрация: 28-01-05
Из: МО, Мытищи
Пользователь №: 2 274

|
Цитата(DeadMoroz @ Jan 15 2008, 16:25)  Как можно соптимизировать этого монстра - разбить на кучу маленьких и запайплайнить? Или как? Сейчас Fmax=106MHz и очень не хочется делать ее меньше. Кстати, использую Spartan-3E(-4). Проблема может быть и в длинне трасс от регистров до регистра после мультиплексора. Так на кристалле XC3S400-4 оринтировочный порог 10 нс. На большем кристалле (Вы не указали размер) будет хуже. Если не жалко задержать выдачу на 1 такт, то можно предложить такую схему (Dn - данные в регистрах, Sn - выборка региста по методу one-hot): 1) объединяем данные от группы регистров, расположенных недалеко друг от друга и защелкиваем в промежуточный регистр. Q <= D0 & S0 | D1 & S1 (это ложится в один LUT4+D) Q <= D0 & S0 | D1 & S1 | D2 & S2 | D3 & S3 (один slice) 2) объединяем выходы промежуточных регистров по "или" и защелкиваем в выходной регистр. QQ <= Q0 | Q1 | ... Qn Правда при такой схеме по умолчанию на выходе будет 0 (мы именно такой метод применяем, так как 0 более безопасное значение в случае ошибок программистов). Если принципиально нужно все 1 (FFFF). То используем чуть другую функцию и объединение по "и": Q <= (D0 | ~S0) & (D1 | ~S1) QQ <= Q0 & Q1 & ... Qn Пример логических выражений на языке Verilog. Думаю это не составит проблему. Использовать мультиплексор (предложения в постах выше) получится только если все регистры идут последовательно в адресном пространстве и выровнены на границу 2 в N. Иными словами адрес представляе собой двоичное число. Иначе всё выродится в схему, предложенную выше (выборка по и, далее объединение по или).
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|