.
Возникло сомнение в правильности фазы выдачи сигналов SEL1 и SEL2 в модели Qsync ( и её CPP-варианте ).
Async :
Qsync
![]()
.
Возникло сомнение в правильности фазы выдачи сигналов SEL1 и SEL2 в модели Qsync ( и её CPP-варианте ).
Async :
Qsync
![]()
.
Аналогично для начального изменения сигнала INIT :
Async
Qsync
- - - Добавлено - - -
Если модель Async верна - в модели Qsync все сигналы должны изменяться точно так же, как и в модели Async.
При текущем алгоритме изменения SEL1 - при входе в HALT_TRAP он остаётся установленным при уже выданном на шину адресе 177676 :
Код:################ HALT Trap to 160002 = HALT ################ ; 000010 -> 177716:000000 ------------------------------------------------- C B S D D W R B I I D D S I H E A D I S S L AD S Y I O T P S R A M M A N A V C C R L L C Y N N U B L 7 Q K R G C I L N L L 3 1 2 ------------------------------------------------- 1 177716 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 177716 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 160001 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 160001 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 000000 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 000000 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 160011 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 160011 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 000000 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 ; PSW :000344 -> 177676:177777 ------------------------------------------------- C B S D D W R B I I D D S I H E A D I S S L AD S Y I O T P S R A M M A N A V C C R L L C Y N N U B L 7 Q K R G C I L N L L 3 1 2 ------------------------------------------------- 1 177676 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 177676 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 000344 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 000344 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 000344 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 000344 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 000000 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Последний раз редактировалось Patron; 18.12.2015 в 17:24.
Проверил ~SELx, там нет ошибки в Async, все соответствует схеме, видимо, сигнал через два регистра и дешифратор долго проходит.
По INIT фаза в моделях будет отличаться, так выполнен переход на синхронную модель, триггер был нужен. Сигнал длительный, практически никогда в работе не используется, поэтому разницу в такта в момент сброса не считаю принципиальной.
В том и проблема модели Qsync, что адрес там выставляется без задержки ( как в модели Async ), а SEL1 изменяется с задержкой ( не как в модели Async )
Но в CPP-модели такая неадекватность явно лишняя - надо ( наверное ) особо подчеркнуть в комментариях к коду модели Qsync, каким должно быть правильное поведение сигнала INIT в данном случае.
Я второстепенные сигналы (BSY, INIT, SEL, входы прерываний) не очень точно переносил, там может быть фазовое отличие на полтакта/такт.
Я уже не помню как оно было, там относительно запутанный сдвиговый регистр с обратной связью, как я понимаю, оно сделано для того чтобы обеспечить минимальную длительность сигнала сброса периферии процессора, если сигнал приходит извне. Ну и сброс всего провессора по INIT если есть ACLO. Проще на реальном процессоре посмотреть как ведет себя INIT при старте.
Сигнал SEL должен выставляться синхронно с адресом, а сниматься синхронно с SYNC - иначе на шине возникает куча-мала.
В текущей CPP-модели сигнал INIT ведёт себя не как в реальном процессоре, а как в модели Qsync - и это не радует.
- - - Добавлено - - -
Если в модели Qsync при вычислении pin_init_out заменить reset на reset_rc - сигнал INIT начинает изменяться синхронно с DCLO :
Есть ли у такого решения какие-то недостатки ?Код:assign pin_init_out = init_out[0] | reset_rc;
Последний раз редактировалось Patron; 18.12.2015 в 19:16.
По схеме процессора - nSELx это защелка (латч) равенства состояния шины AD адресу 1777xx, фиксируется по nSYNC. То есть - пока nSYNC высокий, состояние nSEL изменяется согласно состоянию AD, когда nSYNC активируется (спад в низкий уровень, начало цикла) - nSEL замораживается. То есть, это не какой-то сакральный внутрений сигнал, который как-то влияет на исполнение кода или внутренности процессора, это просто тупой дешифратор адреса.
С установкой nSELx при высоком nSYNC в обоих моделях все в порядке, Async ставит строго согласно схемы, в реальном процессоре сигнал физически запаздывает (там на картинке видно что по срезу CLC на шину наконец вылазит достоверный адрес и почти сразу за его установлением активируется nSEL1). То есть - Async строго кошерный, но из-за своей идеальности дает немного отличную картинку от реального процессора. Qsync дешифрацию и защелкивание nSELx выполняет по фронту CLC. Это реальное отличие, да. Связано с тем, что у нас в схемотехнике не допускаются латчи, а на полтакта ранее по срезу CLC дешифрацию выполнить нельзя - потому что еще нет адреса и не разрешена работа шины. Но, главное, nSELx все равно активирован до среза nSYNC, то есть логика шины никак не нарушается. Со снятием непонятно что смущает, в любом случае на шине имеется минимум длительностью один такт высокого nSYNC, nSELx при этом в Async/Qsync вполне корректно снимается:
Итого - Async идеальный, строго по схеме, из-за этого сигнал nSEL выглядит как пришедший на полтакта раньше. Qsync задерживает nSEL на полтакта (не по схеме), но так же выглядит и реальный процессор. Принципиальных проблем для работы шины тут нет - взаимный порядок событий с nSYNC соблюден. Еще надо не забывать что nSYNC и AD - это комбинации внутренних и внешних сигналов, от внутреннего и внешнего агентов, процессор же может читаться-писаться внешним агентом, и тут уже фазу защелкивания во флип-флопе подкручивать бесполезно. Теоретически, для того чтобы ставить nSEL в Qsync на полтакта ранее, для внутреннего обращения можно было бы куда-то залезть глубого внутрь, вытащить адрес для дешифрации прямо с ALU, предсказать запись в регистр адреса areg, предсказать разрешение шины (если она опоздает то надо дешифровать позже, то есть уже с выхода регистра areg, а не с АЛУ - появится мультиплексор адреса, замечательно), и выполнять фиксацию дешифрации одновременно с этими всеми событиями. А для внешнего обращения это все вообще не работает, надо строить еще один параллельный дешифратор. В итоге получим достаточно сложную и нечитаемую схему. Для сохранения фазы многих внутренних управляющих сигналов это было оправдано и делалось (теперь иногда приходится вникать, потому что оно совсем уж дико выглядит местами), для второстепенного сигнала дешифратора, с незначительным непринципиальным отставанием фазы - нет.
Впрочем, для CPP-модели внести изменение проблем нет, можно защелки sel_xx
обрабатывать по обоим фронтам. Верилог такого не пропустит, а на C++ это запросто. Тогда и будет счастье, всем и даромКод:always @(posedge pin_clk_p) begin if (~pin_sync_in) begin sel_xx <= sel177x; sel_00 <= sel177x & (pin_ad_in[3:1] == 3'b000); sel_02 <= sel177x & (pin_ad_in[3:1] == 3'b001); sel_04 <= sel177x & (pin_ad_in[3:1] == 3'b010); sel_06 <= sel177x & (pin_ad_in[3:1] == 3'b011); sel_10 <= sel177x & (pin_ad_in[3:1] == 3'b100); sel_12 <= sel177x & (pin_ad_in[3:1] == 3'b101); sel_14 <= sel177x & (pin_ad_in[3:1] == 3'b110); sel_16 <= sel177x & (pin_ad_in[3:1] == 3'b111); end end
Этот кусок инициализации при переносе в синхронную модель некоторое время не хотел работать и требовал отладки, поэтому немного отличается от реальной схемы. Qsync строится на совсем других принципах, отличных от Async и реального процессора, в ней не допускается применение латчей. Чисто теоретически в Qsync можно добиться точно такой же картинки как в Async, но в некоторых местах это требует неоправданного усложнения и изменения логики (становится менее понятной и читаемой). Поэтому незначительные фазовые отличия для редких событий на второстепенных сигналах, скорее всего, в Qsync останутся.
- - - Добавлено - - -
Чисто теоретические - сбросы пытаются не делать сложными комбинационными схемами. Выход станет зависеть напрямую от DCLO, несинхронизировано. pin_init_out снаружи соединен с pin_init_in, который используется для сброса таймера и детекторов спада прерывания, поэтому его желательно для реальной ПЛИС таки синхронизировать - разветвленные комбинационные схемы иногда дают ложные короткие пики и асинхронные сбросы их успевают поймать. По pin_init_in предполагается внешняя синхронизация при реальном использовании. Но если практически - то, думаю, можно так поступить, особенно для CPP модели (мне в Qsync стабильность и нежелание потенциальных проблем все-таки важнее, но ОК, тоже внесу коррекцию).
PS. DCLO в реальных схемах (БК/1201.01) по срезу CLC синхронизировано вне процессора, поэтому такой ситуации как на диаграмме не будет.
Последний раз редактировалось Vslav; 18.12.2015 в 22:16.
Потому в tbench.v более актуален такой код :
Код:// // CPU start // @ (negedge clk); @ (negedge clk); @ (negedge clk); @ (negedge clk); dclo = 1; @ (negedge clk); @ (negedge clk); @ (negedge clk); @ (negedge clk); @ (negedge clk); @ (negedge clk); @ (negedge clk); @ (negedge clk); aclo = 1; $display("Processor ACLO and DCLO deasserted");
Да, можно и так сделать, внесу изменения.
- - - Добавлено - - -
Кстати, начальная цель при переходе на Qsync была оставить только одну тактовую частоту и только одно событие по фронту тактовой частоты (это бы и ускорило CPP-модель, только eval_p остался бы). Две фазы достаточно сильно усложняют логику и забирают избыточные ресурсы, это я просто не осилил за один проход такое упрощение сделать. Поэтому все фазы соблюдались бы с точностью максимум до полутакта. Теперь есть модель Wsync, если и будет модификация до единой частоты, то уже на ней, Qsync в этом плане меняться не будет.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)