Последовательное тестирование и утверждение с помощью System-Verilog
У меня есть последовательный вывод модуля Verilog, который я хотел бы протестировать с использованием системы Verilog.
Вывод, называемый "SO", будет выводить что-то вроде 8'hC6 при условии правильного последовательного входа "SI" со значением, скажем, 8'h9A.
Существует ли простой способ кодирования / декодирования последовательных вводов-выводов без явного описания каждого сигнала?
Например:
assert property @(posedge clk) $rose(EN) |-> ##[1:3] SI ##1 !SI[*2] ##1 SI[*2] ##1 !SI ##1 SI ##1 !SI
##[1:3] SO[*2] ##1 !SO[*3] ##1 SO[*2] ##1 !SO;
Это похоже на беспорядок и едва читаемый. Я бы очень хотел просто написать
8'h9A ##[1:3] 8'hC6
но, очевидно, это не работает. Любые советы или примеры будут более чем приветствоваться. Заранее спасибо.
2 ответа
Попробуйте последовательность и обратитесь к разделу 16.10 IEEE Std 1800-2012 (Локальные переменные):
sequence seq_serial(logic signal, local logic [7:0] expected);
byte idx = 7;
(signal == expected[idx], idx--)[*8];
endsequence : seq_serial
asrt_si0x9A_so0xC6 : assert property ( @(posedge clk)
$rose(EN) |-> ##[1:3] seq_serial(SI, 8'h9A) ##[1:3] seq_serial(SO, 8'hC6) );
Это эквивалентно предоставленному утверждению и более читабельно.
Обратите внимание на local
ключевое слово, которое будет относиться expected
в качестве переменной, а не ссылки и позволяет передавать константу (например, 8'h9A
, 8'hC6
) и до сих пор позволяет вам па чистые ссылки. См. IEEE Std 1800-2012 раздел 16.8.2 (Формальные аргументы локальной переменной в объявлениях последовательности) для получения дополнительной информации.
Вот простой тестовый стенд, чтобы доказать утверждение. я веду SO
потому что у меня нет реального DUT, и я хочу продемонстрировать сценарий "с ошибками".
bit EN, clk;
logic SI,SO;
logic [7:0] si_var, so_var;
initial forever #10ns clk++; // clock generator
default clocking cb @(posedge clk); output #1ns EN,SI,SO; endclocking : cb
initial begin : test_vector
si_var = 8'h9A;
so_var = 8'hC6;
##1 cb.EN <= 1;
##($urandom_range(2,0)); // rand delay
foreach(si_var[i]) ##1 cb.SI <= si_var[i];
##($urandom_range(2,0)); // rand delay
foreach(so_var[i]) ##1 cb.SO <= so_var[i];
##1 cb.EN <= 0;
/* Now make the assertion fail */
so_var = 8'hC7; // make fail
##3 cb.EN <= 1;
##($urandom_range(2,0)); // rand delay
foreach(si_var[i]) ##1 cb.SI <= si_var[i];
##($urandom_range(2,0)); // rand delay
foreach(so_var[i]) ##1 cb.SO <= so_var[i];
##1 cb.EN <= 0;
#10ns; // little delay before finish
$finish(2);
end : test_vector
Обычно вы используете утверждения не для описания проверок элементов данных, а для контрольных сигналов. В этом случае вам нужно собрать весь входной поток в 16-битный вектор, собрать весь выходной поток и проверить, что то, что вы получили на линии SO, соответствует тому, что вы должны получить (некоторое преобразование того, что было на SI линия).
Мой SystemVerilog ржавый, но я дам вам быстрый пример того, что я имею в виду. Имейте в виду, что это не компилируется.
// collect input
always @(posedge clk) begin
if en == 1 begin
collect_input();
end
end
logic[7:0] si;
task collect_input();
for i from 0 to 7 begin
si[i] = SI; // take care of endianness here, might be si[7-i];
end
endtask
// collect output
...
logic[7:0] so;
...
collect_output();
for ...
// after collecting so, check that it's correct
if so != transform(si) begin
$error("wrong output data");
end
endtask
Надеюсь, это даст вам идею.