2

ISE 14.7 at synthesis returns the following warning on the subsequent line which eventually leads to an error: "Width mismatch. <temp> has a width of 8 bits but assigned expression is 128-bit wide."

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

The problem seems to be with the for loop. What I am trying to do is to pad an incoming signal of N multiples of 128 bit. Eventually a non-complete 128 bit signal is received and I want to detect where it eventually ends and then add padding. Certainly, some of the code is missing, but this should really be the relevant stuff.

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;

So eventually what I'm asking is: how do I find a way around this and why is this a problem? Is it wrong to be cutting the range in a signal assignment?

Thanks!

toxUP
  • 103
  • 2
  • 10
  • Wild guess : assuming this all worked as it should in simulation (... it did, right?) it is possible that such an ugly expression is confusing the synthesis tool. In which case the simpler `temp <= padding_start_s((i_pad*8 + 7) downto (i_pad*8));` may work. –  Dec 10 '15 at 18:53
  • Does Brians solution work? Otherwise I could suggest my vectors package to transform your 128 bit vector into a vector of bytes. The package is synthesiable (tested with Quartus-II and ISE 14.7). – Paebbels Dec 10 '15 at 22:12
  • 1
    You may also take a look at [my answer here](http://stackoverflow.com/a/34031307/5466118) on how the coding style of multiplexers affects resource usage and number of paths to analyze for timing. – Martin Zabel Dec 11 '15 at 09:12

1 Answers1

1

Without a Minimal, Complete, and Verifiable example an answer is hit or miss, and this is a synthesis issue instead of VHDL language syntax or semantic issue.

As Brian commented the temp assignment is a 16:1 mux for an 8 bit wide value, it's possible to simplify the indexing. Even more than Brian suggests:

    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;

The assignment to padding_bytes works as like a union in C, except that it's only goes one way. It also adds no hardware burden.

So the i_pad value determination is a priority encoder from a particular end with a bunch of byte recognizers comparing values to constant zero_vector. Those 16 recognizers (the for loop will get unwound in synthesis) get optimized to just look for all '0's.

What you have besides recognizers is a 16 to 4 priority encoder producing i_pad and start_pad, used to specify any recognizers found all '0's.

But what's hairy is there's all this arithmetic in what you select for inputs to the recognizers. You can fix that with the same one way union:

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;

And that eliminates a whole heck of a lot of arithmetic required because i_pad is a signal.

Community
  • 1
  • 1
  • Thanks! Those solutions are really beautiful compared to mine! My arsenal of solutions is not yet very big, but this sure helps. – toxUP Dec 11 '15 at 18:12
  • When you have the urge to keep packages of subtype declarations of byte index ranges, ... resist. –  Dec 11 '15 at 18:20