SystemVerilog микширование неблокирующих и блокирующих назначений для арбитра
Я не могу обернуться вокруг примера 10-3 в книге Стюарта Сазерленда (и соавторов) SystemVerilog For Design.
Смотрите строку 232 из:
Вот фрагмент кода. Мой вопрос будет следовать.
bit [0:NumRx-1] RoundRobin;
always_ff @(posedge clk, posedge reset) begin: FSM
bit breakVar;
if (reset) begin: reset_logic
Rxready <= '1;
Txvalid <= '0;
Txsel_out <= '0;
SquatState <= wait_rx_valid;
forward <= 0;
RoundRobin = 1;
end: reset_logic
else begin: FSM_sequencer
unique case (SquatState)
wait_rx_valid: begin: rx_valid_state
Rxready <= '1;
breakVar = 1;
for (int j=0; j<NumRx; j+=1) begin: loop1
for (int i=0; i<NumRx; i+=1) begin: loop2
if (Rxvalid[i] && RoundRobin[i] && breakVar)
begin: match
ATMcell <= RxATMcell[i];
Rxready[i] <= 0;
SquatState <= wait_rx_not_valid;
breakVar = 0;
end: match
end: loop2
if (breakVar)
RoundRobin={RoundRobin[1:$bits(RoundRobin)-1],
RoundRobin[0]};
end: loop1
end: rx_valid_state
В частности, мой вопрос о назначении блокировки для breakVar и RoundRobin. Я где-то читал, что переменные оцениваются локально, но я не могу представить в терминах Гейтса, как синтезируется логика. Входит ли RoundRobin в государственный реестр?
В большинстве руководств говорится, что никогда нельзя смешивать блокирующие и неблокирующие назначения. Есть ли лучший способ представить что-то вроде этого. Можно ли теперь в SV-Design смешивать оба типа присвоений, учитывая, что это блок Always_ff?
2 ответа
Никогда не следует смешивать блокирующие и неблокирующие назначения для одной и той же переменной. breakVar
является временной переменной, которая будет синтезирована в комбинаторную логику, потому что она всегда записывается сначала, а затем читается. Нет состояния для сохранения. RoundRobin
является локальной переменной, которая используется как промежуточная переменная и переменная состояния. Но поскольку доступ к нему осуществляется только из блока Always_ff, опасность возникновения гонки отсутствует.
В старые добрые времена было плохо смешивать блокирующие и неблокирующие назначения в одном и том же блоке процесса, потому что разные инструменты были несовместимы в том, как они планировали эти операции.
Новая спецификация SystemVerilog гораздо точнее о том, как упорядочить обработку этих событий, поэтому теперь можно смешивать блокирующие и неблокирующие назначения, поскольку инструменты теперь будут согласованными. Тем не мение:
Вы будете писать непонятный и сложный в обслуживании код, который заставит людей, которые смотрят на него, задавать вопросы по stackru.
Вы разозлите каждого разработчика RTL с более чем 10-летним опытом. После того, как вы были сожжены несоответствием симулятора / синтезатора, вы развиваете компульсивное отвращение к оскорбительному стилю кодирования.
Мое эмпирическое правило таково: если логика не тривиальна, выполняйте всю сложную работу в блоке always_comb, используя только блокирующие назначения. Все знают, как читать последовательный код, его можно обслуживать, и никто не будет смущен этим. Используйте отдельный процесс always_ff, чтобы ничего не делать, кроме как фиксировать переменные следующего состояния в переменные текущего состояния.
Полностью согласен с ответом Jonathan Mayer.
Вы всегда должны разделять свои логические элементы на блок always_comb и последовательные элементы в блок always_ff.
Если вы пишете код, который так тесно сшит вместе (как комбинированные, так и последовательные элементы в одном блоке), даже если он правильный и соответствует спецификации system verilog, некоторые старые версии симулятора или новые разрабатываемые имитаторы могут сделать вывод о нем неверно.
Ваш код не будет чистым и понятным для других.
Также, написав в стиле выше, вы просто уплотняете строки кода, хотя логика остается той же. Нет смысла писать компактный код, если он мешает читаемости кода.
Что касается использования блокирующих и неблокирующих операторов, я думаю, что дискуссия закрыта. Теперь использование блокирующих операторов в блоке always_comb и неблокирующих операторов в блоке always_ff является больше правилом, чем рекомендацией.
Однако ответы на все ваши вопросы объясняются в этой превосходной статье Клиффорда Э. Каммингса. Неблокирующие присваивания в Verilog Synthesis, Coding Styles That Kill!
И если вы новичок в дизайне verilog/system verilog, я предлагаю вам прочитать все их статьи. Они очень полезны и создают хорошую основу для инженера-проектировщика RTL.
Также может быть слишком много рассказывать здесь, но если вы ищете, как разделить свой код на комбинированный и последовательный блок, вы можете взглянуть на код, сгенерированный bluespec.
Названия сигналов трудно понять за один раз, но если вы внимательно посмотрите, код очень логичен и не оставляет ничего на прихоти инструментов моделирования и синтеза.