Доброго времени суток, уважаемые читатели.
На самом деле я инженер-радиофизик и программирование ПЛИС не является моей непосредственной деятельностью, но в один момент понадобилось написать программу для синхронизации нескольких осцилографических модулей. Пришлось осваивать эту науку. О том, какие у меня возникли с этим проблемы, под катом.
Многие Надеюсь, хотя бы один из вас программировал под FPGA на уровне выше чем моргание светодиодом. Если такое было, то вы могли бы заметить, что иногда что-то работает не так. Возникают проблемы с таймингами подобного рода: с повышение частоты, система становится нестабильной, битики начинают залипать, данные пропадают и проект не работает.
Это перефраз статьи о том, откуда эти проблемы берутся и как с ними бороться. Автор поста использует ALTERA и софт для разработки той же фирмы(Quartus II).
Чтобы лучше понять суть проблемы, рассмотрим простейшую модель 8ми битной ячейки памяти.
module habr111(
input [7:0] data,
input clk,
output[7:0] out
);
reg [7:0] count;
always @ ( posedge clk )
count <= data;
assign out = count;
endmodule
Запускаем симулятор и видим, что когда данные приходят на вход в определенной фазе относительно тактирующего сигнала, то на выходе появляются мусорные данные.
Все дело в том, что д-триггер цифровое устройство только в первом приближении. То есть по сути это набор аналоговых транзисторов, имеющих свое время нарастания фронтов. Бывает, что clock ловит момент, когда сигнал дорастает до напряжения перехода между 0 и 1. Это называется метастабильным состоянием и что будет сформировано на выходе не очевидно.
Так же каждый бит имеет свою задержку: какие-то биты приходят раньше, какие-то позже. Если переключение данных происходит в момент переключения clocka, то из-за вышеописанного эффекта на выход идет мешанина старых и новых битов.
Чтобы проект работал корректно, необходимо избавиться от этих эффектов. Для этого надо самостоятельно считать те самые времена. В Quartus II этим занимается программа timequest. Спрашивается: зачем нам это знать?
Схема, по которой timeqwest обсчитывает тайминги, состоит из двух регистров. Если все их параметры известны, она посчитает и сделает правильную разводку. Но если есть некий внешний регистр, о котором у timeqwest никакой информации нет, то разработчику необходимо посчитать и ввести все самостоятельно. Как это делается — описывается в этой статье.
Мой вольный перевод.
Надеюсь кому-нибудь это поможет так же, как помогло и мне.
Автор: Serenia