1. Problem description
Find the minimum number of an array of 4 numbers and return the position and the number. This is a subset of the Kashubin sorter/absorber. Where the sorter employs even and odd states and a comparator, the “Sultan” min function only employs a comparator at each regression.
2. Implementation
2.1 Description
The min function returns the minimum value of a four 8-bit numbers and the position of the minimum number. Four numbers were chosen instead of eight because it was the highest number that requires only two levels of comparing. The algorithm is illustrated below in figure 1.
Figure 1.
The top level of the min function consists of four 8-bit inputs and one 8-bit output and one 2-bit output with control signal “en”. The flip flops are clocked with the clk and are positive edge triggered. Unlike the Kashubin sorter/absorber, there are no registers on the output. This function is designed to be fast, so only the input goes through a register. Also, the path to the min value is just N levels of gates, where N is log2 of the number of inputs. For example, if there are 8 (23) number of inputs, the min function requires 3 levels of compare gates. Note: If “en” remain on, the min function will find the min value on the positive edge of each clock cycle. The top level diagram is shown below as figure 2.
Figure 2.
2.2 Tools
I used the Mentor tools Renoir, ModelSim, and Leonardo. All were part of the FPGA Advantage evaluation package. I designed, simulated and synthesized this design with the above tools.
2.3 Block Diagram
Figure 3 is a detail system block diagram of the design. It is the actual design that Leonardo generated.
Figure 3.
3. Discussion
3.1 Considerations
If all of the numbers entered are equal or the minimum number is equal to another number in a different position, the min function will return the first number in the order of the array. For example, if the sequence 2,2,2,2 were entered into the min function then (2,0) would be returned. ‘2’ being the lowest number and ‘0’ being it’s position. The min function does not test for equals.
Similarly, if a don’t care is enter in any position, then it is disregarded and an actual number is returned.
3.2 Problems encountered
Since I have never programmed in VHDL before nor do I have experience in hardware design, it took me about 10 hours to get familiar with the Mentor tools. This includes going through the tutorial and making test cases. The design itself is very easy to implement but with no background in VHDL or the tool set it takes much longer. Total Design time was about 20 hours.
I really only encountered two significant problems, the tool set and the process function. On the last compare state I didn’t include the position bus in the process function, so when new numbers were entered but the min number didn’t change, the output would stay the same even though the position changed. I fixed this by including the two address buses in the process statement.
4. Code
The code is below. Notice that I implement a strictly “less than” (<) in all of the compare statements. This is because unless the number in the higher position (e.g. dat_in1) is strictly less than the number in the lower position (e.g. dat_in0), the number in the lower position is passed on. Plus I remember from a hardware class that it takes less hardware to do a strictly less than, than a greater than or equal to.
Although the code says “latch”, the implementation is actually a flip-flop.
The first level of compares has the position hard coded in the design block. Every level after that passes the position of the lowest number.
Latch1_latch1.vhd
This implements the flipflop
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY latch1 IS
PORT(
clk : IN std_logic ;
dat_in1 : IN std_logic_vector (7 DOWNTO 0) ;
en : IN std_logic ;
dbus6 : OUT std_logic_vector (7 DOWNTO 0)
);
-- Declarations
END latch1 ;
-- renoir interface_end
ARCHITECTURE latch1 OF latch1 IS
BEGIN
process (clk,en)
BEGIN
if (clk='1' AND clk'event) then
if (en='1') then
dbus6 <= dat_in1;
end if;
end if;
end process;
END latch1;
Compare0_compare0.vhd
This is the first level of
compare blocks.
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY Compare0 IS
PORT(
dbus4 : IN std_logic_vector (7 DOWNTO 0) ;
dbus6 : IN std_logic_vector (7 DOWNTO 0) ;
dbus12 : OUT std_logic_vector (7 DOWNTO 0) ;
dbus13 : OUT std_logic_vector (1 DOWNTO 0)
);
-- Declarations
END Compare0 ;
-- renoir interface_end
ARCHITECTURE compare0 OF Compare0 IS
BEGIN
process (dbus6,dbus4)
begin
IF (dbus6 < dbus4) THEN
dbus12 <= dbus6;
dbus13 <= "01";
else
dbus12 <= dbus4;
dbus13 <= "00";
end if;
end process;
END compare0;
Compare3_compare3.vhd
This is the second level of compares. All compares above this level will be like this.
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY Compare3 IS
PORT(
dbus12 : IN std_logic_vector (7 DOWNTO 0) ;
dbus13 : IN std_logic_vector (1 DOWNTO 0) ;
dbus14 : IN std_logic_vector (7 DOWNTO 0) ;
dbus15 : IN std_logic_vector (1 DOWNTO 0) ;
dat_out : OUT std_logic_vector (7 DOWNTO 0) ;
dat_out_pos : OUT std_logic_vector (1 DOWNTO 0)
);
-- Declarations
END Compare3 ;
-- renoir interface_end
ARCHITECTURE Compare3 OF Compare3 IS
BEGIN
process (dbus14,dbus12,dbus15,dbus13)
begin
if (dbus14 < dbus12) then
dat_out <= dbus14;
dat_out_pos <= dbus15;
else
dat_out <= dbus12;
dat_out_pos <= dbus13;
end if;
end process;
END Compare3;
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY four_min IS
PORT(
clk : IN std_logic ;
dat_in0 : IN std_logic_vector (7 DOWNTO 0) ;
dat_in1 : IN std_logic_vector (7 DOWNTO 0) ;
dat_in2 : IN std_logic_vector (7 DOWNTO 0) ;
dat_in3 : IN std_logic_vector (7 DOWNTO 0) ;
en : IN std_logic ;
dat_out : OUT std_logic_vector (7 DOWNTO 0) ;
dat_out_pos : OUT std_logic_vector (1 DOWNTO 0)
);
-- Declarations
END four_min ;
-- renoir interface_end
--
-- VHDL Architecture Comparer.four_min.struct
--
-- Created:
-- by - sweather.UNKNOWN (SWMOBL)
-- at - 15:16:33 05/09/2001
--
-- Generated by Mentor Graphics' Renoir(TM) 2000.3 (Build 2)
--
LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
LIBRARY Comparer;
ARCHITECTURE struct OF four_min IS
-- Architecture declarations
-- Internal signal declarations
SIGNAL dbus10 : std_logic_vector(7 DOWNTO 0);
SIGNAL dbus12 : std_logic_vector(7 DOWNTO 0);
SIGNAL dbus13 : std_logic_vector(1 DOWNTO 0);
SIGNAL dbus14 : std_logic_vector(7 DOWNTO 0);
SIGNAL dbus15 : std_logic_vector(1 DOWNTO 0);
SIGNAL dbus4 : std_logic_vector(7 DOWNTO 0);
SIGNAL dbus6 : std_logic_vector(7 DOWNTO 0);
SIGNAL dbus8 : std_logic_vector(7 DOWNTO 0);
-- Component Declarations
COMPONENT Compare0
PORT (
dbus4 : IN std_logic_vector (7 DOWNTO 0);
dbus6 : IN std_logic_vector (7 DOWNTO 0);
dbus12 : OUT std_logic_vector (7 DOWNTO 0);
dbus13 : OUT std_logic_vector (1 DOWNTO 0)
);
END COMPONENT;
COMPONENT Compare1
PORT (
dbus10 : IN std_logic_vector (7 DOWNTO 0);
dbus8 : IN std_logic_vector (7 DOWNTO 0);
dbus14 : OUT std_logic_vector (7 DOWNTO 0);
dbus15 : OUT std_logic_vector (1 DOWNTO 0)
);
END COMPONENT;
COMPONENT Compare3
PORT (
dbus12 : IN std_logic_vector (7 DOWNTO 0);
dbus13 : IN std_logic_vector (1 DOWNTO 0);
dbus14 : IN std_logic_vector (7 DOWNTO 0);
dbus15 : IN std_logic_vector (1 DOWNTO 0);
dat_out : OUT std_logic_vector (7 DOWNTO 0);
dat_out_pos : OUT std_logic_vector (1 DOWNTO 0)
);
END COMPONENT;
COMPONENT latch0
PORT (
clk : IN std_logic ;
dat_in0 : IN std_logic_vector (7 DOWNTO 0);
en : IN std_logic ;
dbus4 : OUT std_logic_vector (7 DOWNTO 0)
);
END COMPONENT;
COMPONENT latch1
PORT (
clk : IN std_logic ;
dat_in1 : IN std_logic_vector (7 DOWNTO 0);
en : IN std_logic ;
dbus6 : OUT std_logic_vector (7 DOWNTO 0)
);
END COMPONENT;
COMPONENT latch2
PORT (
clk : IN std_logic ;
dat_in2 : IN std_logic_vector (7 DOWNTO 0);
en : IN std_logic ;
dbus8 : OUT std_logic_vector (7 DOWNTO 0)
);
END COMPONENT;
COMPONENT latch3
PORT (
clk : IN std_logic ;
dat_in3 : IN std_logic_vector (7 DOWNTO 0);
en : IN std_logic ;
dbus10 : OUT std_logic_vector (7 DOWNTO 0)
);
END COMPONENT;
-- Optional embedded configurations
-- pragma synthesis_off
FOR ALL : Compare0 USE ENTITY Comparer.Compare0;
FOR ALL : Compare1 USE ENTITY Comparer.Compare1;
FOR ALL : Compare3 USE ENTITY Comparer.Compare3;
FOR ALL : latch0 USE ENTITY Comparer.latch0;
FOR ALL : latch1 USE ENTITY Comparer.latch1;
FOR ALL : latch2 USE ENTITY Comparer.latch2;
FOR ALL : latch3 USE ENTITY Comparer.latch3;
-- pragma synthesis_on
BEGIN
-- Instance port mappings.
I4 : Compare0
PORT MAP (
dbus4 => dbus4,
dbus6 => dbus6,
dbus12 => dbus12,
dbus13 => dbus13
);
I5 : Compare1
PORT MAP (
dbus10 => dbus10,
dbus8 => dbus8,
dbus14 => dbus14,
dbus15 => dbus15
);
I6 : Compare3
PORT MAP (
dbus12 => dbus12,
dbus13 => dbus13,
dbus14 => dbus14,
dbus15 => dbus15,
dat_out => dat_out,
dat_out_pos => dat_out_pos
);
I0 : latch0
PORT MAP (
clk => clk,
dat_in0 => dat_in0,
en => en,
dbus4 => dbus4
);
I1 : latch1
PORT MAP (
clk => clk,
dat_in1 => dat_in1,
en => en,
dbus6 => dbus6
);
I2 : latch2
PORT MAP (
clk => clk,
dat_in2 => dat_in2,
en => en,
dbus8 => dbus8
);
I3 : latch3
PORT MAP (
clk => clk,
dat_in3 => dat_in3,
en => en,
dbus10 => dbus10
);
END struct;