Добавление testbench'ей на языке Verilog в проект Vivado — различия между версиями
Korogodin (обсуждение | вклад) (→Написание TB'ей) |
Korogodin (обсуждение | вклад) (→Написание TB'ей) |
||
Строка 23: | Строка 23: | ||
Приведу один из вариантов решения подзадач, не требующий знания tcl скриптов и опирающийся по-максимуму на GUI. | Приведу один из вариантов решения подзадач, не требующий знания tcl скриптов и опирающийся по-максимуму на GUI. | ||
− | == Написание TB' | + | == Написание TB'а == |
Накидаем через GUI новый TB, а потом перенесем его в tcl-скрипт! Начнем с TB для модуля '''imichnl_synthesizer'''. | Накидаем через GUI новый TB, а потом перенесем его в tcl-скрипт! Начнем с TB для модуля '''imichnl_synthesizer'''. | ||
Строка 63: | Строка 63: | ||
Возвращаемся в настройки симуляции (''Flow Navigator -> Simulation -> Simulation Settings'') и указываем в качестве топового модуль imichnl_synthesizer_tb | Возвращаемся в настройки симуляции (''Flow Navigator -> Simulation -> Simulation Settings'') и указываем в качестве топового модуль imichnl_synthesizer_tb | ||
[[file:20160404_vivado_revolution15.png|center]] | [[file:20160404_vivado_revolution15.png|center]] | ||
+ | |||
+ | Пришло время наполнить imichnl_synthesizer_tb смысловым содержанием. Общий сброс, после чего каждую эпоху PHASE_RATE увеличивается на 2000000: | ||
+ | {{Hider|title = imichnl_synthesizer_tb.v | ||
+ | |content = <source lang="verilog"> | ||
+ | `timescale 1ns / 1ps | ||
+ | |||
+ | module imichnl_synthesizer_tb(); | ||
+ | |||
+ | reg pclk; // [in] | ||
+ | reg reset_n; | ||
+ | reg [32-1:0] phase_rate; | ||
+ | reg doinit; | ||
+ | reg fix_pulse; | ||
+ | reg dly_epoch; | ||
+ | |||
+ | wire [32-1:0] phase_rate_int; // [out] | ||
+ | wire [32-1:0] phase_int; | ||
+ | wire [32-1:0] phase_cycles_int; | ||
+ | wire [5-1:0] phase_addr; | ||
+ | |||
+ | // Генератор фазы несущей, | ||
+ | // отображает phase_rate в phase_addr | ||
+ | // по задержанной эпохе dly_epoch защелкивает счетчики циклов и фазы, а также регистр phase_rate | ||
+ | // по задержанной эпохе dly_epoch применяет записанное значение phase_rate | ||
+ | // | ||
+ | imichnl_synthesizer CHSYN ( | ||
+ | .clk (pclk), // [in] | ||
+ | .reset_n (reset_n), | ||
+ | .phase_rate (phase_rate), | ||
+ | .doinit (doinit), | ||
+ | .fix_pulse (fix_pulse), | ||
+ | .epoch_pulse (dly_epoch), | ||
+ | .phase_rate_int (phase_rate_int), // [out] | ||
+ | .phase_int (phase_int), | ||
+ | .phase_cycles_int (phase_cycles_int), | ||
+ | .phase_addr (phase_addr) | ||
+ | ); | ||
+ | |||
+ | initial begin | ||
+ | pclk = 0; | ||
+ | reset_n = 1; | ||
+ | phase_rate = 0; | ||
+ | doinit = 0; | ||
+ | fix_pulse = 0; | ||
+ | dly_epoch = 0; | ||
+ | end | ||
+ | |||
+ | always | ||
+ | #5 pclk = !pclk; | ||
+ | |||
+ | event reset; | ||
+ | event epoch; | ||
+ | event fix; | ||
+ | |||
+ | initial begin | ||
+ | forever begin | ||
+ | @ (reset) | ||
+ | @ (negedge pclk) | ||
+ | reset_n = 0; | ||
+ | @ (negedge pclk) | ||
+ | reset_n = 1; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | initial begin | ||
+ | forever begin | ||
+ | @ (epoch) | ||
+ | @ (negedge pclk) | ||
+ | dly_epoch = 1; | ||
+ | @ (negedge pclk) | ||
+ | dly_epoch = 0; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | initial begin | ||
+ | forever begin | ||
+ | @ (fix) | ||
+ | @ (negedge pclk) | ||
+ | fix_pulse = 1; | ||
+ | @ (negedge pclk) | ||
+ | fix_pulse = 0; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | initial begin: TEST_CASE | ||
+ | #10 -> reset; | ||
+ | fork // Распаралеливание блоков | ||
+ | forever begin | ||
+ | #101 -> epoch; | ||
+ | phase_rate = phase_rate + 20000000; | ||
+ | end | ||
+ | #30 | ||
+ | forever begin | ||
+ | #100 -> fix; | ||
+ | end | ||
+ | join | ||
+ | end | ||
+ | |||
+ | endmodule | ||
+ | </source> | ||
+ | |hidden = 1 | ||
+ | }} | ||
== Ссылки == | == Ссылки == |
Версия 19:13, 4 апреля 2016
|
Пусть у нас есть дизайн для Vivado, проект которого разворачивается в соответствии со статьей Vivado и Git. Возможно, это конечный дизайн, возможно - сабмодуль для другого дизайна. Процедура добавления test bench'ей (далее TB) отличаться не будет, поэтому дальнейшее рассмотрение продолжим на примере сабмодуля imitator.
Задача - добавить TB'и для модулей imitator'а, причем
- они должны храниться в СКВ и быть доступны всем разработчикам,
- имеются в виду TB'и на языке Verilog для симуляторов типа Vivado Simulator, ModelSim и т.д., а не тесты на языках Си или Matlab для Verilator'а.
Для конкретики, будем добавлять в дизайн imitator TB'и для двух модулей:
- imichnl_synthesizer, отвечающий за фазу несущей,
- imitator_channel, являющийся топ-модулем для одного канала имитатора и включающий в себя первый модуль.
Наша задача разбивается на несколько этапов:
- написать код самих TB'ей, запустить, получить результаты,
- понять, какие файлы охватывает TB,
- внести изменения в скрипт регенерации проекта так, чтобы сохранились все настройки и файлы TB.
Приведу один из вариантов решения подзадач, не требующий знания tcl скриптов и опирающийся по-максимуму на GUI.
Написание TB'а
Накидаем через GUI новый TB, а потом перенесем его в tcl-скрипт! Начнем с TB для модуля imichnl_synthesizer.
В Flow Navigator (это панель слева в Vivado) в разделе Simulation выбираем Simulation Settings
В открывшемся окне в разделе Simulation в графе Simulation top modulw name создаем новый файлсет, выбирая Create Simulation Set
ВНИМАНИЕ Не занимайте и не удаляйте файлсет sim_1. Vivado его очень любит и будет создавать заново, делая при этим активным. Лучше оставить sim_1 пустым.
Новому файлсету даем осмысленное название, например, sim_imichnl_synthesizer
Очищаем графу Simulation top module name, т.к. файл с кодом TB'а у нас ещё не создан.
На вкладке Advanced запрещаем включать в TB все файлы проекта, снимая галку с Include all design sources for simulation. Иначе он добавит все наши файлы в файлсет этого TB'а, что нам не нужно.
Закрываем окно, нажимая Ok. Vivado задает вопрос, сделать ли данный TB активным. Можно соглашаться. В итоге в Source проекта появился новый пустой файлсет для симуляции sim_imichnl_synthesizer
В контекстном меню файлсета sim_imichnl_synthesizer, выпадающем при нажатии правой кнопкой мыши, выбираем добавление новых файлов Add Sources
Далее Add or create simulation sources
Добавляем новый файл TB'а, нажимая кнопку Create File в открывшемся окне. Даем файлу осмысленное имя с суффиксом _tb, например, imichnl_synthesizer_tb.v и обязательно указываем в качестве пути каталог tb дизайна imitator. Иначе он будет создан в дебрях песочницы (в prj_imitator) и не будет виден системе контроля версий.
С помощью кнопки Add Files добавляем уже существующие файлы, которые потребуются для работы тестируемого модуля. В данном случае это сам модуль imichnl_synthesizer из каталога verilog
После добавления требуемых файлов нажимаем кнопку Finish. Открывается окно Define module для нашего TB'а imichnl_synthesizer_tb.v. Порты нам добавлять не нужно, просто нажимаем Ok. Теперь у нас в файлсете sim_imichnl_synthesizer два файла - код исследуемого модуля и код TB'а.
Возвращаемся в настройки симуляции (Flow Navigator -> Simulation -> Simulation Settings) и указываем в качестве топового модуль imichnl_synthesizer_tb
Пришло время наполнить imichnl_synthesizer_tb смысловым содержанием. Общий сброс, после чего каждую эпоху PHASE_RATE увеличивается на 2000000:
module imichnl_synthesizer_tb();
reg pclk; // [in]
reg reset_n;
reg [32-1:0] phase_rate;
reg doinit;
reg fix_pulse;
reg dly_epoch;
wire [32-1:0] phase_rate_int; // [out]
wire [32-1:0] phase_int;
wire [32-1:0] phase_cycles_int;
wire [5-1:0] phase_addr;
// Генератор фазы несущей,
// отображает phase_rate в phase_addr
// по задержанной эпохе dly_epoch защелкивает счетчики циклов и фазы, а также регистр phase_rate
// по задержанной эпохе dly_epoch применяет записанное значение phase_rate
//
imichnl_synthesizer CHSYN (
.clk (pclk), // [in]
.reset_n (reset_n),
.phase_rate (phase_rate),
.doinit (doinit),
.fix_pulse (fix_pulse),
.epoch_pulse (dly_epoch),
.phase_rate_int (phase_rate_int), // [out]
.phase_int (phase_int),
.phase_cycles_int (phase_cycles_int),
.phase_addr (phase_addr)
);
initial begin
pclk = 0;
reset_n = 1;
phase_rate = 0;
doinit = 0;
fix_pulse = 0;
dly_epoch = 0;
end
always
#5 pclk = !pclk;
event reset;
event epoch;
event fix;
initial begin
forever begin
@ (reset)
@ (negedge pclk)
reset_n = 0;
@ (negedge pclk)
reset_n = 1;
end
end
initial begin
forever begin
@ (epoch)
@ (negedge pclk)
dly_epoch = 1;
@ (negedge pclk)
dly_epoch = 0;
end
end
initial begin
forever begin
@ (fix)
@ (negedge pclk)
fix_pulse = 1;
@ (negedge pclk)
fix_pulse = 0;
end
end
initial begin: TEST_CASE
#10 -> reset;
fork // Распаралеливание блоков
forever begin
#101 -> epoch;
phase_rate = phase_rate + 20000000;
end
#30
forever begin
#100 -> fix;
end
join
end
endmodule