2
votes

I have a question related to conversion from numeric_std to std_logic_vector. I am using moving average filter code that I saw online and filtering my ADC values to stable the values.

The filter package code is:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package filterpack is
  subtype number is unsigned(27 downto 0);
  type numbers is array(natural range <>) of number;
  function slv_to_num(signal slv: in std_logic_vector) return number;
  procedure MAF_filter(
    signal x: in    number;
    signal h: inout numbers;
    signal y: out   number
  );
end filterpack;

package body filterpack is

function slv_to_num(signal slv: in std_logic_vector) return number is
  variable x: number := (others => '0');
begin
  for i in slv'range loop
    if slv(i) = '1' then
      x(i+4) := '1';
    end if;
  end loop;
  return x;
end function slv_to_num;

procedure MAF_filter(
    signal x: in    number;
    signal h: inout numbers;
    signal y: out   number
  ) is
begin
  h(0) <= x + h(1);       -- h[n] = x[n] + h[n-1]
  y <= h(0) - h(h'high);  -- y[n] = h[n] - h[n-M]
end MAF_filter;

end package body filterpack;

In my top level file, I call the MAF_filter procedure.

Asign_x: x <= slv_to_num(adc_dat);
Filter:  MAF_filter(x,h,y);

The adc_dat is defined as:

adc_dat : out std_logic_vector (23 downto 0);

I want to convert the output of the MAF_Filter to std_logic_vector (23 downto 0). Can anyone tell how can I convert filter output 'y' to 'std_logic_vector'?

Many Thanks!

2

2 Answers

1
votes

What do you want to do with the 4 extra bits? Your type number has 28 bits, but your signal adc_dat has only 24.

If it's ok to discard them, you could use:

adc_dat <= std_logic_vector(y(adc_dat'range));

Also, is there a reason not to write your function slv_to_num as shown below?

function slv_to_num(signal slv: in std_logic_vector) return number is
begin
  return number(slv & "0000");
end function slv_to_num;
0
votes

The conversion has to solve 2 problems : the type difference you noted, and the fact that the two words are different sizes.

The type difference is easy : std_logic_vector (y) will give you the correct type. Because the two types are related types, this is just a cast.

The size difference ... only you have the knowledge to do that.

adc_dat <= std_logic_vector(y(23 downto 0)) will give you the LSBs of Y - i.e. the value of Y itself, but can overflow. Or as Rick says, adc_dat <= std_logic_vector(y(adc_dat'range)); which is usually better, but I wanted to expose the details.

adc_dat <= std_logic_vector(y(27 downto 4)) cannot overflow, but actually gives you y/16.