SM 15 March 24, 2015 Posted March 24, 2015 · Report post Схему этого монстра представляете? Вот что представили - то и синтезит :) Ну, скажете тоже, монстр... Внутри там, грубо говоря, просто пара логических элементов, выходы которых заведены на асинхронные S и R. Классика жанра - К155ИЕ7. Оно становится монстром, когда проектировщики пожидились сделать одновременно и R и S триггеру. Для тулзы понятия асинхронные\синхронные клоки нет Это, как сказать. Пишем латису BLOCK INTERCLOCKDOMAIN PATHS, и вот оно, умолчание проинвертировано... 2) "сдвиговый регистр с асинхронной загрузкой" - это регистр на латчах + мультиплексор имитирующий сдвиг + счётчик чтобы мультиплексор перебирать (обычно уже есть) Это вместо латч+2 флопа.... Это, опять же, когда как. Если в технологии имеется регистр с ALOAD, как например, в альтере, то такое городить не надо. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 March 24, 2015 Posted March 24, 2015 · Report post 1) асинхронное решение - плохое решение почему? Управлять труднее чем синхронным, но тоже имеет права на жизнь, а иногда без него никак... "сдвиговый регистр с асинхронной загрузкой" - это регистр на латчах + мультиплексор имитирующий сдвиг + счётчик чтобы мультиплексор перебирать не совсем верная замена, родной загрузиться и будет сдвигаться, и значение на входе можно менять как хочешь, а этот при смене значения на входе поломается... я заменил на регистр, который захватывает входное значение по первому клоку, а самый первый бит выдает сначала из входного значения, а потом из регистра. Мультиплексор меньше, и после захвата сразу можно входное значения менять на новое 3) тут биться не надо Ресетное значение будет идти до дестинейшен тригера ровно столько, чтобы гарантировать сетап тайм на нём. Смотрите выше что будет если много create_clock в схеме это я пока осознать не могу. Но если активным клоком управляю я, то зная время распространения сигнала, я всегда могу создать необходимую задержку на клоке, после снятия сброса. Так что все вопрос определить это время для контроля Quote Share this post Link to post Share on other sites More sharing options...
topor_topor 0 March 24, 2015 Posted March 24, 2015 · Report post это я пока осознать не могу. Но если активным клоком управляю я, то зная время распространения сигнала, я всегда могу создать необходимую задержку на клоке, после снятия сброса. Так что все вопрос определить это время для контроля это время определяется наибольшим временем между соурс и дестинейшен клок эджем. Или set_max_delay для этого пути Quote Share this post Link to post Share on other sites More sharing options...
SM 15 March 24, 2015 Posted March 24, 2015 · Report post почему? Управлять труднее чем синхронным, но тоже имеет права на жизнь, а иногда без него никак... Это, для верилог-программиста плохое решение. Потому, что он сути в железе происходящего не понимает. А так, вполне хорошее решение, если понимать эту суть :) Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 March 24, 2015 Posted March 24, 2015 · Report post Это, для верилог-программиста плохое решение. Потому, что он сути в железе происходящего не понимает. А так, вполне хорошее решение, если понимать эту суть sm.gif Какой-то сложный наезд... вроде это меня раньше пинали программистом, но с другой стороны я за это решение... не понятно в общем... сделал я 3 модулечка... приемник, считатель простейшей контрольной суммы, и передатчик... Не сочтите за труд, глянуть одним, а то и двумя глазами... это пока асинхронная часть, потом приделаю синхронную часть к ней. И констрайнами обвешаю... в передатчике решение с мультиплексором рабочее, но может можно как-то изящнее? Синхронная схема будет выставлять данные и слать наружу сигнал что данные готовы, внешняя схема будет выжидать гарантированную паузу, и начинать клокать... чипселект будет снят еще до выставления данных синхронной частью... module AsyncSPI_reciever_v1_00( spi_cs, //выбор модуля spi_clk, //клок SPI spi_data_in, //входные данные data, //принятые данные data_received //сигнал что очередное слово принято ); //================================================================================ == parameter SPI_WORD_SIZE = 8; //размер принимаемого слова parameter SPI_BIT_COUNTER_SIZE = 4; //размер регистра счетчика принятых бит //число бит до конца приема, за которое сбрасывают сигнал прошлого принятого слова parameter RECIVED_SIGNAL_CLEAR = 4; //за 4 бита до конца //================================================================================ == input spi_cs; input spi_clk; input spi_data_in; output reg [sPI_WORD_SIZE - 1 : 0] data = 0; output reg data_received = 0; //сдвиговый приемный регистр, на 1 бит меньше принимаемого слова reg [sPI_WORD_SIZE - 2 : 0] ShiftReg = 0; //счетчик принимаемых бит reg [sPI_BIT_COUNTER_SIZE - 1 : 0] BitCounter = SPI_WORD_SIZE; always @(posedge spi_clk or posedge spi_cs) begin if(spi_cs == 1'b1) // используем CS как асинхронный set/reset begin BitCounter <= SPI_WORD_SIZE; //обновляем счетчик data_received <= 0; //снимаем сигнал принятого слова end else begin //каждый такт сдвигаем данные, запоминаем новые поступившие данные ShiftReg <= {ShiftReg [sPI_WORD_SIZE - 3 : 0], spi_data_in}; //каждый такт уменьшаем счетчик принятых бит BitCounter <= $unsigned(BitCounter) - 1'b1; if (BitCounter == (RECIVED_SIGNAL_CLEAR + 1)) data_received <= 1'b0; //снимаем сигнал что данные приняты if(BitCounter == 1) //на последнем бите begin BitCounter <= SPI_WORD_SIZE; //обновляем счетчик data <= {ShiftReg, spi_data_in}; //сохраняем данные на выход data_received <= 1'b1; //выставляем сигнал что данные приняты end end end endmodule module AsyncSPI_CheckSum_Counter_v1_00( spi_cs, //выбор модуля spi_clk, //клок SPI spi_data_in, //входные данные check_sum //полученная контрольная сумма ); //================================================================================ == parameter SPI_CHECK_SUM_SIZE = 8; //размер контрольной суммы parameter SPI_CHECK_SUM_WORD_SIZE = SPI_CHECK_SUM_SIZE; //размер слова по которому идет суммирование parameter SPI_BIT_COUNTER_SIZE = 4; //размер регистра счетчика принятых бит parameter SPI_BEGIN_SUM_VALUE = 16'hA5; //начальное значение при расчете суммы //================================================================================ == input spi_cs; input spi_clk; input spi_data_in; output reg [sPI_CHECK_SUM_SIZE - 1 : 0] check_sum = SPI_BEGIN_SUM_VALUE; //сдвиговый приемный регистр, на 1 бит меньше слова суммы reg [sPI_CHECK_SUM_WORD_SIZE - 2 : 0] ShiftReg = 0; //счетчик принимаемых бит reg [sPI_BIT_COUNTER_SIZE - 1 : 0] BitCounter = SPI_CHECK_SUM_WORD_SIZE; always @(posedge spi_clk or posedge spi_cs) begin if(spi_cs == 1'b1) // используем CS как асинхронный set/reset begin BitCounter <= SPI_CHECK_SUM_WORD_SIZE; //обновляем счетчик check_sum <= $unsigned(SPI_BEGIN_SUM_VALUE); //начальное значение суммы end else begin //каждый такт сдвигаем данные, запоминаем новые поступившие данные ShiftReg <= {ShiftReg [sPI_CHECK_SUM_WORD_SIZE - 3 : 0], spi_data_in}; //каждый такт уменьшаем счетчик принятых бит BitCounter <= $unsigned(BitCounter) - 1'b1; if(BitCounter == 1) //на последнем бите begin //считаем контрольную сумму очередного слова check_sum <= $unsigned(check_sum) + $unsigned({ShiftReg, spi_data_in}); BitCounter <= SPI_CHECK_SUM_WORD_SIZE; //обновляем счетчик end end end endmodule module AsyncSPI_sender_v1_00( spi_cs, //выбор модуля spi_clk, //клок SPI spi_data_out, //выходные данные data, //данные для отправки data_can_change //сигнал что входные данные могут быть изменены ); //================================================================================ == parameter SPI_WORD_SIZE = 8; //размер отправляемого слова parameter SPI_BIT_COUNTER_SIZE = 4; //размер регистра счетчика отправляемых бит //число бит до конца передачи, за которое поднимается сигнал о возможности смены входного слова parameter CHANGE_SIGNAL_SET = 4; //за 4 бита до конца //================================================================================ == input spi_cs; input spi_clk; output spi_data_out; input [sPI_WORD_SIZE - 1 : 0] data; output reg data_can_change = 0; //сдвиговый передающий регистр, на 1 бит меньше передаваемого слова reg [sPI_WORD_SIZE - 2 : 0] ShiftReg = 0; //счетчик передаваемых бит reg [sPI_BIT_COUNTER_SIZE - 1 : 0] BitCounter = SPI_WORD_SIZE; //выходное значение формируется через мультиплексор //для начального бита берется из входных данных //для последующих бит из сдвигового регистра assign spi_data_out = (BitCounter == SPI_WORD_SIZE) ? data[sPI_WORD_SIZE - 1] : ShiftReg [sPI_WORD_SIZE - 2]; always @(posedge spi_clk or posedge spi_cs) begin if(spi_cs == 1'b1) // используем CS как асинхронный set/reset begin BitCounter <= SPI_WORD_SIZE; //обновляем счетчик data_can_change <= 0; //снимаем сигнал смены входного слова end else begin //для первого бита, запоминаем значение входного слово //со сдвигом в 1 бит, который уже отправлен в этом такте if(BitCounter == SPI_WORD_SIZE) ShiftReg <= data[sPI_WORD_SIZE - 2 : 0]; else //для остальных бит, сдвигаем регистр ShiftReg <= (ShiftReg << 1); //чем заменяем выдвинуты бит не важно //каждый такт уменьшаем счетчик принятых бит BitCounter <= $unsigned(BitCounter) - 1'b1; if (BitCounter == (CHANGE_SIGNAL_SET + 1)) data_can_change <= 1'b1; //ставим сигнал возможной смены слова if(BitCounter == 1) //на последнем бите begin BitCounter <= SPI_WORD_SIZE; //обновляем счетчик data_can_change <= 0; //снимаем сигнал возможности смены входного слова end end end endmodule Quote Share this post Link to post Share on other sites More sharing options...
SM 15 March 24, 2015 Posted March 24, 2015 · Report post Какой-то сложный наезд... вроде это меня раньше пинали программистом, но с другой стороны я за это решение... не понятно в общем... Это, как всегда, об одном и том же. Изучите цифровую схемотехнику, и 98% всех этих элементарных вопросов отпадут сами по себе. Нарисуете структурную схему устройства, из сдвиговых регистров, счетчиков, компараторов, сумматоров и прочих узлов, и все будет наглядно видно, где и какие констрейны нужны, и почему, и как это все грамотно описать на HDL. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 March 24, 2015 Posted March 24, 2015 · Report post что опять то не так? вроде все сделал по заветам:)... осталось обконстраинить выходные сигналы относительно клока, чтобы дошли на выход вовремя пути передачи данных из одного домена до другого чтобы паузу определить и сетап данных от клока, чтобы разные куски схемы от одного клока не разбижались и не знаю как этот параметр завется, время которое схема из асинхронного ресета выходит, чтобы знать через сколько можно начать передавать данные после снятия чипселекта и все... гарантированная задержка в синхронной части будет сетап + путь, выдержав ее данные точно будут готовы с данным из синхронной части в асинхронную не понятно немного. путь я обозначу, а надо задавать какой-то холд? Вообще у меня некая путаница в том что есть setup и что есть hold и что есть макс делай, но с этим буду разбираться... Quote Share this post Link to post Share on other sites More sharing options...
SM 15 March 24, 2015 Posted March 24, 2015 · Report post Вообще у меня некая путаница в том что есть setup и что есть hold и что есть макс делай, но с этим буду разбираться... Времянки триггера: setup (Tsu) - за сколько времени до фронта клока, не менее, на входе данных должны быть стабильные данные после их последней смены. hold (Th) - сколько времени после фронта клока, не менее, на входе данных должны удерживаться стабильные данные перед следующей их сменой. recovery (Tr) - через сколько времени после снятия асинхронного сигнала (загрузки, резета, установки), не менее, можно подать фронт клока. removal ( Tm ) - через сколько времени после фронта клока, если он был при активном сигнале асинхронного управления, не менее, можно снимать асинхронное управление. Clock-to-output (Tco) - через сколько времени после фронта клока обновятся данные на выходе. propagation time (Tpd) - через сколько времени после активизации сигнала асинхронного управления, либо при изменении асинхронных данных, произойдет изменение на выходе. Времянки для латча: setup (Tsu) - сколько времени, не менее, должно пройти после последней смены данных перед снятием сигнала загрузки, чтобы данные защелкнулись hold (Th) - сколько времени, не менее, должны удерживаться данные неизменными после снятия сигнала загрузки, чтобы данные защелкнулись. propagation time (Tpd) - через сколько времени после активизации сигнала загрузки, либо при изменении асинхронных данных, произойдет изменение на выходе. Времанки для логики: propagation time (Tpd) - через сколько времени произойдет изменение выхода после того, как произойдет изменение на входе. так вот - все эти set_max_delay, set_input_delay, set_output_delay всегда ограничивают одно и то же - propagation time пути между точками from и to, так, чтобы оно обеспечило выполнение требований по setup/hold/recovery/removal, заданных в базе данных внутренних структур ПЛИС, и (если они заданы) в input/output delay. В принципе, это все методы описания одного и того же. Один и тот же констрейн можно описать и через set_max_delay, и через set_input/output_delay. Разница в том, что первый способ ограничивает напрямую время распространения, а второй - косвенно - input/output_delay вычитается из периода клока, заданного для этой цепи, и делается тот же set_max_delay для полученного значения. Итого - задавать "какой-то сетап/холд" надо ТОЛЬКО тогда, когда сигнал идет наружу из ПЛИС, к кому-то, чей сетап/холд надо сообщить среде. Это делается через задание output_delay. Задавать какой-то "clock-to-output" надо тогда, когда сигнал идет откуда-то снаружи в ПЛИС, и надо сообщить среде этот самый clock-to-out этого кого-то, и задается это через set_input_delay. Все остальные случаи обычно задаются как max_delay. Среда сама знает все setup/hold/recovery/removal/Tco/Tpd для всего, что есть внутри ПЛИС без каких либо их заданий, на то она и среда, чтобы это все знать. Еще раз - изучите цифровую схемотехнику наконец-то!!!! Эти все сетапы (время установления), холды (время удержания), времена распространения, восстановления, снятия (propagation/recovery/removal), это самые азы оттуда! Ну сколько же можно одно и то же говорить! Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 March 24, 2015 Posted March 24, 2015 · Report post Спасибо, надо осмыслить... Еще раз - изучите цифровую схемотехнику наконец-то хорошо, завтра выучу.... %) это не быстро, я в процессе... сразу только кошки родятся... Путаница у меня потому что есть такой параметр через сколько после фронта значение сигнала становиться верным, и где то я видел ему название setup, время установки... Quote Share this post Link to post Share on other sites More sharing options...
SM 15 March 24, 2015 Posted March 24, 2015 · Report post Путаница у меня потому что есть такой параметр через сколько после фронта значение сигнала становиться верным, и где то я видел ему название setup, время установки... Он бывает обозван propagation delay (clk, out) - Tpd(clk,out), а бывает - Clock to output - Tco(out), но сетапом (именно, англ. setup) - никогда. сетап (как и hold, recovery, removal) это, наоборот, требование к входным сигналам, а не свойство выходного. А вот русское "время установления" - оно бывает приделано и к тому (сетапу), и к этому (Tpd/Tco). Попадаются формулировки "время установления кода", "время установления выхода счетчика", и т.п., и, да, это вызывает путаницу. Пользуйтесь однозначной англоязычной терминологией. Quote Share this post Link to post Share on other sites More sharing options...
topor_topor 0 March 25, 2015 Posted March 25, 2015 · Report post Итого - задавать "какой-то сетап/холд" надо ТОЛЬКО тогда, когда сигнал идет наружу из ПЛИС, к кому-то, чей сетап/холд надо сообщить среде. Это делается через задание output_delay. Задавать какой-то "clock-to-output" надо тогда, когда сигнал идет откуда-то снаружи в ПЛИС, и надо сообщить среде этот самый clock-to-out этого кого-то, и задается это через set_input_delay. Все остальные случаи обычно задаются как max_delay. Среда сама знает все setup/hold/recovery/removal/Tco/Tpd для всего, что есть внутри ПЛИС без каких либо их заданий, на то она и среда, чтобы это все знать. Еще раз - изучите цифровую схемотехнику наконец-то!!!! Эти все сетапы (время установления), холды (время удержания), времена распространения, восстановления, снятия (propagation/recovery/removal), это самые азы оттуда! Ну сколько же можно одно и то же говорить! Правильно. Добавлю только, что тпринципы синхронногот дизайна на то и придуманы, чтобы разработчик думал над схемами независимыми от баланса задержек. Все остальное - забота тулзов. Все эти сетап\холды надо понимать только для интерпретации еррор меседжев тулзы. В случае-же когда сигналы выходят наружу и надо сформировать времянку заданной формы (с требуемыми задержками), то это можно указать тулзе при помощи упомянутых set_input/output_delay, set_max\min_delay. Надо лиш разобраться в в опциях этих команд и вс станет ясно. Путаница у меня потому что есть такой параметр через сколько после фронта значение сигнала становиться верным, и где то я видел ему название setup, время установки... Если не задано set_input/output_delay, set_max\min_delay, то значение после фронта на тригере источнике имеет право прийти на тригер примник через время в диапазоне: минимум: холд тайм примника максимум: Разница между еджами на источнике и примнике - пропагейшен источника - сетап примника Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 March 25, 2015 Posted March 25, 2015 · Report post С констраинами боле менее все получилось. Для ксалинкса будет что-то вроде NET "clk_pin" TNM_NET = clk_pin; TIMESPEC TS_clk_pin = PERIOD "clk_pin" 20 ns HIGH 50%; #данные на входе будут готовы за 8 ns до восходящего фронта OFFSET = IN 8 ns VALID 10 ns BEFORE "clk_pin" RISING; #данные на выходе должны быть готовы не позже 8 нс после фронта OFFSET = OUT 8 ns VALID 10 ns AFTER "clk_pin" RISING; NET "encoder_spi_clk" TNM_NET = encoder_spi_clk; TIMESPEC TS_encoder_spi_clk = PERIOD "encoder_spi_clk" 20 ns HIGH 50%; #данные меняются по падающему клоку, за 10 нСек до восходящего #клока и остаются валидными весь цикл 20 нСек #зададим с запасом за 5 нСек, и валидными 10 нСек #данные на входе будут готовы за 8 ns до восходящего фронта OFFSET = IN 5 ns VALID 10 ns BEFORE "encoder_spi_clk" RISING; #данные на выходе должны быть готовы не позже чем за 5 нс до фронта OFFSET = OUT 5 ns VALID 10 ns BEFORE "encoder_spi_clk" RISING; NET "comm_spi_clk" TNM_NET = comm_spi_clk; TIMESPEC TS_comm_spi_clk = PERIOD "comm_spi_clk" 20 ns HIGH 50%; #данные меняются по падающему клоку, за 10 нСек до восходящего #клока и остаются валидными весь цикл 20 нСек #зададим с запасом за 5 нСек, и валидными 10 нСек #данные на входе будут готовы за 5 ns до восходящего фронта OFFSET = IN 5 ns VALID 10 ns BEFORE "comm_spi_clk" RISING; #данные на выходе должны быть готовы не позже чем за 5 нс до фронта OFFSET = OUT 5 ns VALID 10 ns BEFORE "comm_spi_clk" RISING; #между доменный переход #глобальный клок после PLL NET "glb_clk" TNM_NET = glb_clk; #ограничение времени распространения данных из #основного домена в домены SPI и обратно #зададим время распространения в пол величины быстрого клока TIMESPEC TS_glb_comm = from "glb_clk" to "comm_spi_clk" 5 ns DATAPATHONLY; TIMESPEC TS_glb_encoder = from "glb_clk" to "encoder_spi_clk" 5 ns DATAPATHONLY; TIMESPEC TS_comm_glb = from "comm_spi_clk" to "glb_clk" 5 ns DATAPATHONLY; TIMESPEC TS_encoder_glb = from "encoder_spi_clk" to "glb_clk" 5 ns DATAPATHONLY; Вроде бы все славно. Из немного беспокоящих непонятностей осталось вот что: NET "glb_clk" TNM_NET = glb_clk; - это определяет группу всех зависимых элементов от glb_clk. есть вариации NET "glb_clk" TNM_NET = FFS glb_clk; - все синхронные триггеры, сдвиговые регистры и прочее NET "glb_clk" TNM_NET = LATCH glb_clk; - все чувствительные к уровню защелки Вопросы: 1. Если не указать предопределенную группу FFS, LATCH... и так далее, означает ли что будут рассмотрены все возможные элементы и латчи и триггеры и память и прочее? 2. Триггеры с асинхронными сбросами в какую группу входят, наверное все же в FFS, и относительно сброса никакого анализа просто не идет, или идет? 3. В каких элементах спрятаны чувствительные к уровню латчи? То есть если у меня все происходит по posedge clk может так оказаться что мне синтезатор где-то латч запихает? В каких конструкциях оно может быть спрятано? 4. И совсем глупый вопрос, до этого я понимал как читать Timing constrain report, но сейчас получив очередной репорт и поглядев подробнее откуда и куда там что идет, как распределяются пути понял что возможно я не очень точно трактую показания его столбцов. Порыл инет на этот счет и что-то стало еще хуже. Можно на пальцах что есть worst case slack и best case Achievable? Все эти сетап\холды надо понимать только для интерпретации еррор меседжев тулзы. я не правильно применял эти слова, ими я называл нечто другое... еще забыл, когда добавляешь модуль PLL он сам создает сеть для выходного клока, со всеми вытекающими последствиями констраинов. Получается можно констраины писать не только в файле пользовательких констраинов, но и в самом модуле? Или это только для своих сделано? Quote Share this post Link to post Share on other sites More sharing options...