des00 27 September 5, 2014 Posted September 5, 2014 · Report post По сути вопроса я наверное плохо объясняю. Во всяком случае ISE 14.4 часто ругается когда меняется порядок индексов, то есть если объявляли регистр как 3:0, то попытки в каких то действиях запихать в него обратный порядок вызывает ошибку. Тут надо специалиста который поймет о чем я несу и нормально сформулирует :)... я что-то не могу сразу примера вспомнить.... ISE 14.7 ест и не давиться wire [4*32-1 : 0] iram_rdata; ...... wire [63 : 0] L__ordata_rslt; ...... assign iram_rdata[0*32 +: 32] = oram_addr[0] ? N__ordata_rslt[32 +: 32] : N__ordata_rslt[0 +: 32]; // 64 bit assign iram_rdata[1*32 +: 32] = oram_addr[0] ? T__ordata_rslt[32 +: 32] : T__ordata_rslt[0 +: 32]; assign iram_rdata[2*32 +: 32] = oram_addr[0] ? L__ordata_rslt[32 +: 32] : L__ordata_rslt[0 +: 32]; assign iram_rdata[3*32 +: 32] = dec__ordata_rslt; // 32 bit в атаче скрин стандарта Quote Share this post Link to post Share on other sites More sharing options...
ilkz 0 September 5, 2014 Posted September 5, 2014 (edited) · Report post судя по коду port_map и port_sizes связаны однозначно (позиционно через generate), тогда какой смысл вводить 2 переменных, рискуя ошибиться (port_map постоянно увеличивается, в зависимости от port_size) если это можно рассчитать по месту ? а у вас нет произвольного числа параметров, у вас есть вектор port_sizes, длинна которого определенна в момент передачи параметра и nports который тоже определен при передаче параметра до создания параметра port_list. Если будут проблемы с синтезом или пониманием синтезатора, то сделайте красивый финт. А именно, old-style Verilog 95 объявление, позволяет использовать в качестве разрядностей векторов localparam. Т.е. по сути, задавать через параметр нужно только nports и port_sizes. Остальное будут вычисляемые параметры. Если задать только два параметра (nports и port_sizes), то при итерировании в цикле да - мы сможем достать из вектора нужный размер для нужного порта. Но как посчитать смещение для этого порта, ведь нужно держать где-то сумму всех предыдущих размеров? Основная проблема-то именно в этом. А так ваше предложение было бы почти идеальным решением. А совсем идеальным оно станет, имхо, если удастся обойтись только одним параметром - port_sizes, а все остальное - будет вычисляемым. P.S.: Т.е., в идеале нужно получить что-то такое: parameter nports = 8, parameter port_sizes = { 8'd6, 8'd1, 8'd8, 8'd4, 8'd2, 8'd3, 8'd2, 8'd1}, ... localparam current_port_pos = 0; generate for(i = 0; i < nports; i = i + 1) begin: port localparam current_port_pos = current_port_pos + port_sizes[i*8 +: 8] * 8; localparam current_port_size = port_sizes[i*8 +: 8] * 8; // и тогда доступ к порту i будет таким: // datain[current_port_pos +: current_port_size] end endgenerate , но верилог так не разрешает, т.к. получается переопределение константного параметра, что недопустимо. ________________________________________________________________________________ _______________________________ ISE 14.7 ест и не давиться Квартус очень даже давится: output [15:0] trx_data_out, input [15:0] data_from_trx ... assign trx_data_out[15:0] = data_from_trx[0:15]; выхлоп: Error (10198): Verilog HDL error at pcm_test_hw.v(59): part-select direction is opposite from prefix index direction Error (10784): HDL error at pcm_test_hw.v(16): see declaration for object "data_from_trx" Error (12153): Can't elaborate top-level user hierarchy Но если вручную расписать побитово через assign, то все будет работать. Edited September 5, 2014 by ilkz Quote Share this post Link to post Share on other sites More sharing options...
des00 27 September 5, 2014 Posted September 5, 2014 · Report post Если задать только два параметра (nports и port_sizes), то при итерировании в цикле да - мы сможем достать из вектора нужный размер для нужного порта. Но как посчитать смещение для этого порта, ведь нужно держать где-то сумму всех предыдущих размеров? Основная проблема-то именно в этом. module data_packer #( parameter nports = 8, parameter port_sizes = { 8'd6, 8'd1, 8'd8, 8'd4, 8'd2, 8'd3, 8'd2, 8'd1}, parameter max_port_size = 128 // max port size, bytes ) ( datain, port_ready, reset, clk, mode, byte, byte_ready, data_packed ); //------------------------------------------------------------------------------------------------------ // oops //------------------------------------------------------------------------------------------------------ localparam port_map = get_port_map(nports); localparam total_bits_len = get_ports_list(nports) * 8; function [max_port_size*8-1 : 0] get_port_map (input integer nports); integer i, pipa; begin pipa = 0; get_port_map = 1'b0; // unsigned extend for (i = 0; i < nports; i = i + 1) begin get_port_map[i*8 +: 8] = pipa; pipa = pipa + port_sizes[i*8 +: 8]; end end endfunction function integer get_ports_list (input integer nports); integer i; begin get_ports_list = 0; for (i = 0; i < nports; i = i + 1) begin get_ports_list = get_ports_list + port_sizes[i*8 +: 8]; end end endfunction //------------------------------------------------------------------------------------------------------ // //------------------------------------------------------------------------------------------------------ input [total_bits_len - 1 : 0] datain; input [nports - 1 : 0] port_ready; input reset; input clk; input mode; // 0 - forced mode (any port_ready[*] signal raise serialization), // 1 - wait mode (packer will be wait for all port_ready[*] signals before serialization, // port_ready[*] signals can come in any order and time) output reg [7:0] byte; output reg byte_ready; output reg data_packed; bla-bla-bla Какая проблема ? :) Квартус очень даже давится: правильно давиться, а спор с уважаемым Golikov A. о другом: использование +: и -: может применяться к векторам определенным в любом порядке. Quote Share this post Link to post Share on other sites More sharing options...
ilkz 0 September 5, 2014 Posted September 5, 2014 · Report post Какая проблема ? :) Ух е-мое как изящно олд-стайл нагнул нью-стайл :twak: . Проверил на моделяторе и на железе - все синтезируется и работает как задумано. Класс. Век живи, век учись. B) Quote Share this post Link to post Share on other sites More sharing options...
des00 27 September 5, 2014 Posted September 5, 2014 · Report post Век живи, век учись. B) :) до кучи, при использовании такого стиля описания, возможно красивое решение файла параметров по умолчанию. Т.е.:создаете файл например parameters.vh, описываете в нем ваши параметры (в том числе с функциями преобразования), подключаете его в теле модуля сразу после секции портов(секцию параметров не трогаете). И так например во всем проекте. В итоге у вас есть файл параметров со значениями по умолчанию для всего проекта, при этому в любом инстансе модуля параметр может быть изменен индивидуально для модуля, не трогая все остальные инстансы. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 September 5, 2014 Posted September 5, 2014 · Report post assign iram_rdata[0*32 +: 32] = oram_addr[0] ? N__ordata_rslt[32 +: 32] : N__ordata_rslt[0 +: 32]; а так? assign iram_rdata[31 : 0] = oram_addr[0] ? N__ordata_rslt[32 +: 32] : N__ordata_rslt[0 +: 32]; и как следствие reg [31:0] Data; .... Data <= oram_addr[0] ? N__ordata_rslt[32 +: 32] : N__ordata_rslt[0 +: 32]; И я не в коем случае не спорю%) я просто помню что где-то я воткнулся в эту не удобность, а вот где не помню... до кучи, при использовании такого стиля описания, возможно красивое решение файла параметров по умолчанию. Т.е.:создаете файл например parameters.vh, описываете в нем ваши параметры (в том числе с функциями преобразования), Во-во, у меня так знакомый так в проекте сделал, теперь нельзя просто выдрать модуль из проекта, надо еще параметры переносить или этот файл с собой тащить. Палка о 2 концах... Ух е-мое как изящно олд-стайл нагнул нью-стайл Век живи, век учись. Недавно кто-то спрашивал про generate и там SM говорил что основное отличие генерейта в том что он реально генерит текст, и потому у него не может быть накапливающегося параметра в цикле от итерации к итерации, это как раз очень хороший пример различия простого for и generate. в функция можно использовать for без генерайта, и следовательно get_ports_list = 0; for (i = 0; i < nports; i = i + 1) begin get_ports_list = get_ports_list + port_sizes[i*8 +: 8]; end get_ports_list от итерации к итерации сохраняет свое "вычисленное" значение. А в генерайте он лишь текст, и параметр, и потому цикл развернулся в кучу строчек вида localparam current_port_pos = current_port_pos + port_sizes[i*8 +: 8] * 8; то есть в определение константы от константы которой еще нет... интересно попробовать так integer current_port_pos = 0; generate for(i = 0; i < nports; i = i + 1) begin: port current_port_pos = current_port_pos + port_sizes[i*8 +: 8] * 8; .... по идее тоже должно сработать... правильно давиться, а спор с уважаемым Golikov A. о другом: использование +: и -: может применяться к векторам определенным в любом порядке. еще раз все перечитал. Правильно ли я понимаю: если мы берем reg [15:0] Data; то мы не можем делать Data[0:15] , Data[7:10] и так далее... но можем Data[0 +: 16], Data [7 +: 4]? почему то мне казалось что во втором случае тоже ругань была... И да я понял главная моя ошибка, не в моменте присвоения, а в выборе куска вектора в другом порядке нежели при объявлении... вот где я всех запутал Quote Share this post Link to post Share on other sites More sharing options...
des00 27 September 5, 2014 Posted September 5, 2014 · Report post а так? и как следствие assign iram_rdata[31 : 0] = oram_addr[0] ? N__ordata_rslt[31 -: 32] : N__ordata_rslt[0 +: 32]; ISE 14.7 собирает без проблем Во-во, у меня так знакомый так в проекте сделал, теперь нельзя просто выдрать модуль из проекта, надо еще параметры переносить или этот файл с собой тащить. Палка о 2 концах... если вырвали из SVN, от какая разница один или 2 файла. если взяли себе в проект, то потратить 5 минут на копипаст не вижу сложностей. еще раз все перечитал. Правильно ли я понимаю: если мы берем reg [15:0] Data; то мы не можем делать Data[0:15] , Data[7:10] и так далее... но можем Data[0 +: 16], Data [7 +: 4]? Да Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 September 5, 2014 Posted September 5, 2014 · Report post все понятно, это приятно... А порядок бит какой останется, как в объявлении? то есть в случае reg [31 : 0] Data1 reg [0 : 31] Data2 Data1[3 +: 2] == Data1 [4:3] Data2[3 +: 2] == Data2 [3:4] это опасно для понимания, может стать причиной ошибок... Или же порядок бит будет как указан? если вырвали из SVN, от какая разница один или 2 файла. если взяли себе в проект, то потратить 5 минут на копипаст не вижу сложностей. взять себе в проект, улучшить и вернуть, или когда там улучшиться взять себе опять вот где были сложности. Файл тащить там какие то варнинги сыпались, да и проект по идиологии был что все параметры были в модулях, а этот модуль выбивается. А если дописать параметры внутрь, то любой перенос надо не забывать их вставлять - убирать. В общем проблемы как всегда не в технологии, а в идиологии, если все проекты делать с внешним файлом констант - то вопросов нет. Quote Share this post Link to post Share on other sites More sharing options...
des00 27 September 5, 2014 Posted September 5, 2014 · Report post reg [31 : 0] Data1 reg [0 : 31] Data2 Data1[3 +: 2] == Data1 [4:3] Data2[3 +: 2] == Data2 [3:4] да, будет именно так. потому что порядок вектора оговорен стандартом vector[msb : lsb], а вот индексация вектора, с точки зрения направления может быть любой. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 September 5, 2014 Posted September 5, 2014 · Report post ок спасибо. Quote Share this post Link to post Share on other sites More sharing options...
ilkz 0 September 16, 2014 Posted September 16, 2014 · Report post !!! Hotfix !!! В модуле обнаружилась веселая ошибка, приводящая к тому, что при использовании нескольких портов Квартус ругался. Ну и еще по мелочи пара исправлений. Выкладываю обновленный код.`include "timescale.v" module data_packer #( parameter nports = 8, parameter port_sizes = {8'd6, 8'd1, 8'd8, 8'd4, 8'd2, 8'd3, 8'd2, 8'd1}, parameter max_port_size = 8 // max port size, bytes ) ( datain, port_ready, reset, clk, mode, // 0 - forced mode (any port_ready[*] signal raise serialization), // 1 - wait mode (packer will be wait for all port_ready[*] signals before serialization, // port_ready[*] signals can come in any order and time) byte, byte_ready, data_packed ); function [max_port_size*nports*8-1 : 0] get_port_map (input integer nports); integer i, tmp; begin tmp = 0; get_port_map = 1'b0; // unsigned extend for (i = 0; i < nports; i = i + 1) begin get_port_map[i*8 +: 8] = tmp; tmp = tmp + port_sizes[i*8 +: 8]; end end endfunction function integer get_ports_list (input integer nports); integer i; begin get_ports_list = 0; for (i = 0; i < nports; i = i + 1) get_ports_list = get_ports_list + port_sizes[i*8 +: 8]; end endfunction localparam port_map = get_port_map(nports); localparam total_bits_len = get_ports_list(nports) * 8; input [total_bits_len - 1 : 0] datain; input [nports - 1 : 0] port_ready; input reset; input clk; input mode; output reg [7:0] byte; output reg byte_ready; output reg data_packed; reg [total_bits_len - 1 : 0] buffer; reg [nports - 1 : 0] ports_stored; reg [$clog2(max_port_size * nports) : 0] byte_cnt, offset; wire all_ports_stored = &ports_stored; wire serialize_en = byte_cnt > 0; wire serialization_done = {byte_ready, serialize_en} == 2'b10; integer n; genvar i, j; generate for(i = 0; i < nports; i = i + 1) begin: port localparam port_pos = port_map[i*8 +: 8] * 8; localparam port_size = port_sizes[i*8 +: 8] * 8; always @(posedge clk, posedge reset) begin if(reset) begin buffer[port_pos +: port_size] <= 0; ports_stored[i] <= 0; end else begin if(port_ready[i]) begin buffer[port_pos +: port_size] <= datain[port_pos +: port_size]; ports_stored[i] <= 1; end if(byte_ready) ports_stored[i] <= 0; if(serialization_done) buffer[port_pos +: port_size] <= 0; end end end endgenerate always @(posedge clk, posedge reset) begin if(reset) begin byte <= 0; byte_ready <= 0; data_packed <= 0; byte_cnt <= 0; offset <= 0; end else begin for(n = 0; n < nports; n = n + 1) begin if(port_ready[n] & !mode) begin byte_cnt <= port_sizes[n*8 +: 8]; offset <= port_map[n*8 +: 8]; end end if(mode & all_ports_stored) begin byte_cnt <= (total_bits_len >> 3); offset <= 0; end if(byte_cnt > 0) byte_cnt <= byte_cnt - 1; byte <= serialize_en ? buffer[((byte_cnt + offset - 1) * 8) +: 8] : byte; byte_ready <= serialize_en; data_packed <= serialization_done; end end endmodule Quote Share this post Link to post Share on other sites More sharing options...
GAYVER 2 October 8, 2015 Posted October 8, 2015 · Report post а кто может объяснить смысл жтой записи? `define register_port(n) port_sizes[n * 8 +: 8] мы определили глобальный параметр register_port с произвольной размерностью. а что потом делает порт_сайз? он вроде как еще не определен... Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 October 8, 2015 Posted October 8, 2015 · Report post register_port(n) заменить на port_sizes[n * 8 +: 8] Quote Share this post Link to post Share on other sites More sharing options...
gotcha 0 October 8, 2015 Posted October 8, 2015 · Report post Макрофункция, которую обрабатывает препроцессор. Препроцессор всегда просто заменяет один текст на другой, из-за этого можно получить сюрпрайз-сюрпрайз (наприм. если n - арифметическое выражение). Хороший документ на эту тему http://www.veripool.org/papers/Preproc_Goo...Bos10_paper.pdf Quote Share this post Link to post Share on other sites More sharing options...
ilkz 0 October 12, 2015 Posted October 12, 2015 (edited) · Report post GAYVER, это макрос, который позволяет упростить определение параметра port_list (см. пример использования в самом первом посте). Без этого макроса было бы localparam port_list = port_sizes[0 +: 8] + port_sizes[8 +: 8] + port_sizes[16 +: 8]; соответственно, надо помнить про индексы, высчитывать их. Это муторно. Макрос позволяет это действо скрыть: localparam port_list = `register_port(0) + `register_port(1) + `register_port(2); Кроме того, в последней версии кода этот параметр вообще ушел и никаких дополнительных макросов не требуется. Там использование гораздо проще: data_packer dp ( .reset (reset), .clk (sys_clk), .mode (mode), .datain ({port2, port1, port0}), .port_ready (rdy_port), .byte (), .byte_ready (), .data_packed () ) dp.nports = 3, // задаем количество используемых портов dp.port_sizes = {8'd3, 8'd8, 8'd6}, // задаем разрядности каждого порта dp.max_port_size = 8; // разрядность самого толстого используемого порта (в нашем случае 8, но можно задать с запасом) gotcha, сюрпрайз можно словить, если писать не аккуратно и использовать не так как задумано разработчиками. Но в целом Вы правы, с вычисляемыми макросами надо быть очень осторожным, особенно при их разработке. Edited October 12, 2015 by ilkz Quote Share this post Link to post Share on other sites More sharing options...