Vivado 2016.3 无约束记录数组 std_logic_vector

Vivado 2016.3 unconstrained array of record with unconstrained std_logic_vector

我正在尝试在 Vivado 2016.3 中合成一些 VHDL 2008 代码(2016.4 中的情况相同)

想法是能够在记录中拥有不受约束的数组,同时拥有这些记录的不受约束数组。

相关代码:

(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;

最后 test_entity_top.vhd 这基本上限制了合成的大小:

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;

这一切都可以在 ModelSim 中很好地编译。但是 Vivado 不愿意合成它...出现这个错误:

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]

表示它确实接受记录约束的语法:

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

虽然不喜欢:

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

您建议如何使用不受约束的数组和记录?

问题是我的设计经常改变流的位大小..所以使用通用包会很不优雅(特别是这个寄存器是一个很好的例子,当你在一个文件中有不同大小的数据的总线公共汽车)

到目前为止,我使用的是没有记录的一维 slv,使用 functions/procedures 进行手动索引,但是维护起来很麻烦...

我还添加了相关代码的edaplayground示例https://www.edaplayground.com/x/eiC(以证明它在模拟器中工作)...

编辑:

有趣的是,如果我执行以下操作,它实际上会合成:

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;

也就是说,实际上支持无约束数组的记录数组,但不支持直接约束语法。

有什么想法可以更轻松地定义它吗?虽然这样定义顶层没什么大不了的..但我还是不介意避免它,它看起来有点hacky...

谢谢 布鲁诺

借助 Xilinx SR,我们已经找到了所需行为的工作示例,所以我 post 它在这里工作,因为它在 Vivado 和 ModelSim/Edaplayground 中工作以及 ModelSim/Edaplayground。

-- 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;

问题是并非所有文件都在 Vivado 中标记为 2008(我的错)。但是我 post 这个最小的例子很适合这个问题。 还有 Edaplayground link: https://www.edaplayground.com/x/3sKr