Jump to content

    

Vivado BD как спрятать параметризируемые порты AXI

13 минут назад, andrew_b сказал:

Почему это? Все модули компилируются независимо друг от друга.

Там есть ключик для этого. Кажется, @des00 это и имел в виду - опция "-mfcu". В одном режиме оно компилируется как отдельные единицы компиляции (как в Си - в отдельные объектные файлы), а в другом - сразу скопом весь список за раз (и при этом там получается общее пространство объектов и макросов).

Share this post


Link to post
Share on other sites
4 minutes ago, dxp said:

Там есть ключик для этого. Кажется, @des00 это и имел в виду - опция "-mfcu". В одном режиме оно компилируется как отдельные единицы компиляции (как в Си - в отдельные объектные файлы), а в другом - сразу скопом весь список за раз (и при этом там получается общее пространство объектов и макрсов).

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

Share this post


Link to post
Share on other sites

Приветствую!

1 hour ago, dxp said:

Типа того. Ведь если просто тупо их объявить, то отваливается возможность параметризации и они по сути вырождаются в "улучшенные структуры". По-хорошему, просится возможность создавать интерфейсы с помощью generate for, но иметь возможность при этом как-то их объединять в коллекцию, по которой можно было бы итерировать - для автоматизации описания. Технически ведь тут принципиальных трудностей нет - просто средства автоматической генерации и автоматизации кода. Каким-нибудь сторонним скриптом на питоне или даже тикле это можно делать уже и сейчас.

Увы  массив разнотипных сущностей  в SV не создать (не только интерфейсов, а вообще) - ведь  SV  язык с жесткой типизацией. А инстансы интерфейсов одного типа, но с разными параметрами с точки зрения SV имеет разный тип:cray2: А иногда руки так и чешутся сделать что-то универсальное с подобием приведения типов в С/С++. Но увы. 

Ну а массивы  однотипных инстансов без проблем (надеюсь). Будь то переменные, интерфейсы или модули. 

Удачи! Rob.

Share this post


Link to post
Share on other sites
12 минут назад, RobFPGA сказал:

или модули

Что и массив модулей можно создать? А как к ним порты цеплять - синтаксис объявления массива как-то не очень предполагает такие финты. Это, кстати, в полной мере относится и к интерфейсам - там-то тоже ведь сигналы можно передавать при объявлении.

Share this post


Link to post
Share on other sites

Приветствую!

2 hours ago, dxp said:

Что и массив модулей можно создать? А как к ним порты цеплять

Можно :)   Да так же как и обычно  - главное чтобы ширина была правильной - при назначении порта разрядностью N идет  выборка очередных N bit из переменной. 

Spoiler

interface if_test #(DATA_WH=4) (input wire clk, rst);
  logic               ena ;
  logic [DATA_WH-1:0] data;
endinterface

(* keep_hierarchy="yes" *)
module prc_cnt #(WH=4) (
  if_test cnt_if[WH]
);

generate
  for (genvar gi=0; gi<WH; ++gi) begin : g_cnt
    always_ff @(posedge cnt_if[gi].clk) begin
      if (cnt_if[gi].rst) begin
        cnt_if[gi].data <= '0;
      end
      else if (cnt_if[gi].ena) begin
        cnt_if[gi].data <= cnt_if[gi].data + 1'b1;
      end
    end
  end
endgenerate
endmodule

(* keep_hierarchy="yes" *)
module test_inv #(parameter INV=1) (
  input  wire        clk,
  input  wire        rst,
  input  wire        in ,
  output logic [1:0] ou
);

assign ou[0] = (INV==1) ? ~in : in;

always_ff @(posedge clk) begin
  ou[1] <= rst ? '0 : ( (INV==1) ? ~in : in);
end
endmodule

(* keep_hierarchy="yes" *)
module test_if1 #(parameter
  CNT_NUM = 3,
  DATA_WH = 4
) (
  input  wire                             clk, // Clock
  input  wire                             rst, // Synchronous reset active hight
  input  wire  [CNT_NUM-1:0]              din,
  output logic [CNT_NUM-1:0][DATA_WH-1:0] dou
);

(* keep="true" *)
if_test #(DATA_WH) count_if [CNT_NUM] (clk, rst);

(* keep="true" *)
wire [2*CNT_NUM-1:0] w_din;

test_inv #(1) i_inv [CNT_NUM-1:0] (.clk(clk), .rst(rst), .in(din), .ou(w_din));

generate
  for (genvar gi=0; gi<CNT_NUM; ++gi) begin : g_io
    assign count_if[gi].ena = w_din[gi*2+0] & ~w_din[gi*2+1]; // din[gi];
    assign dou[gi] = count_if[gi].data;
  end
endgenerate

prc_cnt #(CNT_NUM) i_prc_cnt (count_if);

endmodule

 

Получается такая симпатичная картинка 

Удачи! Rob.

array_if_mod1.png

Share this post


Link to post
Share on other sites

Приветствую!

Причем как оказалось можно и так 

...
//prc_cnt #(CNT_NUM) i_prc_cnt (count_if);
prc_cnt #(1) i_prc_cnt[CNT_NUM] (count_if);
...

Можно было и не делать отдельный модуль (test_inv) для примера :boast: Как говорится - найдите 3 отличия.

Удачи! Rob.

array_if_mod2.png

Share this post


Link to post
Share on other sites

@RobFPGA как всегда убедителен. :wink2: Но всё равно что-то меня останавливает от использования массива интерфейсов в портах. :acute:

Share this post


Link to post
Share on other sites

Параметризировать интерфейсы, конечно хорошая идея. Но по сути тут все прекрасно понимают, что эти танцы с бубном в основном будут использованы для AXI/Avalon. Отсюда у меня возник вопрос: а имеет смысл не возиться с n-количественными портами AXIа создать и подключить всё нужное через один? Сделать как-бы парсер в один порт, а уже играть с адресацией внутренних компонентов, зарделением работы во времени и т.д. А на выходе иметь уже нужные шины данных: РАМки, Регистры, периферию

Share this post


Link to post
Share on other sites

Приветствую!

21 hours ago, dxp said:

что-то меня останавливает от использования массива интерфейсов в портах

Подумаешь - всего лишь массив интересов :wink:  - а как вам такое  :shok: 

//test_pq
 typedef struct packed {
    st_WDATA_t    wrd ;
    logic [15:12] sel ;
    logic [ 11:0] addr;
  } st_WBUS_t;

  typedef struct packed {
    st_WDATA_t  wrd   ;
    logic [3:0] addr_h;
    logic [3:0] addr_l;
  } st_A_t;

  typedef struct packed {
    st_WDATA_t  wrd   ;
    logic [3:0] addr_h;
    logic [5:0] addr_l;
  } st_B_t;
...
(* keep_hierarchy="yes" *)
module test_st #(parameter
  int  A_NUM  = 1                 ,
  int  B_NUM  = 2                 ,
  type T_IN   = test_pq::st_WBUS_t,
  type T_OU_A = test_pq::st_A_t   ,
  type T_OU_B = test_pq::st_B_t
) (
  input  wire   clk        ,
  input  wire   rst        ,
  input  T_IN   wbus       ,
  output T_OU_A ou_a[A_NUM],
  output T_OU_B ou_b[B_NUM]
);
...

 

1 hour ago, Nick_K said:

эти танцы с бубном в основном будут использованы для AXI/Avalon

Вопрос не в типе шины, а в попытке хитрым вывертом обойти  принципиальное ограничение V/SV  в невозможности параметрами контролировать число портов (и по возможности разного типа).

Удачи! Rob.

Share this post


Link to post
Share on other sites
4 минуты назад, RobFPGA сказал:

Подумаешь - всего лишь массив интересов :wink:  - а как вам такое  :shok: 

Не уловил акцента. :unknw:

 

Кстати, я пробовал массив интерфейсов и наткнулся на то, что оно (в частности, квеста) не позволяет с ними работать банально в цикле - говорит, что неконстантный индекс не разрешается. Смотрю ваши примеры - там везде generate ... for. Это несколько иной контекст - тут просто каждый инстанс как бы канализируется (свои блоки создаются и т.д.). А когда просто внутри, например, always_ff в цикле пробежаться по массиву - фигвам. С массивами структур такой проблемы нет.

Share this post


Link to post
Share on other sites
3 minutes ago, dxp said:

А когда просто внутри, например, always_ff в цикле пробежаться по массиву - фигвам.

Наверное это поведение перекочевало с VHDL. Там всё настолько типизированно, что к реальным нетам можно и нужно обращаться только в генерируемых структурах. А если и есть возможность "в цикле for...loop" то оно такого может насинтезить, что хоть стреляйся.

Share this post


Link to post
Share on other sites
28 минут назад, Nick_K сказал:

Наверное это поведение перекочевало с VHDL.

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

Share this post


Link to post
Share on other sites

Приветствую!

23 minutes ago, dxp said:

Не уловил акцента. :unknw:

Массив портов типы которых задаются параметрами модуля. Прикольно, но и сомнительно с точки зрения полезности. 

33 minutes ago, dxp said:

А когда просто внутри, например, always_ff в цикле пробежаться по массиву - фигвам.

Печально, но это так.  И трудно понять почему же так :scratch_one-s_head:

Удачи! Rob.

Share this post


Link to post
Share on other sites
On 9/6/2019 at 5:35 PM, dxp said:

 А когда просто внутри, например, always_ff в цикле пробежаться по массиву - фигвам. С массивами структур такой проблемы нет.

Если для моделирования, это делается через указатели на интерфейс : виртуальные интерфейсы. К ним можно обращаться в циклах в процедурных блоках. Но, сначала надо инстанцировать интерфейсы, переназначить указатели)

Работает ли это для синтеза, не проверял)

Share this post


Link to post
Share on other sites
10 часов назад, des00 сказал:

Если для моделирования

Не, мне для синтеза.

 

Обнаружил такую неприятность. Есть простейшая структура:

typedef struct
{
  logic a;
  logic b;
}
slon_t;

Она передаётся в модуль как:

module ...
(
  ...
  output slot_t slon[N],
  ...
);
  

Далее есть примерно такой код:

always_ff @(posedge clk) begin
  ...
  for(int i = 0; i < N; ++i) begin
     slon[i].a <= ...
  end
end

...

always_comb begin
  for(int i = 0; i < N; ++i) begin
     slon[i].b = ...
  end
end  

  

Квеста 10.7с выдаёт ошибку, что де объект 'slon' используемый в одном процедурном блоке, используется в другом. Бред! Реально-то там же разные объекты в разных блоках задействуются, а структура - это просто агрегатный тип. Она же не пакованная.

 

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

 

В итоге обошёл так: завел просто местные массивы  и присвоил полям структуры в одном always_comb блоке в цикле:

logic [N-1:0] a;
logic [N-1:0] b;

always_comb begin
  for(int i = 0; i < N; ++i) begin
     slon[i].a = a[i];
     slon[i].b = b[i];
  end
end

А по коду уже работаю с 'a' и 'b'. Стало даже в чём-то удобнее - например, можно обнулить массив простым присваиванием 0 (со структурой приходилось цикл писать).

 

Единственное, гложет сомнение - может я всё-таки что-то делаю не так? Если да, поправьте.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this