vhdl中的冒泡排序
bubble sort in 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 编码的初学者。请帮我解决这个问题。
缺少 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 一个在进程内更新的信号。 i 不应该在这里作为信号(或者你可以在这里使用 for 循环)。
这也指出 temp 是一个信号并且遇到同样的问题,在进程挂起和恢复之前不能使用 temp 的 'new' 值。信号被安排更新,没有包含 after 子句的波形元素的信号分配具有零延迟的隐式 after 子句。当计划恢复的任何进程尚未恢复并随后挂起时,不会发生信号更新。这允许在顺序语句中找到分配的信号的并发外观(并发语句具有包含等效顺序语句的等效过程)。因此,在执行过程语句序列期间,i 和 temp 都不能更新,并且都希望成为变量。
我们也会使用 in_array_sig 的信号被咬。当您增加 i 时,先前索引的 in_array_sig(i + 1) 成为下一个循环迭代的 in_array_sig(i)。在没有干预进程的情况下,暂停和恢复原始值可用。 in_array_sig也想成为一个变量
如果我们要修复所有这些问题,我们也可能会注意到 i 未初始化(这将在 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 最右边的元素。但是,不能保证剩余元素的顺序。
要执行完整的冒泡排序,我们需要另一个循环来嵌套第一个循环。此外,现在的 'inner' 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 可见的进程中。
另外值得注意的是无符号大于运算符的使用。 std_logic_vector 的“>”允许元值和 'H' 和 'L' 值扭曲关系比较,而无符号运算符是算术运算符。
结果
加入包和实体声明:
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;
我们得到:
有用的东西。
架构中的进程 BSORT 中未包含重置为使能,可以添加到带有时钟边沿条件的 if 语句中。
关于这里,我们谈到了 Matthew Taylor 在关于描述硬件的评论中的观点。
根据综合工具,该过程可能会或可能不会实现为硬件。如果不是,则需要中间变量来保存内部循环的每次连续迭代中使用的数组部分。
还有一个时钟周期内可以做多少的问题。最坏的情况是延迟深度由十五个元素比较和十五个 2:2 选择器有条件地交换元素对组成。
如果您要选择与合成延迟不兼容的时钟速度,您需要重新构建实现,从软件循环仿真到跨连续时钟运行的东西。
这可能就像允许更多时钟周期一样简单,方法是使用该启用来确定冒泡排序何时有效加载到 sorted_array 寄存器中。它可能更复杂,也允许不同的和更好的排序方法或修改冒泡排序以说检测不再需要交换。
任何人都可以帮助我编写 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 编码的初学者。请帮我解决这个问题。
缺少 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 一个在进程内更新的信号。 i 不应该在这里作为信号(或者你可以在这里使用 for 循环)。
这也指出 temp 是一个信号并且遇到同样的问题,在进程挂起和恢复之前不能使用 temp 的 'new' 值。信号被安排更新,没有包含 after 子句的波形元素的信号分配具有零延迟的隐式 after 子句。当计划恢复的任何进程尚未恢复并随后挂起时,不会发生信号更新。这允许在顺序语句中找到分配的信号的并发外观(并发语句具有包含等效顺序语句的等效过程)。因此,在执行过程语句序列期间,i 和 temp 都不能更新,并且都希望成为变量。
我们也会使用 in_array_sig 的信号被咬。当您增加 i 时,先前索引的 in_array_sig(i + 1) 成为下一个循环迭代的 in_array_sig(i)。在没有干预进程的情况下,暂停和恢复原始值可用。 in_array_sig也想成为一个变量
如果我们要修复所有这些问题,我们也可能会注意到 i 未初始化(这将在 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 最右边的元素。但是,不能保证剩余元素的顺序。
要执行完整的冒泡排序,我们需要另一个循环来嵌套第一个循环。此外,现在的 'inner' 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 可见的进程中。
另外值得注意的是无符号大于运算符的使用。 std_logic_vector 的“>”允许元值和 'H' 和 'L' 值扭曲关系比较,而无符号运算符是算术运算符。
结果
加入包和实体声明:
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;
我们得到:
有用的东西。
架构中的进程 BSORT 中未包含重置为使能,可以添加到带有时钟边沿条件的 if 语句中。
关于这里,我们谈到了 Matthew Taylor 在关于描述硬件的评论中的观点。
根据综合工具,该过程可能会或可能不会实现为硬件。如果不是,则需要中间变量来保存内部循环的每次连续迭代中使用的数组部分。
还有一个时钟周期内可以做多少的问题。最坏的情况是延迟深度由十五个元素比较和十五个 2:2 选择器有条件地交换元素对组成。
如果您要选择与合成延迟不兼容的时钟速度,您需要重新构建实现,从软件循环仿真到跨连续时钟运行的东西。
这可能就像允许更多时钟周期一样简单,方法是使用该启用来确定冒泡排序何时有效加载到 sorted_array 寄存器中。它可能更复杂,也允许不同的和更好的排序方法或修改冒泡排序以说检测不再需要交换。