Языки описания логических схем, например, Verilog или VHDL, основаны на возможности записывать асинхронные процессы, активирующиеся по изменению значений переменных.
Например, если нужно, чтобы что-то происходило по переднему фронту сигнала clock, так и пишем: always @(posedge clock) begin ... end. Если нужно, чтобы значение переменной перевычислялось каждый раз, когда изменяется любая из переменных, входящая в выражение, пишем, например, так: assign var = expression; или так: always @* begin ... end. Здесь @* означает "если какая-нибудь из переменных, упомянутых внутри блока c целью прочитать ее значение, изменится, выполнить блок".
Теперь, допустим, у нас есть элемент асинхронной памяти, активной не по фронту, а по уровню разрешения на запись, т.е. всегда, когда сигнал разрешения на запись равен 1, реализованный как
always @* if (write_enable) mem[address] = data;Что произойдет, если в какой-то момент write_enable равно единице, а переменная address изменится? Активируется этот процесс, и запишет текущее значение data в ячейку памяти по адресу, соответствующему новому значению переменной address. С точки зрения софтверного симулятора языка Verilog или VHDL - ровно в одну ячейку.
Подумаем, как бы эта память была реализована в хардвере. Слегка упрощая, у каждой ячейки будет свой блок логических элементов, побитно сравнивающих входящий адрес с ее собственным и делающих логическое И результата сравнения c сигналом write_enable, чтобы понять, надо записывать в себя входящие данные или нет.
И если address меняется, скажем, с 1 (...001) на 2 (...010), а проводочки для разных бит чуть-чуть разной длины, то может случиться краткий миг, когда сочетание значений бит будет или ...000, или ...011, и ячейка с адресом 0 или 3 решит в себя что-нибудь записать, совершив тем самым неприемлемое самоуправство.
Бороться с этим в хардвере очень просто - достаточно перед изменением значения переменной address установить сигнал write_enable в 0, а после изменения адреса выждать время, достаточное для нивелировки разницы времени распространения сигнала по отдельным битам адреса, после чего установить write_enable в 1.
А вот бороться с непониманием этого отличия софтверной симуляции от хардвера в головах отдельных инженеров гораздо труднее. Я уже второй день мучаюсь.