cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
8,185 Views
Registered: ‎01-23-2017

VHDL 2008 - unconstrained array of record containing unconstrained array)

Jump to solution
   

I am experimenting to synthesise some VHDL 2008 code in Vivado 2016.3 (the same situation is in 2016.4)

The idea is to be able to have unconstrained array in record and at the same time have unconstrained array of these records.

Relevant code:

(axi_pkg.vhd)

-- axi_pkg.vhd
-- Author: Bruno Kremel (CERN BE-RF-FB)
-- Date: 2016-01-23
-- Description: AXI4 Package

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.misc_pkg.all;

package axi_pkg is
    type axis_in is record
        tdata  : std_logic_vector;
        tvalid : std_logic;
        tlast  : std_logic;
        tuser  : std_logic_vector;
    end record;

    type axis_out is record
        tready : std_logic;
    end record;

    type axis_in_vector is array (natural range <>) of axis_in;
    type axis_out_vector is array (natural range <>) of axis_out;
end package;

(axis_reg.vhd)

-- axis_reg.vhd
-- Author: Bruno Kremel (CERN BE-RF-FB)
-- Date: 2016-11-22
-- Description: AXI4 Stream register

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.misc_pkg.all;
use work.axi_pkg.all;

entity axis_reg is
    generic (
        DATA_TYPE : string := "signed"
        );
    port (
        aresetn : in std_logic;
        aclk    : in std_logic;

        -- Input stream
        in_axis_in  : in  axis_in;
        in_axis_out : out axis_out;

        -- Output stream
        out_axis_in  : out axis_in;
        out_axis_out : in  axis_out
        );
end entity axis_reg;

architecture basic of axis_reg is
    constant OUT_DATA_W :natural := out_axis_in.tdata'length;
    constant IN_DATA_W :natural := in_axis_in.tdata'length;
    signal in_tdata_conv : std_logic_vector(OUT_DATA_W-1 downto 0);
    signal in_tuser_conv : std_logic_vector(OUT_DATA_W/8-1 downto 0);
    signal in_tdata_shd : std_logic_vector(IN_DATA_W-1 downto 0);
    signal in_tuser_shd : std_logic_vector(IN_DATA_W/8-1 downto 0);
begin

    gen_signed: if DATA_TYPE = "signed" generate
        in_tdata_conv <= std_logic_vector(resize(signed(in_tdata_shd), OUT_DATA_W));
        in_tuser_conv <= std_logic_vector(resize(signed(in_tuser_shd), OUT_DATA_W/8));
    end generate;

    gen_unsigned: if DATA_TYPE = "unsigned" generate
        in_tdata_conv <= std_logic_vector(resize(unsigned(in_tdata_shd), OUT_DATA_W));
        in_tuser_conv <= std_logic_vector(resize(unsigned(in_tuser_shd), OUT_DATA_W/8));
    end generate;

    reg_ctrl_inst : entity work.axis_reg_ctrl
        port map (
            aresetn => aresetn,
            aclk    => aclk,

            next_tdata  => in_tdata_conv,
            next_tuser  => in_tuser_conv,
            next_update => open,

            in_tvalid => in_axis_in.tvalid,
            in_tready => in_axis_out.tready,
            in_tlast  => in_axis_in.tlast,

            out_tdata  => out_axis_in.tdata,
            out_tvalid => out_axis_in.tvalid,
            out_tready => out_axis_out.tready,
            out_tlast  => out_axis_in.tlast,
            out_tuser  => out_axis_in.tuser
            );
end architecture;

(test_entity.vhd)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.axi_pkg.all;

entity test_entity is
    port (
        aresetn : std_logic;
        aclk    : std_logic;

        -- Input stream
        in_axis_in  : in  axis_in_vector;
        in_axis_out : out axis_out_vector;

        -- Output stream
        out_axis_in  : out axis_in_vector;
        out_axis_out : in  axis_out_vector
        );
end entity;

architecture test of test_entity is

begin

    gen_reg : for i in 0 to in_axis_in'length-1 generate
    begin
        reg_i : entity work.axis_reg
            generic map (
                DATA_TYPE  => "signed"
                )
            port map (aresetn      => aresetn,
                      aclk         => aclk,
                      in_axis_in   => in_axis_in(i),
                      in_axis_out  => in_axis_out(i),
                      out_axis_in  => out_axis_in(i),
                      out_axis_out => out_axis_out(i));
    end generate;

end architecture;

And finally test_entity_top.vhd which basically constraints the sizes for synthesis:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.axi_pkg.all;

entity test_entity_top is
end entity;

architecture test of test_entity_top is
    constant SIZE   : natural := 10;
    constant DATA_W : natural := 16;
    signal test_axis_in : axis_in(tdata(DATA_W-1 downto 0),
                                  tuser(DATA_W/8-1 downto 0));
    signal test_axis_out : axis_out;
    signal in_axis_in : axis_in_vector(SIZE-1 downto 0)(tdata(DATA_W-1 downto 0),
                                                        tuser(DATA_W/8-1 downto 0));
    signal in_axis_out : axis_out_vector(SIZE-1 downto 0);
    signal out_axis_in : axis_in_vector(SIZE-1 downto 0)(tdata(DATA_W-1 downto 0),
                                                         tuser(DATA_W/8-1 downto 0));
    signal out_axis_out : axis_out_vector(SIZE-1 downto 0);
    signal aresetn      : std_logic;
    signal aclk         : std_logic;
begin

    tst : entity work.test_entity
        port map (aresetn      => aresetn,
                  aclk         => aclk,
                  in_axis_in   => in_axis_in,
                  in_axis_out  => in_axis_out,
                  out_axis_in  => out_axis_in,
                  out_axis_out => out_axis_out
                  );
end architecture;

This all nicely compiles in ModelSim. But Vivado is reluctant to sythesise it... With this error:

ERROR: [Synth 8-2190] illegal syntax for subtype indication [/home/bkremel/test_vivado/test_entity_top.vhd:15]
ERROR: [Synth 8-2235] indexed name prefix type axis_in_vector expects 1 dimensions [/home/bkremel/test_vivado/test_entity_top.vhd:15]
ERROR: [Synth 8-2190] illegal syntax for subtype indication [/home/bkremel/test_vivado/test_entity_top.vhd:18]
ERROR: [Synth 8-2235] indexed name prefix type axis_in_vector expects 1 dimensions [/home/bkremel/test_vivado/test_entity_top.vhd:18]
ERROR: [Synth 8-1031] in_axis_in is not declared [/home/bkremel/test_vivado/test_entity_top.vhd:28]
ERROR: [Synth 8-1031] out_axis_in is not declared [/home/bkremel/test_vivado/test_entity_top.vhd:30]
ERROR: [Synth 8-1568] actual of formal out port out_axis_in cannot be an expression [/home/bkremel/test_vivado/test_entity_top.vhd:30]
INFO: [Synth 8-2810] unit test ignored due to previous errors [/home/bkremel/test_vivado/test_entity_top.vhd:9]

Which indicate it does actually accept the syntax of record constraint (as you would expect from VHDL 2008 sythesiser)

signal test_axis_in : axis_in(tdata(DATA_W-1 downto 0),
                              tuser(DATA_W/8-1 downto 0));

While it does not like:

signal in_axis_in : axis_in_vector(SIZE-1 downto 0)(tdata(DATA_W-1 downto 0),
                                                tuser(DATA_W/8-1 downto 0));

 

Is this supposed to be un-supported in Vivado Synthesis?

 

If it is indeed unsupported what would you suggest to use intead of unconstrained arrays and records?

The thing is that my design quite often changes the bit size of the stream.. So using generic packages would be quite inelegant (especially this register is nice example when in one file you have the bus with different sizes of data bus)

 

So far I have used one dimensional slv without records with manual indexing using functions/procedures, but that is quite messy to maintain...

I also add edaplayground example of relevant code https://www.edaplayground.com/x/eiC (to demonstrate that it works in simulator)...

Thanks Bruno

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Visitor
Visitor
11,857 Views
Registered: ‎01-23-2017

Re: VHDL 2008 - unconstrained array of record containing unconstrained array)

Jump to solution

I have discussed this over Xilinx SR and it turned out that I have forgot to enable VHDL 2008 for all files, now it works.

 

This is minimal working example:

-- axi_pkg.vhd
-- Author: Bruno Kremel (CERN BE-RF-FB)
-- Date: 2016-01-23
-- Description: AXI4 Package

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package axi_pkg is
    type axis_downstream is record
        tdata  : std_logic_vector;
        tvalid : std_logic;
        tlast  : std_logic;
        tuser  : std_logic_vector;
    end record;

    type axis_upstream is record
        tready : std_logic;
    end record;

    type axis_downstream_vector is array (natural range <>) of axis_downstream;
    type axis_upstream_vector is array (natural range <>) of axis_upstream;
end package;


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.axi_pkg.all;

entity test_entity_top is
end entity;

architecture test of test_entity_top is
    constant SIZE   : natural := 4;
    constant DATA_W : natural := 16;

    signal axis_downstream : axis_downstream_vector(SIZE-1 downto 0)(tdata(DATA_W-1 downto 0),
                                                                     tuser(DATA_W/8-1 downto 0));
    signal axis_upstream : axis_upstream_vector(SIZE-1 downto 0);
begin
    assert axis_downstream'length = SIZE
        report "SIZE is not correct"
    severity failure;

    assert axis_downstream(0).tdata'length = DATA_W
        report "TDATA width is not correct"
    severity failure;

    assert axis_downstream(0).tuser'length = (DATA_W/8)
        report "TUSER width is not correct"
    severity failure;

end architecture;

 

Also Edaplayground link: https://www.edaplayground.com/x/3sKr

View solution in original post

0 Kudos
2 Replies
Highlighted
Visitor
Visitor
8,173 Views
Registered: ‎01-23-2017

Re: VHDL 2008 - unconstrained array of record containing unconstrained array)

Jump to solution

What is interesting is, that it actually synthesise if I do following:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.axi_pkg.all;

entity test_entity_top is
end entity;

architecture test of test_entity_top is
    constant SIZE   : natural := 4;
    constant DATA_W : natural := 16;
    subtype axis_in_constr is axis_in(tdata(DATA_W-1 downto 0),
                                      tuser(DATA_W/8-1 downto 0));
    subtype axis_out_constr is axis_out;

    signal ch0, ch1, ch2, ch3 : axis_in_constr;
    signal out0, out1, out2, out3 : axis_in_constr;
    signal in_axis_in : axis_in_vector := (ch0, ch1, ch2, ch3);
    signal out_axis_in : axis_in_vector := (out0, out1, out2, out3);
    signal in_axis_out : axis_out_vector(SIZE-1 downto 0);
    signal out_axis_out : axis_out_vector(SIZE-1 downto 0);
    signal aresetn      : std_logic;
    signal aclk         : std_logic;
begin

    tst : entity work.test_entity
        port map (aresetn      => aresetn,
                  aclk         => aclk,
                  in_axis_in   => in_axis_in,
                  in_axis_out  => in_axis_out,
                  out_axis_in  => out_axis_in,
                  out_axis_out => out_axis_out
                  );
end architecture;

So that means that the array of records with unconstrained array is actually supported, but the direct constraint syntax is not.

Any ideas how to define it less elaboratively? Although it's not a big deal to define top-level like this.. Still I would not mind to avoid it, it looks a tad hacky...

0 Kudos
Highlighted
Visitor
Visitor
11,858 Views
Registered: ‎01-23-2017

Re: VHDL 2008 - unconstrained array of record containing unconstrained array)

Jump to solution

I have discussed this over Xilinx SR and it turned out that I have forgot to enable VHDL 2008 for all files, now it works.

 

This is minimal working example:

-- axi_pkg.vhd
-- Author: Bruno Kremel (CERN BE-RF-FB)
-- Date: 2016-01-23
-- Description: AXI4 Package

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package axi_pkg is
    type axis_downstream is record
        tdata  : std_logic_vector;
        tvalid : std_logic;
        tlast  : std_logic;
        tuser  : std_logic_vector;
    end record;

    type axis_upstream is record
        tready : std_logic;
    end record;

    type axis_downstream_vector is array (natural range <>) of axis_downstream;
    type axis_upstream_vector is array (natural range <>) of axis_upstream;
end package;


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.axi_pkg.all;

entity test_entity_top is
end entity;

architecture test of test_entity_top is
    constant SIZE   : natural := 4;
    constant DATA_W : natural := 16;

    signal axis_downstream : axis_downstream_vector(SIZE-1 downto 0)(tdata(DATA_W-1 downto 0),
                                                                     tuser(DATA_W/8-1 downto 0));
    signal axis_upstream : axis_upstream_vector(SIZE-1 downto 0);
begin
    assert axis_downstream'length = SIZE
        report "SIZE is not correct"
    severity failure;

    assert axis_downstream(0).tdata'length = DATA_W
        report "TDATA width is not correct"
    severity failure;

    assert axis_downstream(0).tuser'length = (DATA_W/8)
        report "TUSER width is not correct"
    severity failure;

end architecture;

 

Also Edaplayground link: https://www.edaplayground.com/x/3sKr

View solution in original post

0 Kudos