Kapsik 0 30 июля, 2019 Опубликовано 30 июля, 2019 · Жалоба Хочу написать максимально параметризорованный синтезируемый модуль. Вход модуля это вектор произвольной длины: input wire [DATA_WIDTH-1:0] data[VECT_WIDTH]; Необходимо производить операции с парами входных wire, например логическое &. Пары "нулевой с первым", "второй с третьим" и тд. Результат также представляют собой вектор, с ним проделываем ту же операцию. Так продолжается пока вектор не выродится в одно число. Spoiler Результат каждой логической операции записывается в регистр. Я хочу создать "reg S" зависящий от входной длины вектора, дальше в циклах записать что надо в этот регистр уже будет не сложно. Я общем виде S может любой. S[][][][][]... Написал следующий код: //генерируем массив регистров genvar gen_result; generate begin for ( gen_result = 1; gen_result < VECT_WIDTH/2; gen_result++ ) begin:gen_result_var reg [DATA_WIDTH-1:0] result[(VECT_WIDTH/2)]; //для примера просто (VECT_WIDTH/2), вообще надо при каждом проходе делить еще на 2 end end endgenerate //записываем один пробный регистр always @( posedge clk ) gen_summ_var[0].result[0] <= 1; В ModelSim все выглядит как надо. Но Quartus ругается. Во всей видимости мои хотелки не синтезируемы. Подскажите, как лучше решить такую задачу? Вдохновение черпал отсюда: https://www.hdlworks.com/hdl_corner/verilog_ref/items/Genvar.htm Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nice_vladi 1 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба 6 hours ago, Kapsik said: Написал следующий код: //генерируем массив регистров genvar gen_result; ... for ( gen_result = 1; gen_result < VECT_WIDTH/2; gen_result++ ) ... end endgenerate //записываем один пробный регистр always @( posedge clk ) gen_summ_var[0].result[0] <= 1; В ModelSim все выглядит как надо. Но Quartus ругается. Во всей видимости мои хотелки не синтезируемы. Сразу в глаза бросилось, что у вас блок называется gen_result_var, а записывать пробный регистр вы пытаетесь в gen_summ_var. Может быть, я не правильно понял, но выглядит ошибкой. А вообще, можно посчитать, сколько вам нужно регистров S и создать массив типа: reg [DATA_WIDTH-1:0] result [N], где N - полное количество требуемых регистров S на вашей схеме. После этого будет 100% правильный массив, удобный для отладки (легко смотреть каждый адрес). И потом уже извращаться в циклах с адресацией в этом массиве. Отдать под первый слой первые N/2 элементов массива, под второй слой N/2+N/4 и т.д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба 9 hours ago, Kapsik said: reg [DATA_WIDTH-1:0] result[(VECT_WIDTH/2)]; Вы просто объявляете переменную result в блоке generate. Этого делать не обязательно. Можно сразу инициализировать переменную нужной длинны на основе параметра. А вот собственно в generate нужно делать присваивание (или я не так понял вашу задумку) Второе - ваш шифратор (в общем понимании) будет работать только при условии кратности VECT_WIDTH=2^N. В противном случае вы будете терять один элемент в операциях, когда строка не делится на 2 нацело. Третье - не уверен как обстоят дела в Verilog, но для SV лучше не использовать смешинные типы массивов (packed и unpacked). Не то чтобы нельзя, просто не запутывайте себя, при условии что от этого можно избавится (например при описании BRAM - нельзя). В общем виде должно получаться что-то такое: reg [DATA_WIDTH-1:0] data_1_stage [VECT_WIDTH/2]; genvar i; generate begin for (i = 0; i < VECT_WIDTH/2; i++) begin: first_stage_generation data_1_stage[i] = data[i*2] ^ data[i*2+1]; end endgenerate Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kapsik 0 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба 4 hours ago, nice_vladi said: Сразу в глаза бросилось, что у вас блок называется gen_result_var, а записывать пробный регистр вы пытаетесь в gen_summ_var. Может быть, я не правильно понял, но выглядит ошибкой. Опечатался когда переносил код на форум =( ошибка будет и при совпадении имен. 4 hours ago, nice_vladi said: А вообще, можно посчитать, сколько вам нужно регистров S и создать массив типа: reg [DATA_WIDTH-1:0] result [N], где N - полное количество требуемых регистров S на вашей схеме. Тоже об этом думал, но никак не мог сообразить как мне хитрые вычисления засунуть в range регистра. Ведь это получается как минимум цикл с делением и аккумулятором, в параметр таки вычисления уже не засунуть. А сейчас вернулся к этой идее, написал функцию расчета общего количества необходимых регистра и вызываю ее при декларировании параметра, такой способ работает. Но у него есть и минусы. Сейчас я хочу делать логическую операцию которая не влияет на разрядность числа. Но если строить такой конвейер с умножением или сложением, разрядность каждого следующего "слоя" растет. Если использовать метод объявления длинного вектора под все вычисления все их надо делать одной, максимальной разрядности. При способе с использованием generate у меня получилось создавать векторы разной длины с разными разрядностями, но к сожалению только в симуляторе... То есть если говорить в самом широком смысле, то идея была нагенерить вот таких регистров у которых варьируется как длина так и разрядность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nice_vladi 1 31 июля, 2019 Опубликовано 31 июля, 2019 · Жалоба 36 minutes ago, Kapsik said: ... Если использовать метод объявления длинного вектора под все вычисления все их надо делать одной, максимальной разрядности ... Все равно компилятор ненужные разрядности посокращает. Так что, думаю, можно смело объявлять максимальные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться