«Работать добросовестно — значит: работать, повышая свою квалификацию, проявляя инициативу в совершенствовании продукции, технологий, организации работ, оказывая не предусмотренную должностными инструкциями помощь другим сотрудникам (включая и руководителей) в общей им всем работе.

Спец курс (Верификация цифровых схем)/Практические задания 3 — различия между версиями

Материал из Wiki
Перейти к: навигация, поиск
(Шаг 1. Создание интерфейса)
 
(не показаны 18 промежуточных версий 1 участника)
Строка 1: Строка 1:
 
{{ВЦС_TOC}}
 
{{ВЦС_TOC}}
 
= Общие для всех вариантов шаги лаб 3 =
 
= Общие для всех вариантов шаги лаб 3 =
 +
 
== Шаг 0. Создание класса транзакции  ==
 
== Шаг 0. Создание класса транзакции  ==
 
# Создать описание класса seq_item.
 
# Создать описание класса seq_item.
 
# Класс должен содержать битовое поле data
 
# Класс должен содержать битовое поле data
 +
 
== Шаг 1. Создание интерфейса ==
 
== Шаг 1. Создание интерфейса ==
# Объявить интерфейс, который содержит тактовый сигнал clk, сигнал сброса rst, и сигнал data.
+
# В отдельном файле my_vif.sv объявить интерфейс с имененем типа my_vif, который в списке входных портов содержит тактовый сигнал clk, сигнал сброса rst, и сигнал data. (все сигналы однобитные)
# Создать модуль и в нем инстанциировать интерфейс
+
# Создать модуль с именем top в файле top.sv.
# Объявить переменную типа reg по имени clk_i, rst_i.
+
# Используя `include "my_vif.sv" подключить интерфейс в самом начале файла top.sv.
 +
# В top модуле инстанциировать интерфейс vif (my_vif vif (.clk(....), ......)).
 +
# Объявить две переменные типа reg по имени clk_i, rst_i.
 
# В initial блоке создать генератор тактового сигнала и сброса используя, переменные clk_i, rst_i;
 
# В initial блоке создать генератор тактового сигнала и сброса используя, переменные clk_i, rst_i;
# Подключить сигналы clk_i, rst_i к интерфейсу.
+
## initial forever clk_i = ~ clk_i;
 +
## initial clk_i = 0;
 +
## initial begin rst_i <=0; # 40 ns; rst_i<= 1; end
 +
# Подключить сигналы генератора тактового сигнала и сброса к соответствующим сигналам clk_i, rst_i в интерфейсе.
  
== Шаг 2. Создание класса конвертации транзакции и воздействия на проводном интерфейсе ==
+
== Шаг 2. Создание класса конвертации транзакции в воздействие на проводном интерфейсе ==
# Создать класс с названием driver_t.
+
# Создать класс с названием driver_t в отдельном файле driver_t.sv.
# В классе объявить переменную типа virtual interface vif.
+
# В классе объявить переменную типа virtual my_vif vif.
 
# Объявить переменную типа seq_item item1;
 
# Объявить переменную типа seq_item item1;
 
# Объявить event get_next_item_e;
 
# Объявить event get_next_item_e;
# Реализовать virtual task mrun_phase в этом классе.
+
# Реализовать таск virtual task mrun_phase() в этом классе.
## Таск должен содержать бесконечный цикл, который ожидает события get_next_item_e.  
+
## Таск должен содержать бесконечный цикл forever, который ожидает события get_next_item_e.  
## После получения события класс должен ожидать события posedge на сигнале clk (на интерфейсе)
+
## После получения ожидаем события posedge на сигнале clk (из интерфейса @(posedge vif.clk))
## После брать значения из объекта транзакции item1.data и назначать на сигнал интерфейса vif.data
+
## После берем значения из объекта транзакции item1.data и назначаем на сигнал интерфейса vif.data
 +
## Цикл повторяется
  
 
== Шаг 3. Запуск и проверка конвертации ==
 
== Шаг 3. Запуск и проверка конвертации ==
# Создать объект в модуле, объявленном в предыдущем задании.
+
# Подключить файл класса в top.sv файле после подключения интерфейса (`include "driver_t.sv")
# Передать указатель на интерфейс в объект driver
+
# Объявить и создать объект driver типа driver_t в top модуле (driver_t driver = new (); ),  
# Запустить task mrun_phase
+
# Передать указатель на интерфейс в объект driver. (driver.vif = vif;)
# Создать в модуле класс транзакции, содержащий поле rand test, передать указатель на транзакцию в класс driver.
+
# Запустить task mrun_phase из обьекта driver. (driver.mrun_phase();)
# Вызвать триггер для события get_next_item_e.
+
# Создать в top модуле класс транзакции item, объявленной на шаге 0 (seq_item item = new(); ).
# Повторить генерацию транзакций 10 раз со случайным интервалом от 1 до 10 us.
+
# Передать указатель на транзакцию в объект driver класса driver_t (driver.item = item; ).
 +
# Вызвать триггер для события get_next_item_e. ( -> driver.get_next_item_e ;)
 +
# Повторить в цикле генерацию транзакций 10 раз.
 +
# Пауза между генерацией каждой транзакции должна выбираться случайным образом в интервале от 1 до 10 us.
 +
# Если выполняете задание на https://www.edaplayground.com, то добавить конструкцию сохранения временных диаграмм.
 +
## 
 +
    //enabling the wave dump
 +
    initial begin
 +
      $dumpfile("dump.vcd");
 +
      $dumpvars;
 +
    end
 +
# Убедиться, что переключения отображаются на интерфейсе.  
  
 
== Шаг 4. Создание класса, получения транзакции с проводного интерфейса ==
 
== Шаг 4. Создание класса, получения транзакции с проводного интерфейса ==
# Создать класс с названием monitor_t.
+
# Создать класс с названием monitor_t в отдельном файле (monitor_t.sv).
# В классе объявить переменную типа virtual interface.
+
# В классе объявить переменную типа virtual my_vif vif.
# Реализовать virtual task mrun_phase  в этом классе. Должен содержать бесконечный цикл. После получения события класс должен ожидать события posedge на сигнале clk (на интерфейсе), после брать значение сигнала test из интерфейса, помещать его в транзакцию и печатать транзакцию в консоль.
+
# Объявить переменную типа seq_item item_collect;
 +
# Реализовать таск virtual task mrun_phase () в этом классе.  
 +
## Таск Должен содержать бесконечный цикл forever.  
 +
## В цикле ожидаем события posedge на сигнале clk (@(posedge vif.clk);)
 +
## Создаем объект item_collect (item_collect = new();)
 +
## В цикле ожидаем события posedge на сигнале clk из интерфейса (@(posedge vif.clk);)
 +
## После события берем значение сигнала data из интерфейса, помещаем его значение в поле data транзакции (item_collect.data = vif.data);
 +
## Печатаем содержимое транзакции в консоль ($display ("TR data: %b", item_collect.data);).
  
 
== Шаг 5. Запуск монитора ==
 
== Шаг 5. Запуск монитора ==
# Создать класс монитора в топ модуле
+
# Подключить файл класса monitor в top.sv файле после подключения драйвера (`include "monitor_t.sv")
# Передать в класс ссылку на интерфейс
+
# Объявить и создать объект monitor класса monitor_t в top модуле (monitor_t monitor = new() ;)
# Запустить в топ модуле task mrun_phase
+
# Передать указатель на интерфейс в объект monitor. (monitor.vif = vif;)
 +
# Запустить в топ модуле task mrun_phase ();
 +
# Убедиться, что 10 транзакций, которые мы отправили, были получены монитором и напечатаны в лог.
  
== Шаг 6. класс Agent ==
+
== Шаг 6. Создание класса Agent ==
 
# Создать класс Agent_t
 
# Создать класс Agent_t
# В классе должны создаваться объекты monitor, driver.
+
# Объявить и создать объект monitor типа monitor_t в классе agent_t (monitor_t monitor = new() ;)
# В классе реализовать virtual task mrun_phase, в котором запускаются task mrun_phase из классов monitor,driver.
+
# Объявить и создать объект driver типа driver_t в классе agent_t (driver_t driver = new (); )
# В классе объявить переменную virtual interface, cссылка на интерфейс должна пробрасываться в драйвер и монитор
+
# Реализовать таск virtual task mrun_phase ()  в этом классе, в котором запускаются mrun_phase из классов monitor,driver.
# Создать класс Agent в топ модуле
+
# В классе объявить переменную virtual my_vif vif
# Передать в класс ссылку на интерфейс
+
# В mrun_phase передать ссылку на интерфейс должна в драйвер и монитор (driver.vif=vif; monitor.vif=vif;)
# Запустить в топ модуле task mrun_phase: в результате в логе должна наблюдаться печать транзакций
+
  
== Шаг 7. Наследуемся от UVM ==
+
== Шаг 7. Подлкючаем агент в top модуле ==
 +
# Подключить файл класса agent в top.sv файле после подключения монитора (`include "agent_t.sv")
 +
# Обьявить указатель agent типа agent_t в top модуле (agent_t agent;)
 +
# Создать объект класса agent_t в top модуле; (intial begin agent = new(); end)
 +
# Передать в объект agent ссылку на интерфейс (agent.vif = vif;)
 +
# Запустить в task mrun_phase из объекта agent. (agent.mrun_phase())
 +
 
 +
== Шаг 8. Использование монитора и драйвера из агента (Аналогично шаг 1,3,5) ==
 +
# В top модуле инстанциировать еще один интерфейс vifa (my_vif vifa (.clk(....), ......)) и подключить сигналы сброса и такстирования.
 +
# Передать указатель на интерфейс в объект agent. (agent.vif = vifa;)
 +
# Создать в top модуле класс транзакции item_a, объявленной на шаге 0 (seq_item item_a = new(); ).
 +
# Передать указатель на транзакцию в объект driver из обьекта agent (agent.driver.item = item; ).
 +
# Вызвать триггер для события get_next_item_e. ( -> agent.driver.get_next_item_e ;)
 +
# Повторить в цикле генерацию транзакций 10 раз.
 +
# Пауза между генерацией каждой транзакции должна выбираться случайным образом в интервале от 1 до 10 us.
 +
# Убедиться, что переключения отображаются на интерфейсе.
 +
# Убедиться, что 10 транзакций, которые мы отправили, были получены монитором и напечатаны в лог.
 +
 
 +
= Общие для всех вариантов шаги лаб 3 при переходе к UVM =
 +
 
 +
== Шаг 1. Наследуемся от UVM ==
 
# Создать класс my_driver_t, наследуемый от uvm_driver
 
# Создать класс my_driver_t, наследуемый от uvm_driver
 
# Функционал класса driver_t перенести в  my_driver_t  
 
# Функционал класса driver_t перенести в  my_driver_t  
Строка 54: Строка 101:
 
# Функционал класса monitor_t перенести в  my_monitor_t  
 
# Функционал класса monitor_t перенести в  my_monitor_t  
 
# Создать класс my_agent_t, наследуемый от uvm_agent
 
# Создать класс my_agent_t, наследуемый от uvm_agent
# Функционал класса agent_t перенести в  my_agent_t  
+
# Функционал класса agent_t перенести в  my_agent_t
 +
# В каждом из описанных шагов дополнительно
 +
## Переопределить конструктор
 +
## Поменять конструктор в точке вызова (передать строковый параметр - имя модуля, и указатель на компонент создающий данный объект)
 +
### при вызове конструктора в топ модуле вторым параметром можно использовать uvm_root::get()
 +
## Добавить макросы регистрации класса
 +
## В каждом описанном классе добавить описание 2 функций
 +
### function void build_phase (uvm_phase phase)
 +
### function void connect_phase (uvm_phase phase)
 +
## В каждом описанном классе добавить описание 1 дополнительного таска
 +
### task run_phase (uvm_phase phase)
  
== Шаг 8. Сиквенс ==
+
== Шаг 2. Сиквенсер ==
 +
# Создать класс наследуемый от uvm_sequencer
 +
## Добавить регистрацию класса в фабрике с помощью макроса
 +
== Шаг 3.0 Агент ==
 +
# Добавить регистрацию класса в фабрике с помощью макроса
 +
# В классе агента объявить указатели на драйвер и монитор
 +
#  Перенести создание объектов драйвера и монитора в build_phase агента из топ модуля
 +
## не забудьте поменять второй параметр конструктора (uvm_root::get() -> this);
 +
## при создании используйте new() или create()
 +
 
 +
== Шаг 3. Соединить драйвер и сиквенсер ==
 +
# В классе агента в методе connect_phase соединить встроенные в драйвер и сиквенсер порты seq_item_port и seq_item_export
 +
 
 +
== Шаг 4. Сиквенс ==
 
# Создать класс наследуемый от uvm_sequence
 
# Создать класс наследуемый от uvm_sequence
# Реализовать метод класса body
+
# Реализовать метод класса body ()
## создать транзакцию tr
+
## объявить указатель на транзакцию tr
 +
## создать транзакцию tr  
 
## вызывать метод класса start_item(tr);
 
## вызывать метод класса start_item(tr);
 
## вызвать tr.randomize() для объекта транзакции;
 
## вызвать tr.randomize() для объекта транзакции;
Строка 65: Строка 136:
 
# повторить перечисленные выше действия 10 раз;
 
# повторить перечисленные выше действия 10 раз;
  
== Шаг 9. Сиквенсер ==
+
== Шаг 5. Заменить вывод сообщений на UVM INFO макросы ==
# Создать класс наследуемый от uvm_sequencer
+
 
== Шаг 10. Тест/Окружение ==
+
== Шаг 6. Соединить интерфейс , драйвер , монитор  ==
 +
# В топ модуле после создания интерфейса реализовать initial begin end
 +
## В блоке begin end вызвать метод помещающий интерфейс в базу конфигурации
 +
## uvm_config_db#(virtual interface):: set (null, "*", "vif", vif); 
 +
# В дравере и мониторе в build_phase таск добавить вызов метода получающего указатель на интерфейс из базы конфигурации
 +
## uvm_config_db#(virtual interface):: get (this, "", "vif", vif);
 +
 
 +
== Шаг 7. Тест/Окружение ==
 
#Создать класс наследуемый от uvm_test с именем my_uvm_test
 
#Создать класс наследуемый от uvm_test с именем my_uvm_test
#Реализовать build_phase метод этого класса
+
#Реализовать метод build_phase этого класса
 
##Создание объекта агента
 
##Создание объекта агента
 
##Создание объекта сиквенсы
 
##Создание объекта сиквенсы
#Реализовать run_phase теста
+
#Реализовать run_phase теста :
## Поднят объект управления
+
## Поднять объект управления (raise_objection)
 +
## Запустить сиквенс на сиквенсере использую метод start()
 +
## Снять объект управления (drop_objection)
 +
 
 +
== Шаг 8. Запустить тест на выполнение  ==
 +
# В топ модуле после создания интерфейса реализовать initial begin end
 +
## В блоке begin end вызвать метод run_test ("my_uvm_test"); my_uvm_test - имя, которые вы дали классу теста.
  
 
= Как выбрать вариант =
 
= Как выбрать вариант =

Текущая версия на 20:31, 3 июля 2020

Лекции ВЦС

Лекции

Практические задания
Тесты

Табель успеваемости

Экзамен

Доп. материалы

Содержание

Общие для всех вариантов шаги лаб 3

Шаг 0. Создание класса транзакции

  1. Создать описание класса seq_item.
  2. Класс должен содержать битовое поле data

Шаг 1. Создание интерфейса

  1. В отдельном файле my_vif.sv объявить интерфейс с имененем типа my_vif, который в списке входных портов содержит тактовый сигнал clk, сигнал сброса rst, и сигнал data. (все сигналы однобитные)
  2. Создать модуль с именем top в файле top.sv.
  3. Используя `include "my_vif.sv" подключить интерфейс в самом начале файла top.sv.
  4. В top модуле инстанциировать интерфейс vif (my_vif vif (.clk(....), ......)).
  5. Объявить две переменные типа reg по имени clk_i, rst_i.
  6. В initial блоке создать генератор тактового сигнала и сброса используя, переменные clk_i, rst_i;
    1. initial forever clk_i = ~ clk_i;
    2. initial clk_i = 0;
    3. initial begin rst_i <=0; # 40 ns; rst_i<= 1; end
  7. Подключить сигналы генератора тактового сигнала и сброса к соответствующим сигналам clk_i, rst_i в интерфейсе.

Шаг 2. Создание класса конвертации транзакции в воздействие на проводном интерфейсе

  1. Создать класс с названием driver_t в отдельном файле driver_t.sv.
  2. В классе объявить переменную типа virtual my_vif vif.
  3. Объявить переменную типа seq_item item1;
  4. Объявить event get_next_item_e;
  5. Реализовать таск virtual task mrun_phase() в этом классе.
    1. Таск должен содержать бесконечный цикл forever, который ожидает события get_next_item_e.
    2. После получения ожидаем события posedge на сигнале clk (из интерфейса @(posedge vif.clk))
    3. После берем значения из объекта транзакции item1.data и назначаем на сигнал интерфейса vif.data
    4. Цикл повторяется

Шаг 3. Запуск и проверка конвертации

  1. Подключить файл класса в top.sv файле после подключения интерфейса (`include "driver_t.sv")
  2. Объявить и создать объект driver типа driver_t в top модуле (driver_t driver = new (); ),
  3. Передать указатель на интерфейс в объект driver. (driver.vif = vif;)
  4. Запустить task mrun_phase из обьекта driver. (driver.mrun_phase();)
  5. Создать в top модуле класс транзакции item, объявленной на шаге 0 (seq_item item = new(); ).
  6. Передать указатель на транзакцию в объект driver класса driver_t (driver.item = item; ).
  7. Вызвать триггер для события get_next_item_e. ( -> driver.get_next_item_e ;)
  8. Повторить в цикле генерацию транзакций 10 раз.
  9. Пауза между генерацией каждой транзакции должна выбираться случайным образом в интервале от 1 до 10 us.
  10. Если выполняете задание на https://www.edaplayground.com, то добавить конструкцию сохранения временных диаграмм.
   //enabling the wave dump
   initial begin 
      $dumpfile("dump.vcd"); 
      $dumpvars;
   end
  1. Убедиться, что переключения отображаются на интерфейсе.

Шаг 4. Создание класса, получения транзакции с проводного интерфейса

  1. Создать класс с названием monitor_t в отдельном файле (monitor_t.sv).
  2. В классе объявить переменную типа virtual my_vif vif.
  3. Объявить переменную типа seq_item item_collect;
  4. Реализовать таск virtual task mrun_phase () в этом классе.
    1. Таск Должен содержать бесконечный цикл forever.
    2. В цикле ожидаем события posedge на сигнале clk (@(posedge vif.clk);)
    3. Создаем объект item_collect (item_collect = new();)
    4. В цикле ожидаем события posedge на сигнале clk из интерфейса (@(posedge vif.clk);)
    5. После события берем значение сигнала data из интерфейса, помещаем его значение в поле data транзакции (item_collect.data = vif.data);
    6. Печатаем содержимое транзакции в консоль ($display ("TR data: %b", item_collect.data);).

Шаг 5. Запуск монитора

  1. Подключить файл класса monitor в top.sv файле после подключения драйвера (`include "monitor_t.sv")
  2. Объявить и создать объект monitor класса monitor_t в top модуле (monitor_t monitor = new() ;)
  3. Передать указатель на интерфейс в объект monitor. (monitor.vif = vif;)
  4. Запустить в топ модуле task mrun_phase ();
  5. Убедиться, что 10 транзакций, которые мы отправили, были получены монитором и напечатаны в лог.

Шаг 6. Создание класса Agent

  1. Создать класс Agent_t
  2. Объявить и создать объект monitor типа monitor_t в классе agent_t (monitor_t monitor = new() ;)
  3. Объявить и создать объект driver типа driver_t в классе agent_t (driver_t driver = new (); )
  4. Реализовать таск virtual task mrun_phase () в этом классе, в котором запускаются mrun_phase из классов monitor,driver.
  5. В классе объявить переменную virtual my_vif vif
  6. В mrun_phase передать ссылку на интерфейс должна в драйвер и монитор (driver.vif=vif; monitor.vif=vif;)

Шаг 7. Подлкючаем агент в top модуле

  1. Подключить файл класса agent в top.sv файле после подключения монитора (`include "agent_t.sv")
  2. Обьявить указатель agent типа agent_t в top модуле (agent_t agent;)
  3. Создать объект класса agent_t в top модуле; (intial begin agent = new(); end)
  4. Передать в объект agent ссылку на интерфейс (agent.vif = vif;)
  5. Запустить в task mrun_phase из объекта agent. (agent.mrun_phase())

Шаг 8. Использование монитора и драйвера из агента (Аналогично шаг 1,3,5)

  1. В top модуле инстанциировать еще один интерфейс vifa (my_vif vifa (.clk(....), ......)) и подключить сигналы сброса и такстирования.
  2. Передать указатель на интерфейс в объект agent. (agent.vif = vifa;)
  3. Создать в top модуле класс транзакции item_a, объявленной на шаге 0 (seq_item item_a = new(); ).
  4. Передать указатель на транзакцию в объект driver из обьекта agent (agent.driver.item = item; ).
  5. Вызвать триггер для события get_next_item_e. ( -> agent.driver.get_next_item_e ;)
  6. Повторить в цикле генерацию транзакций 10 раз.
  7. Пауза между генерацией каждой транзакции должна выбираться случайным образом в интервале от 1 до 10 us.
  8. Убедиться, что переключения отображаются на интерфейсе.
  9. Убедиться, что 10 транзакций, которые мы отправили, были получены монитором и напечатаны в лог.

Общие для всех вариантов шаги лаб 3 при переходе к UVM

Шаг 1. Наследуемся от UVM

  1. Создать класс my_driver_t, наследуемый от uvm_driver
  2. Функционал класса driver_t перенести в my_driver_t
  3. Создать класс my_monitor_t, наследуемый от uvm_monitor
  4. Функционал класса monitor_t перенести в my_monitor_t
  5. Создать класс my_agent_t, наследуемый от uvm_agent
  6. Функционал класса agent_t перенести в my_agent_t
  7. В каждом из описанных шагов дополнительно
    1. Переопределить конструктор
    2. Поменять конструктор в точке вызова (передать строковый параметр - имя модуля, и указатель на компонент создающий данный объект)
      1. при вызове конструктора в топ модуле вторым параметром можно использовать uvm_root::get()
    3. Добавить макросы регистрации класса
    4. В каждом описанном классе добавить описание 2 функций
      1. function void build_phase (uvm_phase phase)
      2. function void connect_phase (uvm_phase phase)
    5. В каждом описанном классе добавить описание 1 дополнительного таска
      1. task run_phase (uvm_phase phase)

Шаг 2. Сиквенсер

  1. Создать класс наследуемый от uvm_sequencer
    1. Добавить регистрацию класса в фабрике с помощью макроса

Шаг 3.0 Агент

  1. Добавить регистрацию класса в фабрике с помощью макроса
  2. В классе агента объявить указатели на драйвер и монитор
  3. Перенести создание объектов драйвера и монитора в build_phase агента из топ модуля
    1. не забудьте поменять второй параметр конструктора (uvm_root::get() -> this);
    2. при создании используйте new() или create()

Шаг 3. Соединить драйвер и сиквенсер

  1. В классе агента в методе connect_phase соединить встроенные в драйвер и сиквенсер порты seq_item_port и seq_item_export

Шаг 4. Сиквенс

  1. Создать класс наследуемый от uvm_sequence
  2. Реализовать метод класса body ()
    1. объявить указатель на транзакцию tr
    2. создать транзакцию tr
    3. вызывать метод класса start_item(tr);
    4. вызвать tr.randomize() для объекта транзакции;
    5. вызвать метод класса finish_item();
  3. повторить перечисленные выше действия 10 раз;

Шаг 5. Заменить вывод сообщений на UVM INFO макросы

Шаг 6. Соединить интерфейс , драйвер , монитор

  1. В топ модуле после создания интерфейса реализовать initial begin end
    1. В блоке begin end вызвать метод помещающий интерфейс в базу конфигурации
    2. uvm_config_db#(virtual interface):: set (null, "*", "vif", vif);
  2. В дравере и мониторе в build_phase таск добавить вызов метода получающего указатель на интерфейс из базы конфигурации
    1. uvm_config_db#(virtual interface):: get (this, "", "vif", vif);

Шаг 7. Тест/Окружение

  1. Создать класс наследуемый от uvm_test с именем my_uvm_test
  2. Реализовать метод build_phase этого класса
    1. Создание объекта агента
    2. Создание объекта сиквенсы
  3. Реализовать run_phase теста :
    1. Поднять объект управления (raise_objection)
    2. Запустить сиквенс на сиквенсере использую метод start()
    3. Снять объект управления (drop_objection)

Шаг 8. Запустить тест на выполнение

  1. В топ модуле после создания интерфейса реализовать initial begin end
    1. В блоке begin end вызвать метод run_test ("my_uvm_test"); my_uvm_test - имя, которые вы дали классу теста.

Как выбрать вариант

Bombilla amarilla - yellow Edison lamp.pngДля задания 1 варианты выбираются согласно табелю успеваемости.

Например: если вариант 3.2 - это значит что необходимо разработать транзакцию SPI без использования UVM макросов.

Спецификации

  1. APB
  2. UART
  3. SPI

Задание

  1. По спецификации интерфейса (*) блока разработать транзакцию, позволяющую описать все доступные операции на заданном интерфейсе:
    1. с использованием UVM макросов.
    2. без использования UVM макросов.
  2. Создать пакет, реализующий весь функционал агента (сиквенсер, драйвер, монитор) из существующих файлов описания всех составных блоков и скомпилировать его. (Можно использовать файлы из проекта https://www.edaplayground.com/x/3ru7)
  3. Реализовать объект конфигурации агента, который содержит методы настройки в три режима: по умолчанию активный ведущий, пассивный, активный ведомый режимы

Дополнительно

  1. Реализовать фазу сброса в драйвере
  2. Реализовать фазу, предшествующую фазе сброса
  3. Подменить драйвер в агенте, из окружения в фазе создания компонент
  4. Создать домен фазы выполнения для агента и подключить агент к этому домену

Спецификация APB интерфейса

  • IHI0024C_amba_apb_protocol_spec.pdf

Спецификация CSR интерфейса

Спецификация UART интерфейса

Спецификация SPI интерфейса