Перейти к содержанию
    

verilog: что должно считаться update event-ом?

Столкнулся со странной особенностью Верилога в Active-HDL 9.1. Если симулировать следующий код, то он зациклится:

reg t1=1'b0,t2=1'b0;
always @(t1) begin
  t2 = 1'b1;
  if(!t1)begin
    t2 = 1'b0;
  end
end  
always @(t2) begin
  t1 = 1'b1;
  if(!t2)begin
    t1 = 1'b0;
  end
end

Несмотря на то, что по завершении каждого always процесса, и t1 и t2 сохраняют своё прежнее значение, симулятор считает промежуточное присваивание другого значения достаточным основанием для update event. Попробовал почитать на эту тему стандарт, ясных разъяснений не нашёл. По-моему, это какая-то дичь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

23 minutes ago, Timmy said:

...

Несмотря на то, что по завершении каждого always процесса, и t1 и t2 сохраняют своё прежнее значение, симулятор считает промежуточное присваивание другого значения достаточным основанием для update event. 

...

Кто вам сказал такое?  Вы применяете blocking присвоение (=) а значит значение переменной меняется сразу же!  A не в конце блока always как при использовании nonblocking (<=).

Удачи! Rob

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А Вы хотите реализовать какую-то логику или исследовать поведение симулятора?

 

Если первое, то не очень понятно, какого результата Вы хотите добиться. Похоже на попытку описать асинхронный мультивибратор. ( :

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, RobFPGA said:

Приветствую!

Кто вам сказал такое?  Вы применяете blocking присвоение (=) а значит значение переменной меняется сразу же!  A не в конце блока always как при использовании nonblocking (<=).

Удачи! Rob

Открою страшную тайну: при использовании <= будет та же самая проблема. Вот ещё код попроще:

reg t=1'b0;
always begin
  @(t);
  t <= 1'b1;
  t <= 1'b0;
end

То есть update flag регистру всегда устанавливается немедленно, если присваивается значение, отличное от текущего. А когда неблокирующим присваиваиванием присваивается значение, равное текущему видимому, update flag уже не сбрасывается :-). И это может внезапно привести к проблемам. Для решения пришлось завести локальный промежуточный регистр и присваивать его "глобальному" регистру в конце always блока.

Я удивлён, что регистры Верилога вообще имеют update flag, это как-то VHDL-ем попахивает :-).

К счастью, на практике ситуация крайне редкая, я вот первый раз столкнулся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А давайте еще обсудим проблему о том, что получится если одновременно подать активный уровень и на R и на S входы в RS-триггере и при этом так же будем клясть верилог...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

 

Да уж - последовательность обработки событий в симуляторе та еще интересная задачка.

Сделал вот такой простой тест

`timescale 1ns/1ps

module event_test;
initial $timeformat(-9, 0, " ns", 10);

logic t1,t2;

always @(t1) begin
  $display("[%t]: T1.0: t1:%b, t2:%b",$time(), t1, t2);
end

always @(t2) begin
  $display("[%t]: T2.0: t1:%b, t2:%b",$time(), t1, t2);
end

always @(t1) begin
  $display("[%t]: T1.1: t1:%b, t2:%b",$time(), t1, t2);
  t2 = 1'b0;
  $display("[%t]: T1.2: t1:%b, t2:%b",$time(), t1, t2);
  // #0;
  t2 = 1'b1;
  $display("[%t]: T1.3: t1:%b, t2:%b",$time(), t1, t2);
  // #0;
  t2 = 1'bz;
  $display("[%t]: T1.4: t1:%b, t2:%b",$time(), t1, t2);
end

initial begin
  $display("[%t]: T0.0: t1:%b, t2:%b",$time(), t1, t2);
  #1;
  t1=0;
end

endmodule

 Если запустить как есть то получим  ожидаемый вывод (Questasim v10.6c)

# [      0 ns]: T0.0: t1:x, t2:x
# [      1 ns]: T1.0: t1:0, t2:x
# [      1 ns]: T1.1: t1:0, t2:x
# [      1 ns]: T1.2: t1:0, t2:0
# [      1 ns]: T1.3: t1:0, t2:1
# [      1 ns]: T1.4: t1:0, t2:z
# [      1 ns]: T2.0: t1:0, t2:z

 

event list: ("@time_ps  +#delta_cycle)  

@0      +0
/event_test/t1 1'hx
/event_test/t2 1'hx
@1000 +0
/event_test/t1 1'h0
@1000 +1
/event_test/t2 1'hz 

 

То есть последовательные присвоение одной переменной в блоке always происходит в одном delta_cycle (вроде так и пишут в доках). А вот обработка события изменения этой переменной происходит по окончанию delta_cycle. Что подтверждает вывод сима варианта с убранными комментариями возле #0; (искусственно добавляем delta_cycle).

 

# [      0 ns]: T0.0: t1:x, t2:x
# [      1 ns]: T1.0: t1:0, t2:x
# [      1 ns]: T1.1: t1:0, t2:x
# [      1 ns]: T1.2: t1:0, t2:0
# [      1 ns]: T2.0: t1:0, t2:0
# [      1 ns]: T1.3: t1:0, t2:1
# [      1 ns]: T2.0: t1:0, t2:1
# [      1 ns]: T1.4: t1:0, t2:z
# [      1 ns]: T2.0: t1:0, t2:z

 

event list:

@0      +0
/event_test/t1 1'hx
/event_test/t2 1'hx
@1000 +0
/event_test/t1 1'h0
@1000 +1
/event_test/t2 1'h0
@1000 +2
/event_test/t2 1'h1
@1000 +3
/event_test/t2 1'hz

 

Удачи! Rob.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...