Jump to content

    

Nagisa

Свой
  • Content Count

    85
  • Joined

Community Reputation

0 Обычный

1 Follower

About Nagisa

  • Rank
    Частый гость
  • Birthday February 3

Информация

  • Город
    Array

Recent Profile Visitors

1068 profile views
  1. никто не объяснил как мне обойтись без него ;-) согласно ТЗ мне необходимо читать видеопоток со скоростью 11796480 слов в секунду , иначе говоря по одному слову за ~84нс цикл с памятью получается минимум 8 операций с частотой 92MHz - те ~86нс те я в принципе не успею даже на VGA выплюнуть поток, а мне еще надо облуживать 2 системы которые тоже хотят читать и писать в память (можно перейти на CL2 это даст экономию но проблемы не решит) если же я использую bust то необходимые 256 слов на строку я читаю в 4 захода по 32 слова и трачу на все это ~3,5мкс против ~22мкс если бы это было одиночное чтение, и успеваю с минимальными задержками обслуживать других абонентов на счет сильно усложняет - я минимизировал изменение логики - те отличие только в длине цикла + времени подачи команды BURST_TERMINATE
  2. в итоге все переехало в автоматы пришлось правда один сигнал управления протаскивать через global clock таки 2й циклон достаточно медленный..... burst заработал как надо, контроллер получился 3х режимный - те одиночная запись, одиночное чтение и пакетное чтение. (режим пакетного чтения на самом деле включен всегда, просто при одночном чтении торможение идет почти стазу, а в пакетном по нужной длине. )
  3. в итоге продвинулся вперед, а именно сделал: 1. автоматы на каждую операцию применительно к абоненту - чтение, запись 2. приоритетный шифратор (всего получается 6 операций) 3. автомат операции для общения с контроллером SDRAM 4. автомат с переменной длиной в непосредственном контроллере SDRAM сейчас прикручиваю VGA и кусок ниже мне мешает однако есть глупый вопрос вот у меня кусок always @(posedge dout_en or posedge B_SYNC_L) begin if (dout_en==1 ) begin DA_OUT<=drd; // данные с SDRAM на шину selbus<=1; // управление шиной - направлением - включаем на выдачу end else begin selbus<=0; // управление шиной - направлением - выключаем end end // dout_en идет с контроллера SDRAM и появляется синхронно с данными (опаздывает на 1/2такта дабы данные установились) // B_SYNC_L - завершение обмена по шине те чистая асинхронщина вопрос - как же сделать правильно ? да, dout_en имеет длительность в несколько тактов - те длиной в бурст, в данном случае он работает как фронт по которому будет взято слово переключить шину обратно надо не ранее B_SYNC_L=1 мне приходит в голову только автомат, но правильно ли так ?
  4. ну так это мне и нужно - те быстро считать в буфер всю строку которую я буду выводить потом на экран на частоте в 130MHz у меня уйдет на это ~1.1мкс в худшем случае - те всего 72 клока VGA (всего у меня их 320 на это) именно и я собираюсь в это время считать строку в буфер обязательно посмотрю сейчас думаю переделать контроллер введя унификацию - те запись 1 слово, а вот чтение всегда 32 слова, для чтения строки я это буду повторять через цикл обслуживания шины - те 4 раза. получится всего два режима, что явно проще текущей ситуации где 3 режима.
  5. согласно даташита, модуль, требует 4096 циклов автоматической регенерации каждые 64мс; выполнение команды автоматической регенерации каждые 15625мкс необходимо и достаточно для полной регенерации. альтернативный вариант - 4096 циклов каждые 64мс. у меня строка 20.67мкс, кадр 15.87мс считывание в буфер строки 1.1мкс максимальная интенсивность работы процессора по загрузке памяти - 1 запрос за 2.5мкс, в длинном цикле у меня уйдет 123нс на обслуживание 1 запроса. получается, что память будет занята ~2.2мкс, а 18.55мкс будет заниматься авторефрешем - те 2400 циклов рефреша на каждые 20.67мкс, что полностью закрывает требования памяти по рефрешу. PS: данные исходя из 130MHz
  6. он жизненно важен - ибо у меня не только обслуживание процессора, но и VGA контроллер. Соответственно в начале каждой строки я читаю bust-ом из SDRAM в памяти самой ПЛИС строку и потом уже ее вывожу вот и получается у меня 3 режима работы. причем если на чтение процу я могу сказать - подожди, те выдать RPLY позднее, то с записью все плохо - я должен ее как минимум сохранить ее в регистр и потом записать в память. запросы на строку burst-ом идут пусть 768 раз в секунду, те есть время на рефреш. немного съест работа проца, но он медленный, те авторефреша должно хватить с большим запасом.
  7. да, я сейчас планирую кардинально переделать автомат, те сделать его приоритетом burst-чтение ибо сейчас или хвост или нос - или нормально работает burst-чтение или операции с шиной, совмещение несет проблемы.
  8. на счет стиля, с точки зрения красоты, да case-вид лучше, но вот тестирование показало что: wire [3:0] run_cmd = (act && (q == STATE_CMD_START ))?CMD_ACTIVE: // есть чтение или запись -> начинаем процесс (!act && (q == STATE_CMD_START ))?CMD_AUTO_REFRESH: // нет ничего - авторефреш ( wre && (q == STATE_CMD_CONT ))?CMD_WRITE: // we -> запись (( oe || rb ) && (q == STATE_CMD_CONT ))?CMD_READ: // не we + oe -> чтение ( oe && (q == STATE_CMD_READ_STOP ))?CMD_BURST_TERMINATE: // тормозим чтение CMD_INHIBIT; работает на 130MHz а вот это нет- максимум 108 wire [3:0] run_cmd; always @ * begin case (q) STATE_CMD_START: if (act) run_cmd=CMD_ACTIVE; else run_cmd=CMD_AUTO_REFRESH; STATE_CMD_CONT: if (wre) run_cmd=CMD_WRITE; else if ( oe || rb ) run_cmd=CMD_READ; STATE_CMD_READ_STOP: if (oe) run_cmd=CMD_BURST_TERMINATE; default: run_cmd=CMD_INHIBIT; endcase end
  9. а можно конкретнее ? я потому и спрашиваю как это правильно сделать тк сам затупил. изначально я взял автомат синхронизированный с шиной, переделал на асинхронный вариант (те автомат состояний крутится постоянно), сделал защелку, прикрутил полную корректную инциализационную процедуру, все на 130 завелось а вот стал прикручивать burst и тут столкнулся с проблемами. собственно бурст мне нужен для упреждающего чтения строки в внутриплисовую память, из которой она размеренно пойдет на VGA если есть примеры реализации контроллера памяти для обслуживания проца и видеопамяти будет очень полезно идею с упрощением я понял (и пытался максимально унифицировать, включив бурст на чтение постоянно, но в обычном режиме посылая прерывание чтения), но не понял как это сделать если у меня разные адресаты и мне точно надо разделять чтение строки и одного слова. как тут правильнее сделать автомат ? и таки хочется получить ответы на вопросы в конце
  10. скорость те у меня циклон 2 и я хочу 130MHz на SDRAM. без бурста на 130 работает, с бурстом нет. конечно, в крайнем случае я могу опустится до 65MHz ....
  11. делаю на Verloge контроллер SDRAM c обработкой 3х запросов а именно: по приоритетам начиная с самого высокого 1. rd - запрос на чтение из памяти, синхронный 2. rdb - запрос на пакетное чтение, отложенный - те можем немного ждать 3. wr - запрос на запись, полностью асинхронный, делаем когда можем Соответственно RD - синхронный, ждем результата и отдаем внешней системе WR это адрес+данные в регистр и отработаем когда будем свободны, но запомнить факт поступления запроса мы должны тк запрос на запись может поступить во время пакетного чтения. RB - запрос пакетного чтения 128 слов, можем немного подождать и завершить процессы чтения/записи общий автомат памяти localparam STATE_FIRST = 4'd0; // first state in cycle localparam STATE_CMD_START = 4'd1; // state in which a new command can be started localparam STATE_CMD_CONT = 4'd4; // STATE_CMD_START + RASCAS_DELAY; // 4 command can be continued localparam STATE_CMD_READ_STOP = 4'd5; // остановка чтения, примеряется при однословном чтении localparam STATE_CMD_READ = 4'd7; // данные готовы localparam STATE_LAST = 4'd15; // last state in cycle reg [3:0] q; always @(posedge clk) begin if (reset_done==1 && ct_rb_zr==1) // процедура инициализации завершена и нет чтения пакета q <= q + 3'd1; // тогда меняем состояение автомата end кусок кода с автоматами обработки запросов // автомат состояний очереди записи localparam STATE_W_WAIT =2'd1; localparam STATE_W_PREPARE =2'd2; localparam STATE_W_WRITE =2'd3; localparam STATE_W_WRITED =2'd0; reg [1:0] statew; always @ (posedge clk) begin if(((statew==STATE_W_WAIT ) && (wr==1 )) || // мы готовы к приему сигнала записи и он поступил - идем в STATEW_PREPARE ((statew==STATE_W_PREPARE) && (q == STATE_FIRST) && oe==0 && rb==0) || // есть данные на запись + есть готовность к началу обработки + ждем завершения других процессов ((statew==STATE_W_WRITE ) && (q == STATE_LAST)) || // запись завершена ((statew==STATE_W_WRITED ) && (wr== 0)) // исходная система завершила цикл записи ) statew <= statew + 2'd1; // меняем статус вперед end wire we= statew[1] ; // автомат состояний очереди чтения localparam STATE_R_WAIT =2'd1; localparam STATE_R_PREPARE =2'd2; localparam STATE_R_READ =2'd3; localparam STATE_R_READED =2'd0; reg [1:0] stater; always @ (posedge clk) begin if(((stater==STATE_R_WAIT ) && (rd== 1 && we==0 && rb==0)) || // мы готовы к приему сигнала чтения и он поступил + есть готовность к началу обработки - идем в STATER_PREPARE ((stater==STATE_R_PREPARE) && (q == STATE_FIRST)) || // есть команда на чтение ((stater==STATE_R_READ ) && (q == STATE_LAST)) || // чтение завершено ((stater==STATE_R_READED ) && (rd== 0)) // исходная система завершила цикл чтения ) stater <= stater + 2'd1; // меняем статус вперед end wire oe=stater[1]; // автомат состояний чтения строки в буфер localparam STATE_RB_WAIT =2'd1; localparam STATE_RB_PREPARE =2'd2; localparam STATE_RB_READ =2'd3; localparam STATE_RB_READED =2'd0; reg [1:0] staterb; always @ (posedge clk) begin if(((staterb==STATE_RB_WAIT ) && (rdb== 1)) || // мы готовы к приему сигнала пакетного чтения и он поступил - идем в STATERB_PREPARE ((staterb==STATE_RB_PREPARE) && (q == STATE_FIRST) && we==0 && oe==0) || // есть команда на чтение + есть готовность к началу обработки ((staterb==STATE_RB_READ ) && (q == STATE_LAST)) || // запись завершена ((staterb==STATE_RB_READED ) ) // исходная система завершила цикл чтения ) staterb <= staterb + 2'd1; // меняем статус вперед end wire rb= staterb[1]; reg [6:0] ct_rb; // счетчик burst-а wire startrb=(q==STATE_CMD_READ) && (staterb==STATE_RB_READ); wire ct_rb_zr=~(|ct_rb); always @ (posedge clk) begin if ( (ct_rb_zr==1 && startrb==1) || (ct_rb_zr==0) ) // условия счета ct_rb<=ct_rb+1; end в куске пакетного чтения как только у нас наступает статус STATE_CMD_READ - я торможу автомат и читаю 128 слов при одиночных чтениях/записях конфликта работает, при интенсивном использовании - глюки нутром чую что делаю не так, но не могу сообразить как это правильнее - подскажите также вопрос - что лучше для определения ноля ? reg [6:0] ct_rb; // счетчик burst-а wire ct_rb_zr=(ct_rb==0); или wire ct_rb_zr=~(|ct_rb); в первом случае в RTL я вижу модуль сравнения, во втором простой логический элемент к чему лучше стремиться ? конструкция с большим if лучше чем case с if-ами в каждом состоянии ? имеет ли смысл делать вместо счетчика состояний автомата делать сдвиговый регистр, и уже проверять состояния автомата по нужному биту в регистре ? те не надо сравнивать регистр целиком а достаточно 1 бита ? прошу направить на путь правильный