vhdl中的冒泡排序

时间:2017-02-23 16:17:25

标签: process vhdl

在给定一组数据作为输入的情况下,任何人都可以帮我编写用于冒泡排序的VHDL代码吗?

我已将in_array声明为包含15个数组元素的输入。我想按降序对它们进行冒泡排序。

in_array是输入数组。 sorted_array已输出数组。 in_array_sig是in_array类型的信号

我在进程内部的语句面临问题

以下是我的代码:

architecture behav of Bubblesort is
  signal in_array_sig : bubble;
  signal temp : std_logic_vector(3 downto 0);
  signal i : integer := 0;
begin

  in_array_sig <= in_array;

  proc1 : process(clk, reset)
  begin
    if reset = '0' then
      if (clk'event and clk = '1') then
        while (i <= 15) loop
          if (in_array_sig(i) < in_array_sig(i + 1)) then
            temp <= in_array_sig(i);
            in_array_sig(i) <= in_array_sig(i + 1);
            in_array_sig(i + 1) <= temp;
          end if;
          i <= i + 1;
        end loop;
      end if;
    end if;
  end process;

  sorted_array <= in_array_sig;

end behav;

我是VHDL编码的初学者。请帮助我。

1 个答案:

答案 0 :(得分:1)

缺少Minimal Complete and Verifiable example使得很难提供关于所有阻止代码准确排除代码的事情的答案。这些可以按照您遇到的故障排除顺序进行描述。

  proc1 : process(clk, reset)
  begin
    if reset = '0' then
      if (clk'event and clk = '1') then
        while (i <= 15) loop
          if (in_array_sig(i) < in_array_sig(i + 1)) then
            temp <= in_array_sig(i);
            in_array_sig(i) <= in_array_sig(i + 1);
            in_array_sig(i + 1) <= temp;
          end if;
          i <= i + 1;
        end loop;
      end if;
    end if;
  end process;

开始注意时钟是通过复位门控的。您可以通过重置来限定分配,使其成为启用。

<强>问题

我们发现生产MCVe和测试平台的第一件事是该过程永远不会中止。这是由while循环中的条件引起的,这取决于i和i在过程中更新的信号。我不应该在这里成为一个信号(或者你可以在这里使用for循环)。

这也指出temp是一个信号并且遇到同样的问题,你不能使用&#39; new&#39; temp的值,直到进程暂停和恢复为止。信号被安排更新,没有包含after子句的波形元素的信号分配具有带零延迟的隐式后子句。在计划恢复的任何进程尚未恢复并随后暂停时,不会发生信号更新。这允许在顺序语句中找到分配信号的并发性(并发语句具有包含等效顺序语句的等效过程)。因此,i和temp都不能在执行语句的进程序列期间更新,并且两者都想成为变量。

我们也会使用in_array_sig的信号进行咬合。当你递增i时,先前索引的in_array_sig(i + 1)变成下一个循环迭代&lt; arayray_sig(i)。没有干预过程暂停和恢复原始值是可用的。 in_array_sig也想成为一个变量。

如果我们要修复所有这些,我们也可能会注意到我没有初始化(这将在for循环迭代方案中处理),我们也可能会发现我们得到了一个绑定错误使用in_array_sig的(i + 1)索引的行。如果没有提供MCVe的问题的作者,不清楚阵列大小是16(编号为0到15)还是17,如果前者i = 15 + 1将超出未公开数组的索引范围,则不清楚输入in_array,in_array_sig和sorted_array。

如果我们确保满足索引范围,并指出我们只需要比阵列中元素数量少1个测试和交换,我们就会发现该过程不是完整的冒泡排序。我们会看到in_array_sig的最大二进制值最终是sorted_array的最右边元素。但是,其余元素的顺序并不保证。

要执行完整的冒泡排序,我们需要另一个循环嵌套第一个循环。也是现在的内心&#39; for循环可以减少要遍历的元素数量,因为每次迭代都会留下最大的剩余元素,直到确保订单完成为止。

修正

修复上述内容会给我们看起来像这样:

architecture foo of bubblesort is
    use ieee.numeric_std.all;
begin

BSORT:
    process (clk)
        variable temp:      std_logic_vector (3 downto 0);
        variable var_array:     bubble;        
    begin
        var_array := in_array;
        if rising_edge(clk) then
            for j in bubble'LEFT to bubble'RIGHT - 1 loop 
                for i in bubble'LEFT to bubble'RIGHT - 1 - j loop 
                    if unsigned(var_array(i)) > unsigned(var_array(i + 1)) then
                        temp := var_array(i);
                        var_array(i) := var_array(i + 1);
                        var_array(i + 1) := temp;
                    end if;
                end loop;
            end loop;
            sorted_array <= var_array;
        end if;
    end process;
end architecture foo;

注意循环迭代方案是根据类型气泡边界来描述的,外部是一个比长度短的内部,而内部是一个更短的每次迭代。另请注意,sorted_array赋值将移动到in_array_sig变量替换var_array可见的进程中。

另外值得注意的是使用unsigned大于运算符。 &#34;&gt;&#34;对于std_logic_vector,允许元值和&#39; H&#39;和&#39; L&#39;用于扭曲关系比较的值,而无符号运算符是算术运算。

<强>结果

抛出包和实体声明:

library ieee;
use ieee.std_logic_1164.all;

package array_type is
    type bubble is array (0 to 15) of std_logic_vector(3 downto 0);
end package;

library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;

entity bubblesort is
    port (
        signal clk:             in  std_logic;
        signal reset:           in  std_logic;
        signal in_array:        in  bubble;
        signal sorted_array:    out bubble 
    );
end entity;

以及测试平台:

library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;

entity bubblesort_tb is
end entity;

architecture fum of bubblesort_tb is
    signal clk:             std_logic := '0';
    signal reset:           std_logic := '0';
    signal in_array:        bubble :=
                   (x"F", x"E", x"D", x"C", x"B", x"A", x"9", x"8",
                    x"7", x"6", x"5", x"4", x"3", x"2", x"1", x"0");
    signal sorted_array:    bubble;
begin

DUT:
    entity work.bubblesort(foo)
        port map (
            clk => clk,
            reset => reset,
            in_array => in_array,
            sorted_array => sorted_array
        );
CLOCK:
    process
    begin
        wait for 10 ns;
        clk <= not clk;
        if now > 30 ns then
            wait;
        end if;
    end process;

end architecture;

我们得到:

bubblesort_tb.png

有效的东西。

作为启用的复位未包含在架构中的过程BSORT中,并且可以在具有时钟边沿条件的if语句中添加。

关于这里,我们在关于描述硬件的评论中得到了马修泰勒的观点。

根据综合工具,该过程可能会或可能不会被视为硬件。如果不是,您需要中间变量来保存内循环的每次连续迭代中使用的数组部分。

还有一个问题是你在一个时钟周期中可以做多少。最坏的情况是延迟深度由十五个元素比较和十五个2:2选择器组成,有条件地交换元素对。

如果您要选择与合成延迟不兼容的时钟速度,则需要重新设计从软件循环仿真到连续时钟操作的实现。

这可以简单到允许更多时钟周期,通过使用该启用来确定冒泡排序何时有效加载到sorted_array寄存器。它可能更复杂,也允许不同的和更好的执行排序方法或修改冒泡排序,以便检测不再需要交换。