Search code examples
vhdlhdl

vhdl takes more logic elements than doing in it hand


Then I have the following multiplexer wrote using just basic logic elements.

entity Multiplex4 is
    port(
        data: in std_logic_vector( 3 downto 0 );
        result: out std_logic_vector( 9 downto 0 )
        );
end Multiplex4;

architecture Multiplex4 of Multiplex4 is
begin
    result(0) <= not ( data(0) or data(1) or data(2) or data(3) );
    result(1) <= data(0) and ( not ( data(1) or data(2) or data(3) ) );
    result(2) <= not data(0) and data(1) and not ( data(2) or data(3) );
    result(3) <= data(0) and data(1) and not ( data(2) or data(3) );
    result(4) <= not ( data(0) or data(1) ) and data(2) and not data(3);
    result(5) <= data(0) and not data(1) and data(2) and not data(3);
    result(6) <= not data(0) and data(1) and data(2) and not data(3);
    result(7) <= data(0) and data(1) and data(2) and not data(3);
    result(8) <= not ( data(0) or data(1) or data(2) ) and data(3);
    result(9) <= data(0) and not ( data(1) or data(2) ) and data(3);
end Multiplex4;

And I'm using it just for an example of a 7 segments display.

entity Display8b is
    port(
        KEY1: in std_logic;
        DS_A, DS_B, DS_C, DS_D, DS_E, DS_F, DS_G, DS_DP: out std_logic;
        DS_EN1: out std_logic;
        DS_EN2: out std_logic;
        DS_EN3: out std_logic;
        DS_EN4: out std_logic
        );
end Display8b;

architecture Display8b of Display8b is

signal counter: std_logic_vector( 3 downto 0 ):= "1001";

COMPONENT Multiplex4
    PORT(
        data: in std_logic_vector( 3 downto 0 );
        result: out std_logic_vector( 9 downto 0 )
        );
END COMPONENT;

signal values: std_logic_vector( 9 downto 0 );
begin
    process(KEY1)
    begin
        if KEY1'event and KEY1='1' then
            if counter = 9 then
                counter <= "0000";
            else
                counter <= counter + 1;
            end if; 
        end if;
    end process;

    mult : Multiplex4 port map( counter, values );

    DS_A <= values(0) or values(2) or values(3) or values(5) or 
                values(6) or values(7) or values(8) or values(9);
    DS_B <= values(0) or values(1) or values(2) or values(3) or 
                values(4) or values(7) or values(8) or values(9);
    DS_C <= values(0) or values(1) or values(3) or values(4) or 
                values(5) or values(6) or values(7) or values(8) or values(9);
    DS_D <= values(0) or values(2) or values(3) or values(5) or
                values(6) or values(8) or values(9);
    DS_E <= values(0) or values(2) or values(6) or values(8);
    DS_F <= values(0) or values(4) or values(5) or values(6) or
                values(8) or values(9);
    DS_G <= values(2) or values(3) or values(4) or values(5) or
                values(6) or values(8) or values(9);
end Display8b;

When the value is 0, set 1 in all n leds, when 6 set in others n leds and so on. I put a key event and a counter just to test.

11 logic elements and 4 logic registers

Obviously I doing it in an wrong way, because it is not using truly the vhdl language. So I have another code, it does the same thing, but I little more smarter and in just one file.

entity Display8 is
    port(
        KEY1: in std_logic;
        DS_A, DS_B, DS_C, DS_D, DS_E, DS_F, DS_G, DS_DP: out std_logic;
        DS_EN1: out std_logic;
        DS_EN2: out std_logic;
        DS_EN3: out std_logic;
        DS_EN4: out std_logic
        );
end Display8;

architecture Display8 of Display8 is

signal result: std_logic_vector( 6 downto 0 );
signal counter: integer := 5;

begin

    process(KEY1)
    begin
        if KEY1'event and KEY1='1' then
            if counter = 9 then
                counter <=0;
            else
                counter <= counter + 1;
        end if; 
        end if;
    end process;

    DS_A <= result(0);
    DS_B <= result(1);
    DS_C <= result(2);
    DS_D <= result(3);
    DS_E <= result(4);
    DS_F <= result(5);
    DS_G <= result(6);

    with counter Select
        result <= 
            "0111111" when 0,   
            "0000110" when 1, 
            "1011011" when 2,
            "1001111" when 3,
            "1100110" when 4,
            "1101101" when 5,
            "1111101" when 6, 
            "0000111" when 7, 
            "1111111" when 8,
            "1101111" when 9,         
            "0111111" when others;

    DS_EN1 <= '0';
    DS_EN2 <= '1';
    DS_EN3 <= '1';
    DS_EN4 <= '1';
end Display8;

60 logic elements and 32 logic registers.

Well, probably I am not doing it right, because the code I believed was better gets more resource than the other. How do I make a better code?

I'm using altera quartus.


Solution

  • Your counter signal unnecessarily uses the whole integer number range while it needs only 4 bits. Try this:

    signal counter: integer range 0 to 9 := 5;
    

    Did not test it, but should significantly reduce resource count (probably down to the same same number your other code uses).