0

我正在使用 VHDL 构建一个 MP3 解码器,我想让它可合成,因为我知道对于可变大小的循环并从可变位置选择可变大小std_logic_vector也是不可合成的

那么如何使循环可合成以及如何从可std_logic_vector合成中选择可变大小

for j in 0 to switch_point_1-1 loop
      bits:= data(ptr+current+scale_lengths(j)-1 downto ptr+current);
      scalefac(j)(0) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
      scalefac(j)(1) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
      scalefac(j)(2) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
      current := current+ scale_lengths(j);
    end loop;

还有一个

for j in switch_point_s-1 to cb_max loop
      for k in 0 to 2 loop
        -- window
      bits:=data(ptr+current+scale_lengths(j)-1 downto ptr+current);
        scalefac(j)(k) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
        current := current+ scale_lengths(j);
      end loop;
    end loop;

这是我拥有的循环之一,其中有一个选择bits:=data(ptr+current+scale_lengths(j)-1 downto ptr+current);也是不可合成的,我怎样才能使它们可合成?

完整代码:

    library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use ieee.numeric_std.all;
use std.textio.all;
use work.txt_util.all;
--use txt_util.all;
 entity extract_main is
port(
  data:in std_logic_vector(4095 downto 0);
  en: in std_logic;
gr,clk:in std_logic;
enabled:in std_logic;
scsfi:in std_logic_vector(20 downto 0);
ptr: in integer;
windows_switching: in std_logic;
block_type: in std_logic_vector(1 downto 0);
mixed_block_flag: in std_logic;
part2_3_length: in std_logic_vector(11 downto 0);
slen1,slen2: in integer;
saved_scalefac_in: in integer;
saved_scalefac_out: out integer;
ptr_out: out integer;
enablenext:out std_logic
);
end extract_main;

architecture a of extract_main is

  type intarr is array(20 downto 0) of integer;
  type scalef is array(20 downto 0) of intarr;



begin

  process(clk)
    variable scalefac : scalef; 
    variable scale_lengths : intarr;
    variable mainInfoBegin,mainInfoSize : integer;
    variable blockType : integer;
    variable part2_length :integer;
    variable switch_point_1: integer;
    variable switch_point_s: integer;
    variable cb_max : integer;
    variable current: integer:=0; -- iterator on data
    variable it: integer;
    variable bits: std_logic_vector(3 downto 0):="0000";
    variable ptrout: integer;
    begin
      if enabled ='1' then
      --size of main data
      if falling_edge(clk) then
        if en = '1' then
      mainInfoSize := to_integer(UNSIGNED(part2_3_length));

      if windows_switching = '0' then
        blockType := 0;
      else
        blockType := to_integer(UNSIGNED(block_type));
      end if;

      if blockType = 2 and mixed_block_flag = '1' then
        part2_length := 17 * slen1 + 18 * slen2;
        scale_lengths(16) :=slen2;
        scale_lengths(15) :=slen2;
        scale_lengths(14) :=slen2;
        scale_lengths(13) :=slen2;
        scale_lengths(12) :=slen2;
        scale_lengths(11) :=slen2;
        scale_lengths(10) :=slen1;
        scale_lengths(9) :=slen1;
        scale_lengths(8) :=slen1;
        scale_lengths(7) :=slen1;
        scale_lengths(6) :=slen1;
        scale_lengths(5) :=slen1;
        scale_lengths(4) :=slen1;
        scale_lengths(3) :=slen1;
        scale_lengths(2) :=slen1;
        scale_lengths(1) :=slen1;
        scale_lengths(0) :=slen1;
        cb_max := 16;
        switch_point_1 := 8;
        switch_point_s := 9;
      elsif blockType = 2 and mixed_block_flag = '0' then
        part2_length := 18 * slen1 + 18 * slen2;
         scale_lengths(11) :=slen2;
        scale_lengths(10) :=slen2;
        scale_lengths(9) :=slen2;
        scale_lengths(8) :=slen2;
        scale_lengths(7) :=slen2;
        scale_lengths(6) :=slen2;
        scale_lengths(5) :=slen1;
        scale_lengths(4) :=slen1;
        scale_lengths(3) :=slen1;
        scale_lengths(2) :=slen1;
        scale_lengths(1) :=slen1;
        scale_lengths(0) :=slen1;
        switch_point_1 := 0;
        switch_point_s := 1;
        cb_max := 11;
    else
        part2_length := 11 * slen1 + 10 * slen2;
        --scalefactor_bands(20 downto 11) <= slen2;
        --scalefactor_bands(10 downto 0)<= slen1;
        scale_lengths(20) :=slen2;
        scale_lengths(19) :=slen2;
        scale_lengths(18) :=slen2;
        scale_lengths(17) :=slen2;
        scale_lengths(16) :=slen2;
        scale_lengths(15) :=slen2;
        scale_lengths(14) :=slen2;
        scale_lengths(13) :=slen2;
        scale_lengths(12) :=slen2;
        scale_lengths(11) :=slen2;
        scale_lengths(10) :=slen1;
        scale_lengths(9) :=slen1;
        scale_lengths(8) :=slen1;
        scale_lengths(7) :=slen1;
        scale_lengths(6) :=slen1;
        scale_lengths(5) :=slen1;
        scale_lengths(4) :=slen1;
        scale_lengths(3) :=slen1;
        scale_lengths(2) :=slen1;
        scale_lengths(1) :=slen1;
        scale_lengths(0) :=slen1;
        cb_max := 20;
      end if;


      if blockType = 2 and windows_switching = '1' then
        for j in 0 to switch_point_1-1 loop
         -- it:=0;
          --for e in ptr+current to ptr+current+scale_lengths(j)-1 loop
           -- bits(it) := ram(e)(0);
            --it := it+1;
          --end loop;
          bits:= data(ptr+current+scale_lengths(j)-1 downto ptr+current);
          scalefac(j)(0) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
          scalefac(j)(1) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
          scalefac(j)(2) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
          current := current+ scale_lengths(j);
        end loop;
        for j in switch_point_s-1 to cb_max loop
          for k in 0 to 2 loop
            -- window
         --   it:=0;
         -- for e in ptr+current to ptr+current+scale_lengths(j)-1 loop
         --   bits(it) := ram(e)(0);
         --   it := it+1;
          --end loop;
          bits:=data(ptr+current+scale_lengths(j)-1 downto ptr+current);
            scalefac(j)(k) := to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
            current := current+ scale_lengths(j);
          end loop;
        end loop;
      else
        for j in 0 to 20 loop
          if gr ='0' or scsfi(j) ='0' then
           -- it:=0;
           -- for e in ptr+current to ptr+current+scale_lengths(j)-1 loop
           --   bits(it) := ram(e)(0);
            --  it := it+1;
            --end loop;
            bits:=data(ptr+current+scale_lengths(j)-1 downto ptr+current);
            scalefac(j)(0):= to_integer(UNSIGNED(bits(scale_lengths(j)-1 downto 0)));
            current := current+ scale_lengths(j);
          else
            scalefac(j)(0):= saved_scalefac_in;
          end if;
        end loop;
        if gr ='1' then
          if scsfi(0) /= '0' or scsfi(6) /='0' or scsfi(11)/='0' or scsfi(16)/='0' then
            saved_scalefac_out<=scalefac(0)(0);
          end if;

        end if;
      end if;
      ptrout:=ptr+current;
      ptr_out<=ptrout;
      enablenext<='1';
    end if;
    end if;
  else enablenext<='0';
    end if;
    end process;

end;
4

1 回答 1

0

有了代码的必要部分,我们就可以开始提供帮助了。

现在很清楚,循环范围有上限,尽管完整的代码会竭尽全力隐藏它们。但是,循环范围必须受限于循环变量用于寻址固定大小的数组这一事实。

首先:是否有充分的理由反向处理您的整数数组?我暂时不假设,并稍微简化一下。其次,我将假设 intarr 和 scalef 的长度是依赖的;同样,这可能不是真的,但如果是这样,事情就会变得更简单。

现在我将关键声明写成:

  subtype index is natural range 0 to 20;
  type intarr is array(index) of integer;
  type scalef is array(index) of intarr;

然后

  process(clk)
    variable scalefac : scalef; 
    variable scale_lengths : intarr;
    variable switch_point_1: index;
    variable switch_point_s: index;

在这一点上,这些变量的界限是显而易见的......

 if blockType = 2 and mixed_block_flag = '1' then
    scale_lengths(11 to 16) := (others => slen2);
    scale_lengths(0 to 10)  := (others => slen1);

scale_lengths(0 to 10) := (0 to 10 => slen1);
scale_lengths := (0 to 10 => slen1, 11 to 16 => slen2, others => default_value); 取决于您想对未初始化的条目做什么。
不是因为它是可合成的,而是因为它节省了大量代码......

我们现在可以处理这些循环:

使它们的界限“局部静态”,即仅从这个单元就可以确定和确定。由于我们有一个方便且正确的边界定义,

for j in 0 to switch_point_1-1 loop
   ...
end loop;

现在变成

for j in index'range loop
   if j <= switch_point_1-1 then
      ...
   end if;
end loop;

这可能是可综合的,具体取决于循环体动作。

于 2013-04-26T18:43:26.207 回答