Halfback 0 September 7, 2021 Posted September 7, 2021 · Report post Всем доброго дня. Надо по сути 32-разрядное знаковое число сократить до 16-разрядного знакового. по сути это будет outdata_reg <= indata/65536; но поскольку на младших циклонах знак деления штука не экономная то написал так: module conv_sign_32to16 ( input clk, input signed [31:0] indata, output signed [15:0] outdata ); reg [15:0] outdata_reg; always @ (posedge clk) begin outdata_reg <= ((indata + (32'd1<<31)) >> 16) - (16'd1<<15); end //always assign outdata = outdata_reg; endmodule может есть способ элегантнее? Заранее спасибо. Quote Share this post Link to post Share on other sites More sharing options...
des00 9 September 7, 2021 Posted September 7, 2021 · Report post 3 minutes ago, Halfback said: может есть способ элегантнее? Заранее спасибо. нет. у вас есть floor/ceil/round вот их в рукопашку и выбирайте исходя из задач PS. деление на 2^N современные синтезаторы распознают, некоторые распознают и честное деление, а некоторые даже округление правильное делают Quote Share this post Link to post Share on other sites More sharing options...
dimka76 13 September 7, 2021 Posted September 7, 2021 · Report post 20 minutes ago, Halfback said: по сути это будет outdata_reg <= indata/65536; Раз так, то почему нельзя просто записать ? outdata_reg[15:0] <= indata[31:16]; Quote Share this post Link to post Share on other sites More sharing options...
des00 9 September 7, 2021 Posted September 7, 2021 · Report post 2 hours ago, dimka76 said: Раз так, то почему нельзя просто записать ? outdata_reg[15:0] <= indata[31:16]; Это floor, округление к нулю для положительных чисел и к минус бесконечности для отрицательных. Может привести к паразитному смещению, при накоплении. Quote Share this post Link to post Share on other sites More sharing options...
Halfback 0 September 7, 2021 Posted September 7, 2021 · Report post 45 минут назад, dimka76 сказал: Раз так, то почему нельзя просто записать ? outdata_reg[15:0] <= indata[31:16]; на все отрицательные числа от -1 до -65355 результат будет "-1" а д.б. "0". кому это не критично - скорее всего так и делают. Quote Share this post Link to post Share on other sites More sharing options...
des00 9 September 7, 2021 Posted September 7, 2021 · Report post 1 hour ago, Halfback said: на все отрицательные числа от -1 до -65355 результат будет "-1" а д.б. "0". кому это не критично - скорее всего так и делают. когда ковырялся в теме округления, то ИМХО главное принять решение что делать с округлением точки 0.5. Ваш код например округляет 1.5 к 1, а не 2.0. Поэтому и написал что надо определиться что именно нужно по ТЗ. Если просто нужно округление положительных и отрицательных чисел к нулю, то можно просто прибавить к результату знаковый разряд. Будет чуть меньше сложений. Но 0.5 округляться будет не корректно. Quote Share this post Link to post Share on other sites More sharing options...
des00 9 September 8, 2021 Posted September 8, 2021 · Report post экстраполировал предоставленный вариант в конвертор 16 в 8 бит. Так меньше диапазон перебираемых чисел. Ну и добавил к сравнению floor/floor с округлением отрицательных чисел к нулю/round(x) ~= floor(x+0.5) module tb (); initial begin int tmp; int err; logic signed [7 : 0] rslt1, rslt2, rslt3, rslt4; for (int i = -(2**15); i <= 2**15-1; i += 100) begin tmp = $signed(i[15 : 0]); rslt1 = conv_16to8(tmp); rslt2 = floor(tmp); rslt3 = round(tmp); rslt4 = floor2(tmp); if ((rslt1 != rslt2) || (rslt1 != rslt3) || (rslt1 != rslt4)) begin $display("error %0d = %0f", tmp, tmp*1.0/256); $display("conv %0d", rslt1); $display("floor %0d", rslt2); $display("round %0d", rslt3); $display("floor2 %0d", rslt4); err++; end end $display("errs = %0d", err); $stop; end function logic signed [7 : 0] conv_16to8 (input logic signed [15 : 0] indata); logic signed [7 : 0] outdata; // outdata = ((indata + (16'd1<<15)) >> 8) - (8'd1<<7); // return outdata; endfunction function logic signed [7 : 0] floor (input logic signed [15 : 0] indata); logic signed [7 : 0] outdata; // outdata = indata >>> 8; // return outdata; endfunction function logic signed [7 : 0] floor2 (input logic signed [15 : 0] indata); logic signed [7 : 0] outdata; // outdata = indata >>> 8; outdata += (indata < 0) ? 1 : 0; // return outdata; endfunction function logic signed [7 : 0] round (input logic signed [15 : 0] indata); logic signed [8 : 0] outdata; logic signed [16 : 0] tmp; // tmp = indata + 128; outdata = (tmp) >>> 8; if (outdata > 127) begin outdata = 127; end // return outdata[7 : 0]; endfunction endmodule можно сравнить "тяжесть" функции округления и качество результата. Вот несколько интересных точек # error -1368 = -5.343750 # conv -6 # floor -6 # round -5 # floor2 -5 # error -1268 = -4.953125 # conv -5 # floor -5 # round -5 # floor2 -4 # error 28032 = 109.500000 # conv 109 # floor 109 # round 110 # floor2 109 # error 28132 = 109.890625 # conv 109 # floor 109 # round 110 # floor2 109 Quote Share this post Link to post Share on other sites More sharing options...
Halfback 0 September 8, 2021 Posted September 8, 2021 · Report post des00 Спасибо, интересно. Посмотрев Ваш код я не понял почему Вы так делаете outdata = indata >>> 8; а не так outdata = indata >> 8; Quote Share this post Link to post Share on other sites More sharing options...
Nick_K 0 September 8, 2021 Posted September 8, 2021 · Report post 26 minutes ago, Halfback said: des00 Спасибо, интересно. Посмотрев Ваш код я не понял почему Вы так делаете outdata = indata >>> 8; а не так outdata = indata >> 8; Очевидно же - это арифметический сдвиг, для сохранения знакового разряда (заполнять 1-цами или нулями, в зависимости от старшего бита) Quote Share this post Link to post Share on other sites More sharing options...
Lmx2315 0 September 8, 2021 Posted September 8, 2021 · Report post module conv_sign_32to16 ( input clk, input signed [31:0] indata, output signed [15:0] outdata ); reg [15:0] outdata_reg; always @ (posedge clk) begin outdata_reg <= ((indata>>> 16) + (indata[15])); end //always assign outdata = outdata_reg; endmodule А я слышал про такой вариант - сдвиг и суммирование старшего отбрасываемого бита. Quote Share this post Link to post Share on other sites More sharing options...
RobFPGA 8 September 8, 2021 Posted September 8, 2021 · Report post Приветствую! 31 minutes ago, Lmx2315 said: А я слышал про такой вариант - сдвиг и суммирование старшего отбрасываемого бита. Только при этом надо проверять сдвинутое число на максимальное положительное 0x7FFF, а иначе можно получить проблему с переполнением. Удачи! Rob. Quote Share this post Link to post Share on other sites More sharing options...
Lmx2315 0 September 8, 2021 Posted September 8, 2021 · Report post 21 минуту назад, RobFPGA сказал: Приветствую! Только при этом надо проверять сдвинутое число на максимальное положительное 0x7FFF, а иначе можно получить проблему с переполнением. Удачи! Rob. если применяем для DSP обработки то можно не проверять, обычно обработка идёт с запасом до верхнего края, а округления происходят в конце обработки. Quote Share this post Link to post Share on other sites More sharing options...
RobFPGA 8 September 8, 2021 Posted September 8, 2021 · Report post Приветствую! 26 minutes ago, Lmx2315 said: если применяем для DSP обработки то можно не проверять ??? То есть на входе + 0x7FFF_8000 вроде и с запасом, а на выходе - 0x8000 и можно не проверять .... Удачи! Rob. Quote Share this post Link to post Share on other sites More sharing options...
Lmx2315 0 September 8, 2021 Posted September 8, 2021 · Report post 22 минуты назад, RobFPGA сказал: Приветствую!??? То есть на входе + 0x7FFF_8000 вроде и с запасом, а на выходе - 0x8000 и можно не проверять .... между 0x7fff где будет переполнение и 0x7ffe где нет переполнения - 0.000265 дб разницы , вот при таком запасе можно и не проверять. Quote Share this post Link to post Share on other sites More sharing options...
des00 9 September 9, 2021 Posted September 9, 2021 · Report post 21 hours ago, Lmx2315 said: точно, получится тот же floor(x+0.5) 20 hours ago, RobFPGA said: Только при этом надо проверять сдвинутое число на максимальное положительное 0x7FFF, а иначе можно получить проблему с переполнением. добавить бит к сумме и проверить 01 комбинацию старших двух бит. может быть будет чуть быстрее чем весь вектор ANDить Quote Share this post Link to post Share on other sites More sharing options...