宽度不匹配:信号分配的矢量范围可变。为什么以及如何解决?

时间:2015-12-10 09:24:51

标签: vhdl xilinx-ise

ISE 14.7在合成时在后续行返回以下警告,最终导致错误: “宽度不匹配。< temp>宽度为8位,但指定的表达式为128位宽。”

temp <= padding_start_s((((i_pad+1)*8)-1) downto (i_pad*8));

问题似乎与for循环有关。我想要做的是填充N位128位的输入信号。最终收到一个非完整的128位信号,我想检测它最终结束的位置然后添加填充。当然,缺少一些代码,但这应该是相关的东西。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.NUMERIC_STD.all;

library work;
  use work.keccak_globals.all;

entity Keccak_padder is
port (

  clk_i                : in  std_logic;
  data_i               : in std_logic_vector(127 downto 0);
  rst_n                : in std_logic;
  start_i              : in std_logic;
  end_i                : in std_logic;
  state_vector_o       : out std_logic_vector(r-1 downto 0);
  state_vector_valid_o : out std_logic;
  long_message_o       : out std_logic
  );
end Keccak_padder;

architecture Behavioral of Keccak_padder is


signal word_count      : integer range 1 to 16:=1;
signal pad_count       : integer range 0 to 3:=0;
signal i_pad           : integer range 0 to 15;
signal word_count      : integer range 1 to 16:=1;
signal padding_start_s : std_logic_vector(127 downto 0):=(others=>'0');
signal temp            : std_logic_vector(7 downto 0);
constant zero_vector   : std_logic_vector(7 downto 0):=(others=>'0');
signal start_pad       : std_logic;

process(clk_i, rst_n, fsm_state, pad_count, start_pad, padding_start_s)

begin

if rising_edge(clk_i) then

  case fsm_state is
    when IDLE =>
      ...
    when TRANSMIT =>
      ...
    when RECEIVE =>
      if (pad_count = 1) then
        state_vector_o((r-1-(data_i'length * (word_count - 1))) downto (r-(data_i'length * (word_count)))) <= temp;
        pad_count <= 0;
        fsm_state <= IDLE;
        start_pad <= '0';
      elsif (start_pad = '1') then
        temp <= padding_start_s((((i_pad+1)*8)-1) downto (i_pad*8));
        pad_count <= pad_count + 1;
      end if;

      for i in 15 downto 0 loop
        if  (padding_start_s((((i+1)*8)-1) downto ((i)*8)) = zero_vector) then
          i_pad     <= i;
          start_pad <= '1';
          exit;
        end if;
      end loop;
  end case;
end if;
end process;

所以我最终要问的是:我如何找到解决方法,为什么这是一个问题?在信号分配中削减范围是错误的吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

如果没有Minimal, Complete, and Verifiable example,答案就会被击中或遗漏,这是一个综合问题,而不是VHDL语言语法或语义问题。

正如Brian所评论的那样,对于8位宽的值,临时分配是16:1的多路复用,因此可以简化索引。甚至超过布莱恩建议:

    type byte_array_16 is array (15 downto 0) of std_logic_vector (7 downto 0);
    signal padding_bytes:    byte_array_16;
begin

    padding_bytes <= byte_array_16'(
            padding_start_s(127 downto 120), padding_start_s(119 downto 112),
            padding_start_s(111 downto 104), padding_start_s(103 downto  96),
            padding_start_s( 95 downto  88), padding_start_s( 87 downto  80),
            padding_start_s( 79 downto  72), padding_start_s( 71 downto  64),
            padding_start_s( 63 downto  56), padding_start_s( 55 downto  48),
            padding_start_s( 47 downto  40), padding_start_s( 39 downto  32),
            padding_start_s( 31 downto  24), padding_start_s( 23 downto  16),
            padding_start_s( 15 downto   8), padding_start_s(  7 downto   0)
    ); 

TEST1:  -- temp assignment expression
    process
        variable i_pad: integer range 0 to 15; -- overloads signal i_pad
    begin
        for i in 0 to 15 loop
            i_pad := i;
            -- temp <= padding_start_s((((i_pad + 1) * 8) - 1) downto (i_pad * 8));
            temp <= padding_bytes(i_pad);
            wait for 0 ns;  -- temp assignment takes effect next delta cycle
        end loop;
        report "Test 1, temp assignment, no bounds errors";
        wait;
    end process;

对padding_bytes的赋值就像C中的union一样,除了它只有一种方式。它也不会增加硬件负担。

因此,i_pad值确定是来自特定端的优先级编码器,其中一串字节识别器将值与常量zero_vector进行比较。这16个识别器(for循环将在合成中解开)得到优化,只需查找所有'0'。

除了识别器之外,还有一个16到4个优先编码器,用于生成i_pad和start_pad,用于指定任何发现全部为0的识别器。

但是,你选择输入识别器的所有算法都是多毛的。您可以使用相同的单向联合修复它:

FIND_FIRST_ZERO_BYTE:  
    process
    begin
        start_pad <= '0';
        for i in 15 downto 0 loop
          if  padding_bytes(i) = zero_vector then
            i_pad     <= i;
            start_pad <= '1';
            exit;
          end if;
        end loop;
        wait;
    end process;

这消除了因为i_pad是一个信号所需的大量算法。