Jump to content
    

Clocking block in SystemVerilog

Начну с конца.

Мне нравится при стимуляциях когда выходные сигналы появляются не по фронту клока, а чуть позже - это увеличивает читаемость. Плюс потенциальная возможность увеличить широту проверок вводя всякого рода задержки в шинах, например можно симулировать разбежку данных в шине при сопряжении частот.

Это можно делать руками и снаружи интерфейса, но мне кажется что именно для этого и сделан код блок, и хочется его загнать в интерфейс чтобы получить собранный реюзный кусок.

 

Так что в итоге это академическая задача образовательного толка, хочется понять как оно правильно используется, потому что реально все немного не очевидно.

 

По поводу ссылки, спасибо я прочел, тут у меня тоже есть уточняющий вопрос, здорово если вы ответите:

Я обычно интерфейсы с тасками работы пихал в параметризированные классы драйверов, мне казалось это удобнее, в одном месте объявляю экземпляр класса драйвера и интерфейс с одинаковыми параметрами.

Что дает предложенный подход? Как я понимаю он позволяет не передавать в класс параметры интерфейса не связанные с работой класса, то есть класс потенциально может иметь меньше параметров чем интерфейс.

Есть еще какие-то бонусы?

 

Еще важный вопрос, вы можете подключать к модулям сигналы cb.data, объявленные в клок блоке как output просто напрямую, типа my_module(.data(cb.data), ...)? Это точно?

Моя среда меня с этой идеей послала, сказала клоковый сигнал надо драйвить клоково. То есть подключение сигнала к порту среда воспринимает как assign, а для клокового оутпута

assign недопустим, приходиться делать wire подключенный к порту и дополнительный always @* в котором его пихать через <= в клоковый сигнал, тогда работает.

 

 

В целом на сегодня у меня практически сложилась картина, сейчас найду время проверить правильность понимания и может все будет хорошо.:)

 

Кроме того, что в класс можно не передавать необходимые только для итерфейса параметры, появляется возможножсть использовать на полную полиморфизм и наследование классов. Я обычно объявляю абстрактный класс, содержащий pure virtual методы, который я передаю вместо виртуального интерфейса в uvm-классы. Внутри интерфейса я объявляю класс или классы, унаследованные от абстрактного класса, которые реализуют методы различным образом, например есть вариант с использованием clocking блока и с использованием сигналов напрямую. От уже созданных реализаций классов также можно наследоваться и переопределять работу определенных методов, например для асинхронных интерфейсов переопределять методы, отвечающие за задержки, создавая реализации манимальных, максимальных и средних задержек и т.д. Чтобы переключаться между вариантами реализации нужно только указать экземпляр какого класса нужно создать. uvm классы менять не нужно, так как в них передан базовый класс. Также это позволяет вообще не указывать параметры для базового класса, если в данный базовый класс не помещать методы, которым необходимы параметры. Можно сделать еще один базовый класс, унаследованный от другого, расширив его методами, которым нужны параметры, тогда в драйвере и мониторе нужно будет один раз в build_phase привести к базовому классу с нужными параметрами (тут надо учесть, что это подходит, если использовать механизм переопределения компонентов uvm для преобразования базовых классов monitor и driver в заданные реализации классов monitor и driver, использующие базовый класс с конкретными параметрами).

 

Еще важный вопрос, вы можете подключать к модулям сигналы cb.data, объявленные в клок блоке как output просто напрямую, типа my_module(.data(cb.data), ...)? Это точно?

Моя среда меня с этой идеей послала, сказала клоковый сигнал надо драйвить клоково. То есть подключение сигнала к порту среда воспринимает как assign, а для клокового оутпута

assign недопустим, приходиться делать wire подключенный к порту и дополнительный always @* в котором его пихать через <= в клоковый сигнал, тогда работает.

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

 

Clocking блок предназначен для установки сигналов с задержкой со стороны тестбенча, если вы пытаетесь достигнуть того, чтобы my_module устанавливал сигналы с задержкой, то мне кажется clocking блок для этого не очень подходит. Если же вы напрямую подключите сигналы к модулю (например, как в примере, который я привел), все будет работать, кроме того, что my_module не будет создавать задержки при установке сигналов.

 

 

 

почему если вызывать таск с паузами кратными периоду клоку, время от времени сигналы начинаются подниматься по парно в одном такте (ab, bc)? ну что за!? что я не так то сделал?

а покажите как вызываете task

Share this post


Link to post
Share on other sites

Спасибо, опять с последнего

в модуле примерно так...

initial begin 
  clk = 0;
  
  fork
     forever begin clk = ~clk; #5; end
     
     begin 
        for(int i  = 0; i < 100; i++)
           begin
              for(int j = 0; j< 100; j++)
                 intf.task;
              #100;
           end
     end

end

 

там на самом деле интерфейс шины параллельной, происходит пачка чтений и пауза. Интерфейс ставит адрес и выбор, в след такте поднимает чтение, в след такте опускает и ставит новые адрес и выбор. Соотвественно выбор должен висеть в единице, адреса менятся и чтение дергаться. Время от времени в начале пачки выбор поднимается вместе с чтением, тем которое идет после ##1, а в самом первом вызове такой канетели нет. Если перед пачками выравниваться по клоку клокингблока то все нормально, но почему оно съезжает без выравнивания не понятно....

 

 

что я не могу подключить порты модуля напрямую я уже давно знаю, о чем сетовал раньше. И причину там тоже красноречиво синтезатор написал. Просто думал может быть что-то упускаю. Теперь кажется понимаю что. То есть клокинг блоки это тестовая часть интерфейса, для организации работы со стороны тестового окружения и заводит через них обмен для реальных модулей не верно? Наверное этот ответ я и искал... то есть фактически они позволяют задавать сигналы из драйверов и сами выравнивают происходящее по границам клоков, как будто в драйвера работают обычные синхронные модули... теперь становится понятно что они скрывают и почему так криво работают:)

 

 

Про классы я разворачивал матрешку в другую сторону, заворачивал классы в классы, с интерфейсом внутри, но тут у меня наследие С++, в систем верилоге как то очень вывернута концепция объектности, тут объекты не заворачиваются большими и старшими, а наоборот объекты всовываются во внутрь. Видать к этому надо просто привыкнуть. Спасибо за комментарии

Share this post


Link to post
Share on other sites

там на самом деле интерфейс шины параллельной, происходит пачка чтений и пауза. Интерфейс ставит адрес и выбор, в след такте поднимает чтение, в след такте опускает и ставит новые адрес и выбор. Соотвественно выбор должен висеть в единице, адреса менятся и чтение дергаться. Время от времени в начале пачки выбор поднимается вместе с чтением, тем которое идет после ##1, а в самом первом вызове такой канетели нет. Если перед пачками выравниваться по клоку клокингблока то все нормально, но почему оно съезжает без выравнивания не понятно....

Проверил, все работает, как написано. Вот пример, аналогичный вашему, который запускал с использованием Questasim 10.4b.

interface my_if(input clk);
  logic a, b, c;
  
  default clocking cb_env @(posedge clk);
      default input #1step output #2ns;
      output a;
      output b;
      output c;
  endclocking

  task set;
     ##0;
     a <= 1;
     ##1;
     b <= 1;
     ##1;
     c <= 1;
     ##2;
     a <= 0;
     b <= 0;
     c <= 0;
  endtask

endinterface

module top;
  
  bit clk;
  
  my_if intf(clk);
  
  initial begin
    clk = 0;
    
    fork
       forever begin clk = ~clk; #5; end
      
       begin
          for(int i  = 0; i < 10; i++)
             begin
                for(int j = 0; j< 10; j++)
                   intf.set();
                #100;
             end
       end
    join

  end
endmodule

 

Вот полученная диаграмма:

2017_02_03_214538.png

 

Возможно ваши ошибки связаны со средой моделирования, которую используете?

 

Про классы я разворачивал матрешку в другую сторону, заворачивал классы в классы, с интерфейсом внутри, но тут у меня наследие С++, в систем верилоге как то очень вывернута концепция объектности, тут объекты не заворачиваются большими и старшими, а наоборот объекты всовываются во внутрь. Видать к этому надо просто привыкнуть. Спасибо за комментарии

 

Можно было бы делать наоборот - засовывать виртуальный интерфейс в класс, но зависимость от интерфейса никуда не исчезает, кода становится немного больше, и такой класс нужно еще куда-то вставить (такие классы, по моему мнению не заслуживают вставки в package, т.к. имеют сомнительные перспективы повторной используемости и лучше их не разделять с интерфейсом, статические переменные которого используются в классе), поэтому приведенный в ссылке способ определения класса в интерфейсе мне нравится больше.

Edited by Fitc

Share this post


Link to post
Share on other sites

Куеста сим,... я по ней скучаю:) да скорее всего какие-то косячики от симулятора, нц-сим, он вообще очень своеобразно подходит к системверилогу.

Я все передумал как так получилось что 2 сигнала через ##1 поднялись в один момент, и не мог придумать, подумал может есть какие нюансы.

 

Вообще я заметил что он часто делает странные вещи то есть я обращаюсь к сигналу напрямую, в симуляторе он рисует одно значение, а после присвоения оно другое, оказалось взял сигнал из под клокинг блока, хотя я по иерархии не указывал... правда я применил неблокирующее присовение которое немогло быть применено просто к сигналу, и видать он симпровизировал:)

 

Но я перестал его мучать клокинг блоками с интерфейсами к модулям и оставил только интерфейсы тестбенча, определенности стало сильно больше.

 

 

По классам спасибо, концепт уже понят:) применяю уже в другую сторону:) Пришел за клокинг блоками, а узнал про соединение:) 2 ответа за одну цену;)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...