1
votes

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;
1
Can you make msgLength a generic? ie Does is vary during the normal operation of your system? - Matthew Taylor
Unfortunately, yes, msgLength is variable. - Robin Arbaud
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
It seems Yosys is verilog based. Which VHDL front-end are you using? These all seems very experimental. So don't expect miracles. - JHBonarius
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

1 Answers

0
votes

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.