Как правило, процедурные блоки могут содержать операторы задержки или ожидания события, которые блокируют процедуру до тех пор, пока не будет удовлетворено время или событие. Эти операторы используются как в симуляции, так и в синтезе для написания тестовых программ и описания логики; Гибкость этих конструкций (например, задержка #
или ожидание события @
) довольно велика. Однако, используя их для описания оборудования, вы можете использовать их только в ограниченных ситуациях.
Ваш случай: @(posedge (sclk ^ (CPHA ^ CPOL)) or posedge spi_word_send)
просто говорит: подождите, пока выражение sclk ^ CPHA ^ CPOL
не перейдет от низкого к высокому (posedge
) или spi_word_send
, чтобы перейти от низкого к высокому, затем выполните выражения, содержащиеся в always
block (один пример изменения выражения xor с низкого на высокое: sclk = 1, CPHA = 1, CPOL = 0
становится sclk = 1, CPHA = 1, CPOL = 1
, (1 ^ 1 ^ 0 = 0, 1 ^ 1 ^ 1 = 1).
Язык позволяет вам иметь такие сложные выражения ожидания, и инструменты моделирования, как правило, запускают его, как и ожидалось, но если выражение предполагается синтезировать, вам нужно быть уверенным, что вы на самом деле описываете необходимое оборудование. Как уже упоминалось, это не очень хороший стиль, и он описывает триггер с довольно сложным тактовым сигналом (или, возможно, установкой / сбросом, инструмент синтеза постарается изо всех сил, но, вероятно, сгенерирует что-то странное для этого, если он вообще пройдет); это, безусловно, асинхронная логика. Большинство проектов являются синхронными, и инструменты синтеза обычно предназначены для обработки синхронных проектов, когда они описываются поведенчески, как приведенный выше. Таким образом, на блоки always @
наложены существенные ограничения, т. Е. Что-то вроде always @(posedge some_clock or negedge some_asserted_low_reset)
, чтобы гарантировать, что код, выводящий чистые триггеры, очистит часы и сбросит их.