Jump to content

    

numeric_std

1 hour ago, Timmy said:

А вот с Верилогом, кажется, придётся мудрить.

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

Ну а если призвать на помощь макросы (хотя многие их не любят) то будет так

  bit [7 : 0] a, a1;
  bit [3 : 0] b, b1;

  bit [15 : 0] c, c1;

  assign c = ($size(c) > ($size(a) + $size(b))) ? (a*b) <<< ($size(c) - ($size(a) + $size(b))) :
                                                  (a*b) >>> ($size(a) + $size(b) - $size(c)) ;

  `define align_left(a, b, c)                                                                             \
    ($size(c) > ($size(a) + $size(b))) ? (a * b) <<< ($size(c) - ($size(a) + $size(b))) : \
                                         (a * b) >>> ($size(a) + $size(b) - $size(c))     \

  assign c1 = `align_left(a1, b1, c1);

 

Share this post


Link to post
Share on other sites
1 hour ago, Timmy said:

другую переменную произвольной разрядности, с выравниванием по старшим битам

Ну во-первых я изначально сказал, что в Верилоге операции с векторами (сдвиги, перекручивания и т.п.) ИМХО сложнее VHDL'ных.

Во-вторых можно расписать вот так:

localparam int p_mul_len = ($bits(a_inp) + $bits(b_inp));
logic [p_mul_len - 1 : 0] r_temp;

assign r_temp = a_inp * b_inp;

assign c_out = {<<p_mul_len{r_temp}};

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

В-третьих, у меня Ваш код VHDL не захотел синтезироваться. Видно я не нашёл библиотеки с align_left функцией. На Верилоге всё в стандарте съедается.

18 minutes ago, des00 said:

арифметический сдвиг влево или вправо

Не арифметический, а логический. Обрезать - вроде как нулями добить :smile:

Share this post


Link to post
Share on other sites
3 minutes ago, Nick_K said:

Не арифметический, а логический. Обрезать - вроде как нулями добить :smile:

Обрезать - убрать младшие биты из большего при присвоении к меньшему, оставив на месте старший не знаковый бит. Добивают когда нужно масштабировать при присвоении меньшего к большему, оставив в силе старший не знаковый бит, При сдвиге влево, арифметический и логический сдвиги одинаковы.

Share this post


Link to post
Share on other sites
22 minutes ago, des00 said:

Обрезать - убрать младшие биты из большего при присвоении к меньшему, оставив на месте старший не знаковый бит.

А да, пардоньте запутался. Тогда получается немного красивее у меня:

localparam int p_mul_len = ($bits(a_inp) + $bits(b_inp));
logic [p_mul_len - 1 : 0] r_temp;

assign r_temp = a_inp * b_inp;

assign c_out = r_temp[(p_mul_len - 1) -: $bits(c_out)];

По сравнению с моим первым вариантом. Хотя тут не учтён вариант произведения меньшего чем результат.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now