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

Потребовалось мне написать некий простой компонент. С написанием проблем не возникло, но вот с его тестированием возникли сложности. Обычно я разрабатывал компоненты отвязанные от стандартных шин с каким-нибудь FIFO на входе и выходе или простым интерфейсом. Там создаешь testbench, генерируешь сброс и клок, а далее просто скармливаешь на входе данные и читаешь их с выхода. Но AXI...

Описание компонента: Сейчас компонент содержит AXI-Lite для конфигурирования, и несколько AXI-Stream где собственно и происходит обработка независимых потоков данных. По сути клок везде один, но возможно, в будущем клок AXI-Lite будет другим, поэтому он выведен отдельно. Но вот AXI-Stream как Slave так и Master будут работать от одного клока, поэтому кучу клоков, я объединил в один, чтобы не было ни у кого соблазна подать на эти входы независимые клоки, чем создать мне головняк по синхронизации данных. Ниже картинка того, что у меня получилось. Мой компонент: "Normalizer_0".

image.thumb.png.f41fbf178eba74e0d31858d23fc67868.png

Теперь надо бы создать testbench. И вот тут я сел в лужу...

1. Для работы с AXI нашел компоненты axi4stream_vip и axi_vip, но для работы с ними, как сказано в их описании, требуется знание SystemVerilog, его у меня нет. К тому же я не понимаю как в одном тестбенче можно описывать работу сразу двух компонентов.

2. Если я выброшу axi4stream_vip и axi_vip и выведу все AXI наружу, мне необходимо будет описать работу с AXI, что не исключает создание дополнительных ошибок уже снаружи.

3. Т.к. я знаю только VHDL, стал копать в этом направлении и нашел: UVVM (Universal VHDL Verification Methodology), но с VIVADO эта вещь напрямую не работает или я не сумел разобраться. Она работает с GVHDL. Но и с этим зверем я не справился.

4. Сама VIVADO при создании моего компонента создала шаблон testbench. Но увы, тоже на SystemVerilog, где есть куча ошибок, но я их не понимаю.

В каком направлении посоветуете двигаться, чтобы сформировать testbench, в котором, прописать регистры по шине AXI_Lite и скармливать по AXI-Steam тестовые данные, а на выходе их проверять, но не вдаваться в тонкости работы шины.

Упреждаю вопрос: "Зачем так сложно?". Будет не очень быстрый поток входных данных, но довольно ресурсоемкая обработка. Вот я и разделил вычислительные ресурсы между потоками таким образом.

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


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

Предлагаю посмотреть в сторону https://www.xilinx.com/products/intellectual-property/do-axi-bfm.html, есть документация с примерами.
С акси-стрим, вроде, сложностей не должно быть - там довольно простой "протокол".

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


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

3 часа назад, Tausinov сказал:

Предлагаю посмотреть в сторону https://www.xilinx.com/products/intellectual-property/do-axi-bfm.html, есть документация с примерами.
С акси-стрим, вроде, сложностей не должно быть - там довольно простой "протокол".

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

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

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


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

On 8/2/2022 at 8:26 AM, Vadim_nsk said:

В каком направлении посоветуете двигаться, чтобы сформировать testbench, в котором, прописать регистры по шине AXI_Lite и скармливать по AXI-Steam тестовые данные, а на выходе их проверять, но не вдаваться в тонкости работы шины.

связываясь с ксайлинским AXI VIP вступаете в область профессиональной деятельности, где без system verilog никак. там в этих VIP используются и assertion-ы и возможность использовать в UVM тестбенчах. 

например, я склеил из опенсорсных кусков и своих представлених AXI мастера - дык этот VIP (конкретно assertion) мгновенно нашел несколько несоответствий. хотя и на симуляторе и в железе все вполне работало...

 

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


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

On 8/2/2022 at 7:26 AM, Vadim_nsk said:

но не вдаваться в тонкости работы шины.

Вдаваться придется, рано или поздно.

Вот пример как у нас реализовали, для быстрого тестирования

    -- Write to AXI4-lite
    procedure axiWrite(
        constant Addr_in      : in    std_logic_vector(C_ADDRESS_SIZE-1 downto 0);-- Address to write to
        constant Data_in      : in    std_logic_vector(C_DATA_SIZE-1 downto 0);-- Data to write
        signal   Axi          : inout AXI_TYPE;-- AXI signals connected to slave
        signal   Clk_in       : in    std_logic;-- Clock to synchronize operation with
        constant Show_info_in : in    boolean := false;-- Display information in log about operation
        constant Timeout_in   : in    natural := 5)-- Maximum operation cycles before timeout error
    is
        variable axi_awready_asserted  : boolean := false;
        variable axi_wready_asserted   : boolean := false;
        variable axi_bvalid_asserted   : boolean := false;
        variable axi_bready_deasserted : boolean := false;
        variable axi_write_successful  : boolean := false;
    begin
        -- Setting signals controlled by slave to 'Z' state (in case AXI_TYPE wasn't initialized)
        Axi.awready_out   <= 'Z';
        Axi.wready_out    <= 'Z';
        Axi.bvalid_out    <= 'Z';
        Axi.bresp_bus_out <= (others => 'Z');

        -- Initializing master signals before transmission
        Axi.awprot_bus_in <= (others => '0');
        Axi.awvalid_in    <= '0';
        Axi.wstrb_in      <= (others => '1');
        Axi.wvalid_in     <= '0';
        Axi.bready_in     <= '0';

        -- Synchronizing transmission start to rising edge
        wait until rising_edge(Clk_in);

        -- Setting up address for writing
        Axi.awaddr_bus_in <= Addr_in;
        Axi.awvalid_in    <= '1';

        -- Setting up data for writing
        Axi.wdata_bus_in <= Data_in;
        Axi.wvalid_in    <= '1';

        for i in 0 to Timeout_in-1 loop
            wait until rising_edge(Clk_in);

            -- Check if address ready from slave was received
            if (Axi.awready_out = '1') then
                Axi.awvalid_in <= '0';
                axi_awready_asserted := true;
            end if;

            -- Check if data ready from slave was received
            if (Axi.wready_out = '1') then
                Axi.wvalid_in <= '0';
                axi_wready_asserted := true;
            end if;

            -- Check if write response from slave was received
            if (Axi.bvalid_out = '1') then
                Axi.bready_in <= '1';
                axi_bvalid_asserted := true;
            end if;

            -- If master asserted response ready, deassert it
            if (Axi.bready_in = '1') then
                Axi.bready_in <= '0';
                axi_bready_deasserted := true;
            end if;

            -- If operation was successful, set success flag and exit loop
            if ((axi_awready_asserted  = true)  and
                (axi_wready_asserted   = true)  and
                (axi_bvalid_asserted   = true)  and
                (axi_bready_deasserted = true)) then
                axi_write_successful := true;
                exit;
            end if;
        end loop;

        -- Display information if it was requested
        if ((Show_info_in = true) and (axi_write_successful = true)) then
            report "Successfully wrote " & integer'image(to_integer(signed(Data_in))) & " to address " & integer'image(to_integer(unsigned(Addr_in)));
        end if;

        -- Display error if write was unsuccessful
        if (axi_write_successful = false) then
            case Axi.bresp_bus_out is
                when "00" =>
                    report "AXI write error, write response is 0b00 - OKAY" severity error;
                when "01" =>
                    report "AXI write error, write response is 0b01 - EXOKAY" severity error;
                when "10" =>
                    report "AXI write error, write response is 0b10 - SLVERR" severity error;
                when "11" =>
                    report "AXI write error, write response is 0b10 - DCERR" severity error;
                when others =>
                    report "AXI write error, unknown response code" severity error;
            end case;
        end if;
    end axiWrite;

 

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


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

Спасибо. То , что надо! И работа шины и SystemVerilog у меня еще впереди, но не теперь. Тем более, что в мир FPGA я заходил как раз через Verilog, который мне показался более простым после Си, нежели VHDL с его многословным синтаксисом.

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


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

Спрошу тут же, т.к. вопрос в рамках этого же проекта и даже в рамках этого же компонента...

Когда рисуешь дизайн-схему, все связи формируются в ней и среда формирует VHDL-обертку по этому дизайну, в котором все IP-корки на шине AXI соединяются обычным способом. Но я пошел другим путем. Внутри своего компонента на VHDL я сгенерировал делитель на шину AXI, подключил его, все собралось. Но стоит мне выйти из проекта компонента, как он теряет связи.

image.thumb.png.bcfcb16732e9618c2bfc4fd708c6f743.png

Захожу в редактирование компонента, указываю файл div_gen_0.dcp, тогда он выдает сообщение и снова собирается:

image.thumb.png.de4358a0b33584e04a6af3e4b183d8bb.png

Ну, ладно бы он имел некие ограничения, о чем предупреждает, но он же теряет связь с компонентом. Кто как поступает в таком случае? Как его подключить внутри своего компонента?

Во внешнем проекте, где я использую свой компонент никак не могу ему подсунуть реализацию этого делителя:

image.thumb.png.a92b6b8b9617ede7181c84908b7574e7.png

image.png

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


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

"[Project 1-840] The design checkpoint file '.../ip_repo/Normalizer_1.0/src/div_gen_0/div_gen_0.dcp' was generated for an IP by an out of context synthesis run and should not be used directly as a source in a Vivado flow. Constraints and other files related to the IP are only stored in the xci/xcix, not the checkpoint. It is strongly recommended that the original IP source file (.xci/.xcix) be used."

А как его использовать, этот самый original IP source file (.xci/.xcix)?

 

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


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

Еще раз перегенерировал делитель, добавил его в дочернем проекте, все собралось. Убедился, что там добавлен именнно xci-файл. Вышел во внешний проект, получил ошибку. Добавил xci и во внешний проект, бесполезно...

image.thumb.png.d89412fdda8790b0b90584f5ad2d883c.png

он его в упор не видит.

Нет, ну есть конечно у меня вариант. В дочернем проекте в своем компоненте вывести наружу еще 3 AXI-шины, под умножитель. Подключить уже в графике во внешнем проекте к этим шинам делитель и может тогда все получится. Но это так геморно. И главное, я не знаю сработает ли. Да и к этим шинам можно подключить не делитель, а что угодно. Это же неправильно. Есть и еще один путь, взять какой-нибудь делитель с opencores, без AXI, использовать его. Но это тоже какой-то костыль. Я не хочу данный проект выводить наружу. Может кто-нибудь помочь, если я перешлю проект в личном сообщении?

Изменено пользователем Vadim_nsk

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


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

On 8/4/2022 at 8:30 PM, slkhome said:

У Вас нормально подлкючен репозиторий где лежит Ваш IP core?

image.thumb.png.cc098d9e80c41393813545dffc4f2141.png

путь правильный

 

Захожу в редактирование вот так:

image.png

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

image.thumb.png.a9c72d228fc16891f13538bf62346737.png

Изменено пользователем Vadim_nsk

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


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

On 8/4/2022 at 8:36 PM, slkhome said:

Т.е. я правильно понимаю - у Вас одно ядро внутри другого?

затрудняюсь ответить... Я как раз только что описал свои действия по созданию своего компонента. Может теперь вам будет понятен ответ на ваш вопрос...

Там в дочернем проекте видны сообщения, они не критичны:

image.thumb.png.5709e753923c3184dd3df58689de4cd0.png

он хоть и пишет, что компонент есть и он не может снова его добавить, тем не менее, все изменения во внешнем проекте видятся и новые шины добавились (s01_axis и m01_axis созданы уже позже):

image.png.ba409fbab612f48e38c83175a31ca8bb.png

Где-то потерялось одно сообщение с картинкой... :-(

В общем, во внешнем проекте создал свой компонент с AXI-шиной, добавил в схему, все собралось. Затем, отредактировал, добавив еще две шины. Снова все собралось. Затем отредактировал, добавив из IP Catalog делитель на AXI-шине. И т.к. в дочернем проекте у меня не было графического дизайна, ведь при создании своего компонента я выбрал VHDL, то просто описал интерфейс компонента делителя и добавил работу с ним в код. Все собралось. А вот во внешнем проекте делитель не виден. Добавляю его руками, все равно не видится.

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


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

Внутри проекта своего компонента создал пустой desigh_1, на который добавил делитель. Не помогло. Пока вижу такой вариант. Создать еще один свой компонент внутри своего компонента где вывести наружу 3 AXIS шины, к которым подключить делитель. Но это же ужас просто. В будущем мне придется увеличить количество AXIS шин и получается, что придется делать это в двух местах одновременно. И то, не факт, что это сработает.

Кто-нибудь создавая свои компоненты на AXI использовал стандартные корки? Как вы это делаете?

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


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

Странно. Предположим что мне для работы компонента потребовалось FIR-фильтр, умножитель, делитель, CORDIC и еще что-нибудь. Мне что для подключения всех этих вещей в своем компоненте создавать внешние AXI-шины? Наверняка есть другой путь...

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


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

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

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

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

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

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

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

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

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

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