TimeQuest для чайников. Часть 4 (Как много интерфейсов разных)

Вот мы и подошли к основному таинству TimeQuesta. Это таинство задания временных ограничений для интерфейсов ввода/вывода. Интерфейсов существует великое множество, но относительно методов их обработки и задания констрейнов их можно разделить на 2 основные группы : асинхронные и синхронные интерфейсы.

Под синхронностью я понимаю метод обработки интерфейса в ПЛИС. Если для обработки потока данных используется логика, тактируемая от частоты этого интерфейса, то такой интерфейс я называю синхронным. В противном случае интерфейс асинхронный.

Асинхронные я делю на истинно асинхронные (т.е. обрабатываемые полностью на  комбинационной логике) и асинхронные с обработкой на системном клоке. Синхронные же в свою очередь делятся по признаку местоположения источника тактовой частоты на system-synchonus и source-synchronus интерфейсы.

Есть еще самосинхронные интерфейсы работающие с Clock Data Recovery (CDR), но их мы рассматривать не будем. Также не будем рассматривать подробно вопросы реализации интерфейсов, нас интересует только задание временных ограничений в TimeQuest. 

Асинхронные интерфейсы 


Истинно асинхронные интерфейсы

Иногда требуется сделать какие нибудь простые дешифраторы команд/сигналов или делать иную комбинационную логику. В большинстве случаев можно объявить все пути как false_path и не париться, в любом случае задержки там будут не более 20нс и для большинства применений этого более чем достаточно.

Но есть случаи когда нарушение времянок распространения путей чревато. Кроме того, есть особая категория плисоводов, которые любят увлекаться асинхронщиной. Очень часто этим страдают начинающие плисоводы, не читавшие библии HDL Chip Design (с) Douglas Smith. В таких проектах подают на тактовые входы триггеров комбинационные сигналы и т.д. Часто удивляются почему не работает.

Работать то оно будет, но только в том случае если вы правильно прописали констрейны на эту асинхронщину и учли температурную зависимость длины асинхронных путей. Рассмотрим простой пример регистра защелки. 

module async (input cs_n, we_n, input [7 : 0] idat, output [7 : 0] odat);
    always_ff @(negedge we_n) begin 
odat <= ~cs_n ? idat : odat; 
    end 
endmodule 
sdc файл для такого проекта, на сыклоне 3, может быть таким 
create_clock -period 10MHz -name {write} [get_ports {we_n}]
 
set_max_delay -from [get_ports {cs_n}] -to [get_pins {odat[*]~reg0|ena}] 5.5ns
set_min_delay -from [get_ports {cs_n}] -to [get_pins {odat[*]~reg0|ena}] 4.5ns
 
set_max_delay -from [get_ports {idat[*]}] -to [get_pins {odat[*]~reg0|d}] 5.5ns
set_min_delay -from [get_ports {idat[*]}] -to [get_pins {odat[*]~reg0|d}] 4.5ns
 
set_max_delay -from [get_pins {odat[*]~reg0|q}] -to [get_ports {odat[*]}] 5.5ns
set_min_delay -from [get_pins {odat[*]~reg0|q}] -to [get_ports {odat[*]}] 4.5ns
Ага скажут многие, а клок то все таки есть. Да есть, но нужен он для того, что бы TimeQuest не кричал о нарушении Minimal Pulse Width сигнала приходящего на тактовые порты триггеров. 
Как вы видите для данной схемы пришлось прописывать все основные задержки по путям, при этом применять их надо к конкретным пинам триггера ПЛИС. При смене семейства ПЛИС потребуется правка этих пинов в sdc файле. 
Собственно все, собираем проект, запускаем анализ и в итоге видим 
 

Квартусу не хватает ума, что бы с помощью LUT ов выровнять задержки по некоторым путям, делать это придется в рукопашную, вставляя lcell буферы. Или расширить диапазон требуемой задержки. Другого пути я не вижу.

Видя такую особенность квартуса вспоминается старая реклама "Вы все еще балуетесь асинхронщиной? Тогда мы идем к вам...". На самом деле никуда мы не идем, решение о том что использовать, а что нет, в вашем проекте лежит целиком на вас. 


Асинхронные интерфейсы с обработкой на системном клоке

В качестве яркого примера асинхронного интерфейса можно взять всем известный, самый обычный UART.

Приемный сигнал UART_TX -> FPGA_RX нарезают системной частотой, которая должна быть выше символьной частоты UART и обрабатывают, используя детекторы перехода сигнала из состояния в состояние.

Констрейны на такие интерфейсы это уже знакомые нам set_false_path

set_false_path -from [get_ports {uart_rx}] -to [get_clocks{sys_clk}]

Так мы задаем путь, который не надо анализировать от порта uart_rx до триггеров тактируемых клоком sys_clk

set_false_path -from [get_ports {uart_rx}] -to [all_clocks]

А так путь от порта uart_rx до триггеров тактируемых от любого из клоков в системе. С выходным сигналом поступаем точно так же

set_false_path -from [all_clocks] -to [get_ports {uart_tx}]

Стоит отметить, что в данном случае (UART) можно даже не контролировать использование триггера в I/O буфере ПЛИС.

Рассмотрим теперь более сложный пример, возьмем простой SPI мастер. Положим, что данные захватываются слейвом по фронту тактовой частоты.

module spi (input clk, start, input [7 : 0] data, output logic busy, sclk, sdi, cs_n) ;

  logic         ff  ;
  logic [3 : 0] cnt ;
  logic         done;
  logic [7 : 0] buffer;

  assign ff   = cnt[0];
  assign done = &cnt;

  always_ff @(posedge clk) begin // simple FSM
    if (~busy) begin
      if (start) begin
        busy    <= 1'b1;
        cnt     <= 0;
        buffer  <= data;
      end
    end
    else begin
      cnt <= cnt + 1'b1;
      if (ff) begin
        buffer  <= (buffer << 1);
      end
      if (done) begin
        busy <= 1'b0;
      end
    end
  end

  always_ff @(posedge clk) begin // io registers
    sclk <= ff;
    sdi  <= buffer[7];
    cs_n <= ~busy;
  end

endmodule

По идее этот интерфейс синхронный, т.е. вместе с данными передается сигнал тактовой частоты sclk. Но как мы видим из кода, временные отношения между сигналами заданы последовательностью состояний конечного автомата. И единственное что нужно, для их четкого выполнения, убедиться, что выходные триггеры были размещены в I/O ячейках. Как вы уже, наверное, догадались, констрейны для данного интерфейса будут

set_false_path -from [get_clocks {clk}] -to [get_ports {sclk sdi cs_n}]

ПредпросмотрAttachmentSize
Clock_Setup_and_Hold_Slack_Explained.doc191.5 КБ
mnl_timequest_cookbook.pdf481.87 КБ
an433.pdf1.38 МБ

Комментарии

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

Спасибо Автору! Всё очень

Спасибо Автору! Всё очень понятно описано! Нужно поправить ссылку на картинку под строкой ...С помошью Report Worst Case Path смотрим что же происходит в интерфейсе.
des00 аватар

Спасибо, поправил

Спасибо, поправил

Самоя первая картинка не

Самоя первая картинка не соответствует превью.(я так понимаю превью правильнее)

(уточнение) Самая первая

(уточнение)

Самая первая картинка на 3й странице не соответствует превью.(я так понимаю превью правильнее)

set_output_delay -clock

set_output_delay -clock [get_clocks {oclk}] -min -5.0 [get_ports {data[*]}]

как получается что мин делай отрицательная, как понять это физически???? 

я понимаю она вычислялась по формуле OmD = min tD (EXT) – tH (EXT) – max tCS (EXT),  

des00 аватар

Физически это понимается

Физически это понимается очень просто. Любые задержки задаются относительно фронтов таковой частоты приемника данных. В одном случае мы задаем запас для времени предустановки, в другом случая для времени удержания.

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <p> <span> <s> <strike> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <caption> <tbody> <tr> <td> <em> <b> <u> <i> <strong> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <embed> <object> <param> <strike>
  • Использовать как разделитель страниц.

Подробнее о форматировании