1

I am trying to copy some part of a std_logic_vector into another, at a position (index) depending on an input. This can be synthesized in Vivado, but I want to use another tool (SymbiYosys, https://github.com/YosysHQ/SymbiYosys) for formal verification. SymbiYosys can use Verific as frontend to process VHDL, but Verific does not accept this. Here is a small piece of code which reproduces the problem. Verific complains that the "left range bound is not constant". So, is there a workaround to make Verific accept such variable range assignments ?

I already found this post VHDL: slice a various part of an array which proposes to use a loop and to assign values bit per bit, but I would rather not change my code now that it works with Vivado. Also I think such a loop would impair code readability, and perhaps implementation efficiency. Therefore, I am looking for a different method (maybe a way to turn this error into a warning, or a less drastic code modification).

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

entity test is

port(
    clk         : in std_logic;
    prefix      : in std_logic_vector(  8*8 -1 downto 0);
    msgIn       : in std_logic_vector(128*8 -1 downto 0);
    msgLength   : in integer range 1 to 128;

    test_out    : out std_logic_vector((128+8)*8 -1 downto 0)
);

end test;

architecture behav of test is
begin

process (clk)
begin
    if rising_edge(clk) then

        test_out <= (others => '0');
        test_out((msgLength+8)*8 -1 downto msgLength*8) <= prefix;
        test_out( msgLength   *8 -1 downto           0) <= msgIn(msgLength*8 -1 downto 0);

    end if;
end process;

end behav;
Robin Arbaud
  • 11
  • 1
  • 4
  • Can you make `msgLength` a generic? ie Does is vary during the normal operation of your system? – Matthew Taylor Jun 19 '18 at 08:53
  • Unfortunately, yes, msgLength is variable. – Robin Arbaud Jun 19 '18 at 09:29
  • Sometimes it helps to put this in a function and then call the function from the process. In the past Xilinx ISE also required this. – JHBonarius Jun 19 '18 at 09:42
  • It seems Yosys is verilog based. Which VHDL front-end are you using? These all seems very experimental. So don't expect miracles. – JHBonarius Jun 19 '18 at 09:53
  • I just read this: "Therefore, I am looking for a different method. Maybe a way to turn this error into a warning, or a less drastic code modification." You probably want the impossible. I would consider accepting. bitwise selecting is probably the best. And you should consider the complexity of your design.. this will not be high-speed. – JHBonarius Jun 19 '18 at 11:18
  • Yosys itself supports only verilog, but VHDL code can be integrated using the Verific frontend (see ). – Robin Arbaud Jun 19 '18 at 17:08

1 Answers1

0

A bit of shifting should make it (if your tools support the srl and sll operators). First left-align your message (left shift), left-pad it with your prefix and, finally, right-shift it:

process (clk)
    variable tmp1: std_logic_vector(128*8 -1 downto 0);
    variable tmp2: std_logic_vector((128+8)*8 -1 downto 0);
begin
    if rising_edge(clk) then
        tmp1 := msgIn sll (8 * (128 - msgLength));    -- left-align
        tmp2 := prefix & tmp1;                        -- left-pad
        test_out <= tmp2 srl (8 * (128 - msgLength)); -- right-shift
    end if;
end process;

Remarks:

  1. In case your tools do not support the srl and sll operators on std_logic_vector, try to work with bit_vector, instead. srl and sll have been introduced in the standard in 1993. Example:

    process (clk)
        variable tmp1: bit_vector(128*8 -1 downto 0);
        variable tmp2: bit_vector((128+8)*8 -1 downto 0);
    begin
        if rising_edge(clk) then
            tmp1 := to_bitvector(msgIn) sll (8 * (128 - msgLength));
            tmp2 := to_bitvector(prefix) & tmp1;
            test_out <= to_stdlogicvector(tmp2 srl (8 * (128 - msgLength)));
        end if;
    end process;
    
  2. The synthesis result may be huge and slow because this 1088 bits barrel shifter with 128 possible different shifts is a kind of monster.

  3. If you have time (I mean several clock cycles) to do it, there are probably much smaller and more efficient solutions.

Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • 1
    @JHBonarius I don't know the `std_vector_1164` package (do you mean `std_logic_1164`?). Anyway, they are in `std_logic_1164` since 2008 (and maybe even before that, I do not keep all versions). And in case the OP's tools don't support them, they are defined on `bit_vector` since 1993. I add this to my answer. – Renaud Pacalet Jun 20 '18 at 15:22
  • Removed my comment. Was reading old library. Pre-2008 they were only defined for `std_logic_vector` in the deprecated `std_logic_arith`. My bad. I would personally use `shift_left` and `shift_right` and cast to even `unsigned` by the way. – JHBonarius Jun 20 '18 at 19:38
  • I'd use SHIFT_LEFT/RIGHT as well, defined in IEEE Std 1076.3-1997 .73.2 Package declaration for NUMERIC_STD, in common use in 1995. This answer could use std_logic_vector with type conversions by substituting unsigned for bit vector in the process. (Those shift distances should be times 8, message length is in octets.) Verific supports VHDL revision flags. There's no guarantee sll, srl, shfit_left or shift_right are supported without experimentation or understanding Verific and reading the complete SymbiYosys source. Two shifts seem awkward when you could use one plus two resizes. –  Jun 20 '18 at 23:26
  • I think [this process](https://i.stack.imgur.com/hRXXi.jpg) may provide the same logic produced by Vivado. `test_out <= std_logic_vector ( resize ( unsigned(prefix) & resize( unsigned(msgin), msglength * 8 ) , test_out'length ) );` (I simulated the original and compared it against this.) –  Jun 20 '18 at 23:32
  • @user1155120: "_Two shifts seem awkward when you could use one plus two resizes_" synthesis is smarter than what you think. It is not because you use two shifts in your description that you end up with two barrel shifters. In this case there will be only one. But yes, you are right, `shift_right`/`shift_left` could also be used. And `resize` too. Your solution with `resize` has one advantage: it avoids a subtraction (`128-msglength`). – Renaud Pacalet Jun 21 '18 at 05:33
  • @user1155120: "_Those shift distances should be times 8, message length is in octets_". Absolutely, thanks. I fixed my answer. – Renaud Pacalet Jun 21 '18 at 05:34
  • @RenaudPacalet have you looked into Yosys? It is open-source under-development for verilog. There's a VHDL front-end, but likely its just rewriting the VHDL to verilog. It's capabilities are not comparable to Xilinx, Altera, Synopsis, etc synthesis software. – JHBonarius Jun 21 '18 at 07:12
  • @JHBonarius: I had a look because I am quite impatient myself to use Yosis but the last time I had a look at the VHDL frontend it was far from being usable for my purpose. We should contribute. – Renaud Pacalet Jun 21 '18 at 12:58