VHDL通用案例陈述

时间:2017-11-30 14:03:43

标签: vhdl fpga xilinx vivado

我试图用一般数量的case语句实例化一个mux。目前我的代码如下所示:

在这些示例中,data_array和selector是输入,data是输出,mux的宽度是4。

process(all)
begin
    case? selector is
        when "1---" => data <= data_array(3);
        when "01--" => data <= data_array(2);
        when "001-" => data <= data_array(1);
        when "0001" => data <= data_array(0);
        when others => data <= (others => '-');
    end case?;
end process;

有没有办法获得通用数量的个案陈述?或者我可以使用类似的功能吗?

我可以使用代码生成来解决这个问题,以生成适当数量的case语句,但我想知道是否有可用于解决此问题的VHDL(-2008)功能。

我已经重写了mux以使用for循环但不幸的是我的实现工具并没有很好地处理这个问题。推断的逻辑不是最优的,而且在时间方面非常糟糕。

在此示例中,GENERIC_WIDTH是多路复用器的宽度。

process(all)
begin
    data_v := (others => '0');
    for i in 0 to GENERIC_WIDTH-1 loop
        if selector(i) then
            data <= data_array(i);
        end if;
    end loop;
end process;

我的目标是使用Vivado 2017.3的Xilinx设备。实现结果表明,使用case语句可以产生比使用for循环更高效的逻辑(就WNS和逻辑深度而言)。

1 个答案:

答案 0 :(得分:2)

它不再重要:现代综合工具将正确优化所有逻辑。我对Vivado 2017.3输出进行了比较。基础实体是

library ieee;
use ieee.std_logic_1164.all;

entity MyMux is
    generic(
        data_width : positive := 32;
        data_depth : positive := 4
    );
    port(
        clk : in std_logic;
        data_in : in std_logic_vector(data_width-1 downto 0);
        selector : in std_logic_vector(data_depth-1 downto 0);
        data_out : out std_logic_vector(data_width-1 downto 0)
    );
end entity;

架构1:

architecture rtl of MyMux is
    subtype data_type is std_logic_vector(data_width-1 downto 0);
    type data_array_type is array (0 to data_depth-1) of data_type;

    signal data_array : data_array_type := (others => (others => '0'));
begin
    read_data : process(clk) begin
        if rising_edge(clk) then
            for i in data_depth-1 downto 1 loop
                data_array(i) <= data_array(i-1);
            end loop;
            data_array(0) <= data_in;
        end if;
    end process;

    select_output: process(all) begin
        case? selector is
            when "1---" => data_out <= data_array(3);
            when "01--" => data_out <= data_array(2);
            when "001-" => data_out <= data_array(1);
            when "0001" => data_out <= data_array(0);
            when others => data_out <= (others => '-');
        end case?;
    end process;
end architecture;

架构2:

architecture rtl of MyMux is
    subtype data_type is std_logic_vector(data_width-1 downto 0);
    type data_array_type is array (0 to data_depth-1) of data_type;

    signal data_array : data_array_type := (others => (others => '0'));
begin
    read_data : process(clk) begin
        if rising_edge(clk) then
            for i in data_depth-1 downto 1 loop
                data_array(i) <= data_array(i-1);
            end loop;
            data_array(0) <= data_in;
        end if;
    end process;

    select_output: process(all) begin
        data_out <= (others => '-');
        for i in 0 to data_depth-1 loop
            if selector(i) then
                data_out <= data_array(i);
            end if;
        end loop;
    end process;
end architecture;

架构3:

architecture rtl of MyMux is
    subtype data_type is std_logic_vector(data_width-1 downto 0);
    type data_array_type is array (0 to data_depth-1) of data_type;

    signal data_array : data_array_type := (others => (others => '0'));

    function my_mux(
        selector : std_logic_vector(data_depth-1 downto 0);
        data_array : data_array_type) return data_type is
        variable data : data_type;
    begin
        data := (others => '-');
        for i in 0 to data_depth-1 loop
            if selector(i)='1' then
                data := data_array(i);
            end if;
        end loop;
        return data;
    end function;
begin
    read_data : process(clk) begin
        if rising_edge(clk) then
            for i in data_depth-1 downto 1 loop
                data_array(i) <= data_array(i-1);
            end loop;
            data_array(0) <= data_in;
        end if;
    end process;

    data_out <= my_mux(selector, data_array);
end architecture;

输出:

  • 架构1:32 LUT3,32 LUT6,128 FDRE
  • 架构2:32 LUT3,32 LUT5,128 FDRE
  • 架构3:32 LUT3,32 LUT5,128 FDRE

所以他们几乎都是一样的。

问题是你的情况似乎是非确定性的组成部分:初始安置随机化。根据我的经验,这个初始放置是基于从代码散列中提取的一些随机化器种子。相同的代码将始终提供相同的实现。但是对代码进行非常小的更改,时间和资源的使用可能会完全不同。

您应该注意,您在代码中描述的逻辑将实现为多路复用器链。当GENERIC_WIDTH增加时,延迟也会增加。这是不可避免的。