Перейти к содержанию
    

преобразование int32 в int16 на verilog

Всем доброго дня.

Надо по сути 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

может есть способ элегантнее? Заранее спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, Halfback said:

может есть способ элегантнее? Заранее спасибо.

нет. у вас есть floor/ceil/round вот их в рукопашку и выбирайте исходя из задач

PS. деление на 2^N современные синтезаторы распознают, некоторые распознают и честное деление, а некоторые даже округление правильное делают

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 minutes ago, Halfback said:

по сути это будет 

outdata_reg <= indata/65536; 

Раз так, то почему нельзя просто записать ?

outdata_reg[15:0] <= indata[31:16];

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, dimka76 said:

Раз так, то почему нельзя просто записать ?


outdata_reg[15:0] <= indata[31:16];

 

Это floor, округление к нулю для положительных чисел и к минус бесконечности для отрицательных. Может привести к паразитному смещению, при накоплении.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 минут назад, dimka76 сказал:

Раз так, то почему нельзя просто записать ?


outdata_reg[15:0] <= indata[31:16];

 

на все отрицательные числа от -1 до -65355 результат будет "-1" а д.б. "0".

кому это не критично - скорее всего так и делают.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Halfback said:

на все отрицательные числа от -1 до -65355 результат будет "-1" а д.б. "0".

кому это не критично - скорее всего так и делают.

когда ковырялся в теме округления, то ИМХО главное принять решение что делать с округлением точки 0.5. Ваш код например округляет 1.5 к 1, а не 2.0. Поэтому и написал что надо определиться что именно нужно по ТЗ. Если просто нужно округление положительных и отрицательных чисел к нулю, то можно просто прибавить к результату знаковый разряд. Будет чуть меньше сложений. Но 0.5 округляться будет не корректно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

экстраполировал предоставленный вариант в конвертор 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  

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

des00

Спасибо, интересно.

Посмотрев Ваш код я не понял почему Вы так делаете 

outdata = indata >>> 8;

а не так 

outdata = indata >> 8;

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

26 minutes ago, Halfback said:

des00

Спасибо, интересно.

Посмотрев Ваш код я не понял почему Вы так делаете 


outdata = indata >>> 8;

а не так 


outdata = indata >> 8;

 

 

Очевидно же - это арифметический сдвиг, для сохранения знакового разряда (заполнять 1-цами или нулями, в зависимости от старшего бита)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

А я слышал про такой вариант - сдвиг и суммирование старшего отбрасываемого бита.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

31 minutes ago, Lmx2315 said:

А я слышал про такой вариант - сдвиг и суммирование старшего отбрасываемого бита.

Только при этом надо проверять сдвинутое число на  максимальное положительное  0x7FFF,  а  иначе  можно получить проблему с переполнением.

 

Удачи! Rob. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 минуту назад, RobFPGA сказал:

Приветствую!

Только при этом надо проверять сдвинутое число на  максимальное положительное  0x7FFF,  а  иначе  можно получить проблему с переполнением.

 

Удачи! Rob. 

если применяем для DSP обработки то можно не проверять, обычно обработка идёт с запасом до верхнего края, а округления происходят в конце обработки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

26 minutes ago, Lmx2315 said:

если применяем для DSP обработки то можно не проверять

???  :shok:  

То есть на  входе + 0x7FFF_8000  вроде и с запасом,  а на выходе - 0x8000   :wacko2: и можно не проверять ....   

 

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 минуты назад, RobFPGA сказал:

Приветствую!???

  :shok:  То есть на  входе + 0x7FFF_8000  вроде и с запасом,  а на выходе - 0x8000   :wacko2: и можно не проверять ....   

между 0x7fff где будет переполнение и 0x7ffe где нет переполнения - 0.000265 дб разницы , вот при таком запасе можно и не проверять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 hours ago, Lmx2315 said:

точно, получится тот же floor(x+0.5)

20 hours ago, RobFPGA said:

Только при этом надо проверять сдвинутое число на  максимальное положительное  0x7FFF,  а  иначе  можно получить проблему с переполнением.

добавить бит к сумме и проверить 01 комбинацию старших двух бит. может быть будет чуть быстрее чем весь вектор ANDить

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...