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 30 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 30 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 0 27 апреля, 2013 Опубликовано 27 апреля, 2013 · Жалоба verilog не поддерживает структуры, за что мы все его очень любим и уважаем. Один из способов "работы" со структурами в verilog, аналогично упакованным структурам в sv - это объявить гомогенную шину, а в файле, подключаемом через `include, предоставлять сервисные параметры и функции доступа к кускам этой шины, как к полям. Задача с многомерными шинами, у которых что-то там зависит от параметров, решается аналогично. Полноценной работой это назвать, конечно, нельзя, т.к. при elaboration никаких соответствий типов при подключении не проверяется, но все же хоть какой-то выход. Я может чего-то не понимаю, но нельзя ли задачу ТС решить таким простым способом, как объявить структуру через typedef во внешнем инклюде ( в ней могут быть как шины, так и просто обычные проволоки), а затаем через параметр модуля повторить её столько раз сколько нужно? Это конечно не так красиво как с интерфейсами, кроме того для входов и выходов придётся делать две структуры, зато соберётся любым синтезатором, даже без поддержки SV. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 9 29 апреля, 2013 Опубликовано 29 апреля, 2013 · Жалоба Был конкретный вопрос с примером. количество портов не может зависить от параметра. Может я не правильно выразился...... я не хочу завести parameter, в понимании синтаксиса verilog, и потом этот пораметр прикрутить к кол-ву портов модуля. под словами "какойнить параметр" я не имел ввиду только parameter, я имел ввиду что где-то как-то указать, например: parameter, property, define, typdef, QEditLine, TComboBox, set_module_property..... и т.п. Меняя этот "параметр" менялось бы кол-во портов и соответсвенно графическое отображение. про скриптовые языки я уже понял. про интерфейсы внутри модуля - не очень понятно. ну будет внутри модуля что-то там делится. Но внешне на графике всёравно будет один толстый порт, в который нужно объеденять все шины. ps количество портов не может зависить от параметра. ну в мегакорках же зависит Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 30 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 0 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 30 27 мая, 2013 Опубликовано 27 мая, 2013 · Жалоба Вопрос в том, как "вытащить" из инстанцируемого модуля "а" один из интерфейсов и подключить его к "sub_a"??? Не очень понял задачу. В чём проблема-то? Интерфейсы ведут себя в плане синтаксиса ровно также, как и обычные порты. Интерфейс из вложенного модуля напрямую прокидывается "наверх" как и обычный порт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться