Methane 0 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба От параметра количество портов не изменится. А чтобы собрать/разобрать упакованный массив - для этого SV и интерфейсы не нужны. module we_no_need_thats_system_verilog( input [234:0] all_in, input [345:0] all_out ); assign clk = all_in[0]; assign reset_n = all_in[1]; assign data = all_in[66:2]; ..... ..... assign cs = all_in[234]; и.т.д и.т.п ..... endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masics 0 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба module we_no_need_thats_system_verilog( input [234:0] all_in, input [345:0] all_out ); assign clk = all_in[0]; assign reset_n = all_in[1]; assign data = all_in[66:2]; ..... ..... assign cs = all_in[234]; и.т.д и.т.п ..... endmodule Не надо ёрничать. Был конкретный вопрос с примером. Советую прочитать, а потом выступать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 67 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба От параметра количество портов не изменится. А чтобы собрать/разобрать упакованный массив - для этого SV и интерфейсы не нужны. Количество портов изменится внутри интерфейса. От параметра. У модуля это меняться не может, у интерфейса может. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masics 0 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба Количество портов изменится внутри интерфейса. От параметра. У модуля это меняться не может, у интерфейса может. Можно пример? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
spectr 0 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба Не так давно решал похожую задачу (нужно было что-то вроде легко масштабируемого мультиплексора данных где каждый вход подключается на выход своим CS'ом). Вышел из положения следующим образом. Собственно, многопортовый параметризируемый модуль: module data_mux #( parameter num_inputs = 3, parameter datawidth = 60 ) ( input reset, input clk, input [num_inputs*datawidth-1:0] datain, input [num_inputs-1:0] cs_in, output reg [datawidth-1:0] dataout, output reg data_ready ); integer i; always @(posedge clk, posedge reset) begin if(reset) begin dataout <= 0; data_ready <= 0; end else begin data_ready <= |cs_in; for(i = 0; i < num_inputs; i= i + 1) begin if(cs_in[i] == 1) dataout <= datain[i*datawidth +: datawidth]; end end end endmodule А в надмодуле используется следующий синтаксический сахар: // map data sources to single bus localparam datawidth = 60; localparam num_sources = 4; wire [num_sources*datawidth-1:0] mapped_data; wire [num_sources-1:0] mapped_cs; `define map_data(index, cs_signal, data) \ assign mapped_data[index*datawidth +: datawidth] = data; \ assign mapped_cs[index] = cs_signal `map_data(0, cs_sync_link, 60'h C0FFEE000C0FFEE); `map_data(1, ping_req, 60'h 000F00DF00DF00D); `map_data(2, adc_data_ready, {12'd0, adc_data}); `map_data(3, do_echo, serdes_rxfifo_data[59:0]); wire [datawidth-1:0] data_to_send; wire send; data_mux datamux ( .reset (reset), .clk (clk_100), .datain (mapped_data), .cs_in (mapped_cs), .dataout (data_to_send), .data_ready (send) ); defparam datamux.num_inputs = num_sources, datamux.datawidth = datawidth; В итоге, дальнейшие манипуляции по добавлению нового порта сводятся лишь к: 1. Правке параметра num_sources 2. Добавлению волшебной строчки `map_data(port_index, my_cs_signal, data_for_this_cs_signal); Пока что очень удобно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 67 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба Можно пример? Из рабочего проекта (выбрал попроще). Это интерфейс, цель которого - раздать сигналы от внешней шины памяти, зацепленной на внешний микропроцессор, по модулям внутри интерфейса. interface mmr_i #( parameter AW = 13, // common address width parameter DW = 16, // data width parameter DAW = 5, // device address width (is a part of AW) parameter int N = 1 // number of the devices ); // types typedef bit [DW-1:0] data_t; typedef data_t q_bundle_t[N]; // public bit [AW-1:0] addr; bit [DW-1:0] data; bit wren; bit [DW-1:0] q; // private q_bundle_t q_bundle; // functions function automatic data_t qmux(q_bundle_t x, int n); return x[n]; endfunction // logic assign q = qmux(q_bundle, addr[AW-DAW-1:DAW]); // modports modport port ( output addr, output data, output wren, input q ); genvar i; generate for(i = 0; i < N; i++) begin : mport bit dev_sel; assign dev_sel = addr[AW-DAW-1:DAW] == i; modport dev ( input .addr ( addr[DAW-1:0] ), input .data ( data ), input .wren ( wren ), input .sel ( dev_sel ), output .q ( q_bundle[i] ) ); end endgenerate endinterface Использование: mmr_i // объявляем объект интерфейса #( .AW ( 13 ), .DW ( 16 ), .DAW ( 4 ), .N ( 7 ) ) mmr(); ... module_m module_inst ( .clk ( clk ), .rst ( rst ), ... .mmr ( mmr.mport[4].dev ) // сгенерированный модпорт (линк к модулю) ); ... memory_port_m #( .ADDR_WIDTH ( 24 ), .BANK_ADDR_WIDTH ( 2 ), .EXT_ADDR_WIDTH ( BF_ADDR_WIDTH ), .BF_DATA_WIDTH ( BF_DATA_WIDTH ), .VM_DATA_WIDTH ( VM_DATA_WIDTH ), .BF_AGENT_BUF_CAPACITY ( BF_AGENT_BUF_CAPACITY ), .VM_AGENT_BUF_CAPACITY ( VM_AGENT_BUF_CAPACITY/2 ) ) memory_port ( .clk ( clk ), .hfclk ( hfclk ), .clk_s ( clk_s ), .rst ( rst ), //---------------------------------- // // Agents // .bf_wr0 ( bf_wr0 ), .bf_rd0 ( bf_rd0 ), .vm_wr0 ( vm_wr0.agent ), .vm_rd0 ( vm_rd0.agent ), //---------------------------------- // // MMRs // .mmr ( mmr ), // "статический" модпорт (шина на внешний проц) ... У каждого модуля, который имеет регистры, отмапленные на на шину внешнего проца, есть подключение порта вида: .mmr ( mmr.mport[..].dev ) Пример не совсем то, что спрашивал ТС, но механизмы, которые показаны, годятся для того, чтобы автоматом генерировать необходимые порты внутри интерфейса по параметрам. P.S. Инстанции модулей показаны обрезанными. Если что-то пропустил/неточно сказал, прошу извинить, не могу в данный момент сделать тщательно, тороплюсь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 26 апреля, 2013 Опубликовано 26 апреля, 2013 · Жалоба 2 dxp красиво!!! Это только ква такое сейчас собрать может или симплифай с вивадой тоже обучены? ЗЫ. правда задача даже близко не похожа на задачу TC. т.к. как ни крути, а порт у модуля все же один. А пихать всю логику в интерфейс ИМХО не комильфо. PPS. ЕМНИП в модуль можно передать массив интерфейсов, у меня работало в симуляторе, но на тот момент ни один синтезатор не смог собрать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 27 апреля, 2013 Опубликовано 27 апреля, 2013 · Жалоба 2 dxp красиво!!! Это только ква такое сейчас собрать может или симплифай с вивадой тоже обучены? ЗЫ. правда задача даже близко не похожа на задачу TC. т.к. как ни крути, а порт у модуля все же один. А пихать всю логику в интерфейс ИМХО не комильфо. PPS. ЕМНИП в модуль можно передать массив интерфейсов, у меня работало в симуляторе, но на тот момент ни один синтезатор не смог собрать. Я может чего-то не понимаю, но нельзя ли задачу ТС решить таким простым способом, как объявить структуру через typedef во внешнем инклюде ( в ней могут быть как шины, так и просто обычные проволоки), а затаем через параметр модуля повторить её столько раз сколько нужно? Это конечно не так красиво как с интерфейсами, кроме того для входов и выходов придётся делать две структуры, зато соберётся любым синтезатором, даже без поддержки SV. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
FatRobot 4 27 апреля, 2013 Опубликовано 27 апреля, 2013 · Жалоба verilog не поддерживает структуры, за что мы все его очень любим и уважаем. Один из способов "работы" со структурами в verilog, аналогично упакованным структурам в sv - это объявить гомогенную шину, а в файле, подключаемом через `include, предоставлять сервисные параметры и функции доступа к кускам этой шины, как к полям. Задача с многомерными шинами, у которых что-то там зависит от параметров, решается аналогично. Полноценной работой это назвать, конечно, нельзя, т.к. при elaboration никаких соответствий типов при подключении не проверяется, но все же хоть какой-то выход. Я может чего-то не понимаю, но нельзя ли задачу ТС решить таким простым способом, как объявить структуру через typedef во внешнем инклюде ( в ней могут быть как шины, так и просто обычные проволоки), а затаем через параметр модуля повторить её столько раз сколько нужно? Это конечно не так красиво как с интерфейсами, кроме того для входов и выходов придётся делать две структуры, зато соберётся любым синтезатором, даже без поддержки SV. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 29 апреля, 2013 Опубликовано 29 апреля, 2013 · Жалоба Был конкретный вопрос с примером. количество портов не может зависить от параметра. Может я не правильно выразился...... я не хочу завести parameter, в понимании синтаксиса verilog, и потом этот пораметр прикрутить к кол-ву портов модуля. под словами "какойнить параметр" я не имел ввиду только parameter, я имел ввиду что где-то как-то указать, например: parameter, property, define, typdef, QEditLine, TComboBox, set_module_property..... и т.п. Меняя этот "параметр" менялось бы кол-во портов и соответсвенно графическое отображение. про скриптовые языки я уже понял. про интерфейсы внутри модуля - не очень понятно. ну будет внутри модуля что-то там делится. Но внешне на графике всёравно будет один толстый порт, в который нужно объеденять все шины. ps количество портов не может зависить от параметра. ну в мегакорках же зависит Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 67 29 апреля, 2013 Опубликовано 29 апреля, 2013 · Жалоба Это только ква такое сейчас собрать может или симплифай с вивадой тоже обучены? Квартус и квеста держат, за другие не скажу, не пробовали. А пихать всю логику в интерфейс ИМХО не комильфо. Не всю, а только необходимую. Тем более, по задаче ТС там и логики-то нет - только генерация портов внутри интерфейса в соответствии с заданными параметрами. Что касается логики, то у нас есть ещё ряд успешных применений интерфейсов. В частности, есть интерфейсы, которые занимаются упаковкой/распаковкой данных - шина на внешнюю память 32 бита, а внутри ПЛИС данные от модулей имеют меньшую разрядность (8, 10, 16 бит) - интерфейс сам упаковывает данные при записи и распаковывает при чтении. Очень удобно. Реализация интерфейсов: interface mem_wr_i #( parameter AW = 24, // address width of physical memory space parameter DW = 32, // data width of physical memory space parameter ADW = 16, // application word data width parameter CAP = 512 // capacity of the agent fifo buffer ) ( input clk, input rst ); localparam FACTOR = DW/ADW; //------------------------------------------ // // Common // bit start; bit up; bit load; bit busy; bit full; bit empty; bit [ clog2(FACTOR)-1:0] pack_cnt; bit [FACTOR-1-1:0][ADW-1:0] data; // -1 because MSBs of data_agent need not to fix in medium register //------------------------------------------ // // Application // bit [AW+clog2(FACTOR)-1:0] addr_app; bit [ bits(CAP)-1:0] count_app; bit [ ADW-1:0] data_app; bit [ bits(CAP)-1:0] fifo_cnt_app; //------------------------------------------ // // Agent // // bit [ AW-1:0] addr_agent; bit [ DW-1:0] data_agent; bit [bits(CAP/FACTOR)-1:0] count_agent; bit [bits(CAP/FACTOR)-1:0] fifo_cnt_agent; bit load_agent; function automatic int iassign(input int x, input int y); return x & (y | ~y); endfunction //------------------------------------------ // // Logic // assign load_agent = load && (pack_cnt == FACTOR-1); assign fifo_cnt_app = fifo_cnt_agent*FACTOR; assign count_agent = count_app/FACTOR; assign addr_agent = addr_app/FACTOR; assign data_agent = { data_app, data }; always_ff @(posedge clk) begin if(rst) begin pack_cnt <= 0; end else begin if(load) begin data[pack_cnt] <= data_app; pack_cnt <= pack_cnt + 1; if(pack_cnt == FACTOR-1) begin pack_cnt <= 0; end end end end //------------------------------------------ // // Modports // modport app ( output .data ( data_app ), output start, output .count ( count_app ), output .addr ( addr_app ), output load, output up, input busy, input full, input empty, input .fifo_cnt ( fifo_cnt_app ) ); modport agent ( input .data ( data_agent ), input start, input .count ( count_agent ), input .addr ( addr_agent ), input .load ( load_agent ), input up, output busy, output full, output empty, output .fifo_cnt ( fifo_cnt_agent ) ); endinterface //------------------------------------------------------------------------------ interface mem_rd_i #( parameter AW = 24, // address width of physical memory space parameter DW = 32, // data width of physical memory space parameter ADW = 16, // application word data width parameter CAP = 512 // capacity of the agent fifo buffer ) ( input clk, input rst ); localparam FACTOR = DW/ADW; //------------------------------------------ // // Common // bit start; bit up; bit get; bit busy; bit full; bit empty; bit [ clog2(FACTOR)-1:0] pack_cnt; bit [ FACTOR-1:0][ADW-1:0] data; //------------------------------------------ // // Application // bit [AW+clog2(FACTOR)-1:0] addr_app; bit [ bits(CAP)-1:0] count_app; bit [ ADW-1:0] data_app; bit [ bits(CAP)-1:0] fifo_cnt_app; //bit get_app; //------------------------------------------ // // Agent // bit [ AW-1:0] addr_agent; bit [ DW-1:0] data_agent; bit [bits(CAP/FACTOR)-1:0] count_agent; bit [bits(CAP/FACTOR)-1:0] fifo_cnt_agent; bit get_agent; //------------------------------------------ // // Logic // assign get_agent = get && (pack_cnt == FACTOR-1); assign fifo_cnt_app = fifo_cnt_agent*FACTOR; assign count_agent = count_app/FACTOR; assign addr_agent = addr_app/FACTOR; assign data = data_agent; assign data_app = data[pack_cnt]; always_ff @(posedge clk) begin if(rst) begin pack_cnt <= 0; end else begin if(get) begin pack_cnt <= pack_cnt + 1; if(pack_cnt == FACTOR-1) begin pack_cnt <= 0; end end end end //------------------------------------------ // // Modports // // modport app ( input .data ( data_app ), output start, output .count ( count_app ), output .addr ( addr_app ), output get, output up, input busy, input full, input empty, input .fifo_cnt ( fifo_cnt_app ) ); modport agent ( output .data ( data_agent ), input start, input .count ( count_agent ), input .addr ( addr_agent ), input .get ( get_agent ), input up, output busy, output full, output empty, output .fifo_cnt ( fifo_cnt_agent ) ); endinterface Без интерфейсов эту логику пришлось бы пихать либо в код модулей, либо лепить промежуточный модуль (я так и делал, пока не подружился с интерфейсами поближе), а ведь ей (этой логике) как раз самое место в интерфейсе. С такими интерфейсами подключение делается просто тривиальным - по одной строчке в инстанцировании каждого модуля. Если интересно, можно ещё показать пару применений в реальном боевом проекте - как раз там есть пример, где порты внутри интерфейса генерируются автоматически в соответствии массивом параметров, задаваемых при инстанцировании интерфейса: интерфейс switch fabric, который парсит поток (в данном случае от USB) и раздаёт порции данных по модулям. Вообще, SV интерфейс очень гибкая штука. Помимо линкования модулей он может использоваться хоть локально - при этом он похож на структуру с возможностью определения порций кода внутри неё. Получается что-то вроде модуля с некоторыми ограничениями (к сожалению, внутри интерфейса нельзя инстанцировать модули - т.е., скажем, тот же модуль FIFO внутри интерфейса сделать нельзя, что очень жаль; остаётся описывать логику FIFO кодом, но это далеко не всегда годный вариант), но в ряде случаев такое использование проще и удобнее, нежели инстанцирование модуля: удобство заключается, например, в том, что не нужно заводить пачку сигналов (пусть даже объединённых в структуру) для подключения к портам модуля - потроха интерфейса можно юзать напрямую инлайн (как на AHDL :) ), это уменьшает писанину и сокращает количество сущностей. Для небольших законченных по смыслу порций логики реализация в виде интерфейса вместо модуля часто оказывается значительно удобнее. Рекомендую. PPS. ЕМНИП в модуль можно передать массив интерфейсов, у меня работало в симуляторе, но на тот момент ни один синтезатор не смог собрать. Квартус нынешний, вроде, уже поддерживает массив интерфейсов. Когда-то я очень хотел этой возможности, но синтезаторы не поддерживали (ква) или поддерживали с глюками (Precision). Теперь я понял, что то, что я хотел, отлично реализуется без всяких массивов на одном интерфейсе - там можно задать сколько угодно портов, включая руление свойствами (направление сигналов и их тип) каждого модпорта. Вот пример mmr_i из предыдущего поста как раз показывает, как можно из одного интерфейса объединять пачку портов на соответствующее количество модулей. Реально массив интерфейсов актуален в ситуации, когда есть эн модулей с одинаковыми интерфейсами, которые нужно упаковать в один модуль и манипулировать ими в цикле. Но и в этом случае всё можно сделать на одном интерфейсе со сгенерированными модпортами. Это только вопрос удобства. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Fynjisx 0 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба Квартус нынешний, вроде, уже поддерживает массив интерфейсов. Модуль "а" инстанцирует подмодули - "sub_a", в портах которых определен интерфейс "chan": module a #( parameter PAR1= 14, PAR2 = 15, COUNT_UNIT = 6 ) ( // Input Ports ... // Output Ports ... //Selecting the modport in the module port declaration channel.master chan[COUNT_UNIT-1:0] ); genvar c; generate for (c = 0; c < COUNT_UNIT; c = c+1) begin: test sub_a #( .PAR1(1) ) sub_a_inst( .clk, .data_i(scr__data_i), .addr(scr__addr_i), .wr(scr__wr[c]), .rst_n, .scr_gate(scr_gate[c]), .chan(chan[c]) ); end endgenerate endmodule Есть модуль top, который инстанцирует модуль "а" а также один "sub_a". Вопрос в том, как "вытащить" из инстанцируемого модуля "а" один из интерфейсов и подключить его к "sub_a"??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
FatRobot 4 24 мая, 2013 Опубликовано 24 мая, 2013 · Жалоба module test( `ifdef PRM_1 input a, `endif `ifdef PRM_2 input b, `endif input c, output out ); endmodule тошнотворный способ ну в мегакорках же зависит Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1891ВМ12Я 0 25 мая, 2013 Опубликовано 25 мая, 2013 · Жалоба Не понимаю в чем проблема. Если N портов одинаковой или даже разной разрядности, то берем один порт, а дальше в зависимости от параметров - расщепляем его на сколько угодно шин и всё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 67 27 мая, 2013 Опубликовано 27 мая, 2013 · Жалоба Вопрос в том, как "вытащить" из инстанцируемого модуля "а" один из интерфейсов и подключить его к "sub_a"??? Не очень понял задачу. В чём проблема-то? Интерфейсы ведут себя в плане синтаксиса ровно также, как и обычные порты. Интерфейс из вложенного модуля напрямую прокидывается "наверх" как и обычный порт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться