Hier jetzt mal eine Umsetzung des allseits bekannten Bubblesort-Algorithmus in VHDL.
Zuerst die rein kombinatorische Variante:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package BSTypes is
type BSData_Typ is array (0 to 9) of integer range 0 to 127;
end BSTypes;
package body BSTypes is
end BSTypes;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.bstypes.all;
entity Bubblesort is
Port ( di : in BSData_Typ;
do : out BSData_Typ );
end Bubblesort;
architecture Behavioral of Bubblesort is
begin
process (di)
variable din : BSData_Typ;
variable temp : integer;
variable n : integer;
variable oncemore : boolean;
begin
din := di;
n := din'length;
oncemore := TRUE;
while oncemore = TRUE and n > 1 loop
oncemore := FALSE;
for i in 0 to din'length-2 loop
if din(i) > din(i+1) then
temp := din(i); -- Dreieckstausch
din(i) := din(i+1);
din(i+1) := temp;
oncemore := TRUE;
end if;
end loop;
n := n-1;
end loop;
do <= din;
end process;
end Behavioral;
In einem Spartan 3 FPGA braucht diese Lösung abhängig vom Abbruch (über die Variable oncemore) unterschiedlich viele Ressourcen:
Mit Abbruch: Number of Slices 1293 Number of 4 input LUTs 2272
Ohne Abbruch: Number of Slices 976 Number of 4 input LUTs 1701
Der offensichtlichste Unterschied ist, dass der in der Software effizientere Abbruch (wenn das Array schon vor Ablauf aller Kombinationen schon komplett sortiert ist) in der Hardware nur Nachteile mit sich bringt.
Nachfolgend eine getaktete Lösung, die auf Kosten der Rechenzeit deutlich weniger Ressourcen braucht. Bubblesort.zip
Insbesondere fällt hier der Unterschied zwischen der Variante mit und der ohneAbbruch wesentlich geringer aus:
Mit Abbruch: Number of Slices 168 Number of 4 input LUTs 250
Ohne Abbruch: Number of Slices 167 Number of 4 input LUTs 245
-- Typdefinition BSData_Typ s.o.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.bstypes.all;
entity Bubblesort is
Port ( di : in BSData_Typ;
do : out BSData_Typ;
start : in std_logic;
done : out std_logic;
clk : in std_logic);
end Bubblesort;
architecture Behavioral of Bubblesort is
signal busy : boolean := FALSE;
signal din : BSData_Typ;
signal n,i : integer range 0 to din'length;
begin
process
variable temp : integer;
begin
wait until rising_edge(clk);
if (busy=FALSE) then
if (start='1') then
din <= di;
busy <= TRUE;
n <= 0;
i <= 0;
end if;
else
if (n < din'length) then
if (i<din'length-1) then
if din(i) > din(i+1) then
temp := din(i); -- Dreieckstausch
din(i) <= din(i+1);
din(i+1) <= temp;
end if;
i <= i+1;
else
i <= 0;
n <= n+1;
end if;
else
busy <= FALSE;
do <= din;
end if;
end if;
end process;
done <= '1' when start='0' and busy=FALSE else '0';
end Behavioral;
Das ist die Testbench für die kombinatorische Variante:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
use ieee.math_real.all;
use work.bstypes.all;
ENTITY tb_BubbleSort IS
END tb_BubbleSort;
ARCHITECTURE behavior OF tb_BubbleSort IS
COMPONENT Bubblesort
Port ( di : in BSData_Typ;
do : out BSData_Typ );
END COMPONENT;
--Inputs
signal di : BSData_Typ := (3,6,1,8,7,2,4,5,9,0);
--Outputs
signal do : BSData_Typ;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Bubblesort PORT MAP (
di => di,
do => do
);
-- Stimulus process
stim_proc: process
variable rand : real;
variable seed1 : positive := 234;
variable seed2 : positive := 567;
begin
wait for 100 ns;
loop
for i in 0 to 9 loop
UNIFORM(seed1, seed2, rand);
di(i) <= integer(TRUNC(rand*127.999));
end loop;
wait for 10 ns;
for i in 0 to 8 loop
assert do(i)<=do(i+1) report "Falsche Reihenfolge!" severity failure;
end loop;
end loop;
end process;
END;
Und das kommt dabei heraus:
Und hier können die Dateien gezippt heruntergeladen werden: Bubblesort.zip