Nick_K 0 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба Здравствуйте, настал тут у меня момент отупения (всю неделю). Нужно реализовать асинхронный энкодер для параметризируемого регистра сдвига. Нужно контролировать фронт сигнала - то есть перепад подряд идущих единиц, пока не встретится стабильный ноль. Я написал такую функцию для преобразования входного потока, но она синтезируется в какую-то ерунду: function logic my_encoder( input logic [6 : 0] i_encode ); casez (i_encode) // приоритетный выбор "до первого ноля" 7'b??????1: return 3'b000; 7'b?????10: return 3'b001; 7'b????100: return 3'b010; 7'b???1000: return 3'b011; 7'b??10000: return 3'b100; 7'b?100000: return 3'b101; 7'b1000000: return 3'b110; default: return 3'b111; endcase Так как функции не параметризируются, а входной регистр может быть разной длинны, приходится по-рагульному встраивать в код: parameter p_length = 3; // анализ 3-х бит данных logic [3 : 0] r_data; // иходной вектор wire logic [1 : 0] r_data_encoded; // выходные декодированные данные assign {r_data_encoded} = my_encoder(r_data[p_length - 1 : 0]); Приоритетный перебор "менял местами" - ничего не помогло (перечисление наоборот). Подскажите возможное решение. А лучше почему данный Кейс финтезируется в какой-то бред (у меня всегда 1-й бит r_data_encoded подтянут на землю). З.Ы. Так же пробовал абстрагироваться от остальных значений и детектировать только наиболее раннее значение фронта, результат таков же: casez (i_encode) 7'b??????1: return 3'b000; 7'b?????10: return 3'b001; 7'b????10?: return 3'b010; 7'b???10??: return 3'b011; 7'b??10???: return 3'b100; 7'b?10????: return 3'b101; 7'b10?????: return 3'b110; default: return 3'b111; endcase Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба 13 минут назад, Nick_K сказал: Нужно контролировать фронт сигнала - то есть перепад подряд идущих единиц, пока не встретится стабильный ноль. Делаем так. рисуем автомат, у которого две ветви. Одна из исходного влево - это если 0, другая - вправо, это если 0. Тактируем все системными клоками, поскольку входные импульсы привязываем к ним на самом входе проекта. Чтобы не зависеть от частоты дребезга, даем еще сигнал "разрешения", который и определяет как часто будет срабатывать автомат... Ну и в каждой ветви делаем по 3-5 состояний. Скажем для ветви "0" - если 0, то переход в следующее, а если 1 - то в исходное... Получим фильтр дребезга по фронтам и по просечкам сигналов... Прохождение автомата по последнему состоянию в ветви и даст импульс длительностью в 1 клок, который может быть использован в более верхнем автомате.... Хотите подробнее - могу по скайпу голосом... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба Спасибо, как в схемотехнике это выглядит - я понимаю. Вопрос как это описать на умном SystemVerilog не используя кучу if-else. На VHDL знаю, а с SV достаточно недавно работаю Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба 2 минуты назад, Nick_K сказал: Спасибо, как в схемотехнике это выглядит - я понимаю. Вопрос как это описать на умном SystemVerilog не используя кучу if-else. На VHDL знаю, а с SV достаточно недавно работаю Как описать автомат? В этом проблема? И при чем тут именно SV? Регистровая часть автомата и комбинационная да еще таймер для выдержки времени... Дело то простейшее... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба Приветствую! Для начала поставьте более конкретную задачу - какие комбинации вы хотите детектировать? Что считать фронтом в вашем понимании? В широком регистре перепадов 1->0 может быть несколько - нужны все или только первый? C какой стороны регистра искать фронт? Ну а для "параметризация" функций с векторами можно пользоваться некими особенностями Verilog - автоматическим расширением/усечением разрядности при присвоении. Например нахождение первой 1 справа module test_1 ( input wire clk , input wire [3:0] din_a, input wire [7:0] din_b, output logic [3:0] dou_a, output logic [4:0] dou_b ); localparam MAX_POSSIBLE_WIDTH = 256; function int first_one_from_right (input logic [MAX_POSSIBLE_WIDTH-1:0] din, int din_wh); for (int ii=0; ii<MAX_POSSIBLE_WIDTH; ++ii) begin if (din[ii]==1) begin return ii; end end return din_wh; endfunction always @(posedge clk) begin dou_a <= ($clog2($bits(din_a))+1)'(first_one_from_right(din_a, $bits(din_a))); dou_b <= first_one_from_right(din_b, $bits(din_b)); end endmodule Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба 44 minutes ago, RobFPGA said: Для начала поставьте более конкретную задачу - какие комбинации вы хотите детектировать? Фронт в данной задаче - это когда слева единицы, а справа хотя бы один ноль. Что правее после ноля - не важно, для меня это дребезг, а если ноли слева от единиц - это обычная обрезка входного сигнала. К примеру: 00001111 - данных нет 00001110 - начало приёма 00001100 - продолжение 00001001 - дребезг Если бы не необходимость отсеивания дребезга, то я бы просто сумму унарного кода вычислял. А так загвоздка. За параметризацию входных сигналов я вкурсе, только мне это не сильно подходит, если говорить о функции case. Кстати было бы неплохо понять как параметризировать выходной сигнал (который после return), а также как передавать локальный параметр (или просто параметр) в пакет/package, т.к. функции обычно выношу в пакеты отдельные, для удобства редактирования. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 25 июля, 2019 Опубликовано 25 июля, 2019 · Жалоба Приветствую! Все одно не однозначные/неполные условия: 00001100 - продолжение ... 00110011 - дребезг ? 01100110 - Где фронт ? Увы - SV язык с жесткой типизацией - требует чтобы типы аргументов и возвращаемых значений были определённы на этапе компиляции. Поэтому и приходится закладывать максимальные значения ширины векторов. Ну или как вариант засунуть функции в interface Но это если синтезатор поддерживает такие извраты. interface if_func #(MAX_WH=8); typedef logic [MAX_WH-1:0] din_t; typedef logic [$clog2(MAX_WH):0] dou_t; function dou_t first_one_from_rignt (input din_t din); for (int ii=0; ii<MAX_WH; ++ii) begin if (din[ii]==1) begin return ii; end end return MAX_WH; endfunction endinterface module ... if_func #(.MAX_WH($bits(din_a))) func_if_a (); if_func #(.MAX_WH($bits(din_b))) func_if_b (); ... dou_a <= func_if_a.first_one_from_rignt(din_a); dou_b <= func_if_b.first_one_from_rignt(din_b); .. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 26 июля, 2019 Опубликовано 26 июля, 2019 · Жалоба 17 hours ago, RobFPGA said: 00110011 - дребезг ? 0011 - фронт, остальное мусор 17 hours ago, RobFPGA said: 01100110 - Где фронт ? 011 - фронт 17 hours ago, RobFPGA said: Увы - SV язык с жесткой типизацией - требует чтобы типы аргументов и возвращаемых значений были определённы на этапе компиляции. Спасибо! именно это и навело меня на мысль/решение - я объявлял возвращаемое значение как logic без размеров. Поэтому у меня синтезировало только первый бит выходного значения. Поменял на logic [1:0] и пошло как тёща под лёд ... вобщем пошло Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nice_vladi 3 27 июля, 2019 Опубликовано 27 июля, 2019 · Жалоба On 7/25/2019 at 5:11 PM, Nick_K said: ... wire logic [1 : 0] r_data_encoded; // выходные декодированные данные assign {r_data_encoded} = my_encoder(r_data[p_length - 1 : 0]); ... почему данный Кейс финтезируется в какой-то бред (у меня всегда 1-й бит r_data_encoded подтянут на землю) ... ... casez (i_encode) 7'b??????1: return 3'b000; 7'b?????10: return 3'b001; 7'b????10?: return 3'b010; 7'b???10??: return 3'b011; 7'b??10???: return 3'b100; 7'b?10????: return 3'b101; 7'b10?????: return 3'b110; default: return 3'b111; endcase Функция my_encode возвращает 3 битика (return 3'bXXX), а регистр, в который вы выкладываете этот результат (r_data_encoded) имеет разрядность [1:0] = 2 битика. А если хочется параметризировать - над делать что-то вроде того, что показал @RobFPGA. Ну и все разрядности обязаны быть определены на этапе синтеза. А еще, похоже, что вам просто надо посчитать количество нулей или единиц в слове - можно попробовать погуглить на эту тему, есть разные алгоритмы как для С так и для HDL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 27 июля, 2019 Опубликовано 27 июля, 2019 · Жалоба В 25.07.2019 в 13:11, Nick_K сказал: Так как функции не параметризируются Переходите на VHDL. Там с параметризацией никаких проблем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_sda 0 27 июля, 2019 Опубликовано 27 июля, 2019 · Жалоба В 25.07.2019 в 14:48, Nick_K сказал: Фронт в данной задаче - это когда слева единицы, а справа хотя бы один ноль. Что правее после ноля - не важно, для меня это дребезг, а если ноли слева от единиц - это обычная обрезка входного сигнала. К примеру: 00001111 - данных нет 00001110 - начало приёма 00001100 - продолжение 00001001 - дребезг Если бы не необходимость отсеивания дребезга, то я бы просто сумму унарного кода вычислял. А так загвоздка. За параметризацию входных сигналов я вкурсе, только мне это не сильно подходит, если говорить о функции case. Кстати было бы неплохо понять как параметризировать выходной сигнал (который после return), а также как передавать локальный параметр (или просто параметр) в пакет/package, т.к. функции обычно выношу в пакеты отдельные, для удобства редактирования. На мой взгляд вы всё смешали в кучу. Мухи отдельно, котлеты отдельно - сначала удалите дребезг, а уж потом вылавливайте фронт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_K 0 29 июля, 2019 Опубликовано 29 июля, 2019 · Жалоба On 7/27/2019 at 7:00 AM, nice_vladi said: Функция my_encode возвращает 3 битика (return 3'bXXX), а регистр, в который вы выкладываете этот результат (r_data_encoded) имеет разрядность [1:0] = 2 битика. Я же написал уже, что проблема в объявлении функции: function logic my_encoder( input logic [6 : 0] i_encode ); А должно быть: function [2:0] logic my_encoder( input logic [6 : 0] i_encode ); тогда функция синтезирует правильную ширину выходного вектора на SV. В отличии от VHDL где как-раз размерность и нельзя указывать для функции. On 7/27/2019 at 7:00 AM, nice_vladi said: А еще, похоже, что вам просто надо посчитать количество нулей или единиц в слове - можно попробовать погуглить на эту тему, есть разные алгоритмы как для С так и для HDL. Опять нет. Нужно к каждым двум битам сдвигового регистра прицепить XOR и повесить на чепочку мультиплексоров. Чтобы старший мультиплексор обрезал работу всем остальным. можно реализовать через приоритетный if-else но тогда это получится очень большой кусок кода, с 0 удобочитаемостью и реюзабелльностью. А так на Лутах обычный Энкодер вышел. On 7/27/2019 at 7:20 AM, andrew_b said: Переходите на VHDL. Там с параметризацией никаких проблем. Я с него только слез Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться