Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

Optimum way to do Count = Count + 1 Using only std_logic_1164

Hello I'm new in this forum and recently I received an assigment for my Digital Systems Class. Its common to use in C/C++ or any high level language, a notation like cont = cont + 1. But my professor has prohibited the use of any library but std_logic_1164. I need to run a count of 32-bit and I have a component that can sum 32-bit, but I don't have any idea of how to perform it. Normally I will use

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

...

signal tmp : std_logic_vector(31 downto 0);

process(clk, rst)

begin

...

if tmp >= x"FFFFFFFF" then

tmp <= x"00000000";

else

tmp <= tmp + '1';

end if;

...

But I can't do that, at the moment I have something like

library ieee;

use ieee.std_logic_1164.all;

...

signal tmp, tmp2 : std_logic_vector(31 downto 0);

signal caux : std_logic;

component fullAdder32 is port(

a32, b32 : in std_logic_vector(31 downto 0);

s32 : out std_logic_vector(31 downto 0);

cout : out std_logic);

end component;

begin

f32 : fullAdder32 port map (tmp, 0x"00000001", tmp2, caux);

process(clk, rst)

begin

...

if tmp >= x"FFFFFFFF" then

tmp <= x"00000000";

else

tmp <= tmp2;

end if;

Is there a correct way to perform that because my code "compile" but with the instruction of "tmp <= tmp2" give a report of 100 macrocells and I only have 64 in the CPLD (Altera MAX3000). Without that instruction the fitter shows 20/64. Using, tmp = tmp + '1', the fitter shows (67/64). So I will appreciate any advice or sample you can show. Thanks in advance

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    An overflow detection is not necessary, because a binary 32 bit counter counts from x"FFFFFFFF" to x"00000000" on it's own. You make it count from x"FFFFFFFF" to x"00000001" which is wrong and needs more logic.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks every one for your fast answers.

    Hello Tricky, thanks for your assistance and its good for me that you "being a pedant" :cool:, I here for learning . And yes, I'm was mistaken about that library. When I put the second code with the 32-bit full adder is because at that moment I already had the instantiations in the coponent fullAdder32, and it is built of single full adders that are built from half adder components. Mi problem is that I really don't know how to use that in oder to achieve de classic "something = something + 1" since when i use the

    "f0 : fullAdder32 port map(a, b, sum, carry) its already running while the process that compare the current sum if its overflow thate the current sum. What I need to do change the "classic" with fulladders? Or there is another way to perform it with out the "+" sign and about the loop, does it takes more resources?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    With your VHDL file open in Quartus II go to the edit menu --> templates --> VHDL and find the counter templates, those will show you coding styles you can use for various counters. There is also an HDL recommended coding styles chapter in the Quartus II handbook worth looking at as well.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Since you only add '1', the addition can be implemented with 32 single-bit half-adders. No overflow detection is needed.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello everyone, thanks for your replies.

    As std_match mentioned I only used half adders modules. I tested my counter making a clk division and running on modelsim.

    The code is next

    library ieee;

    use ieee.std_logic_1164.all;

    entity clkdiv is

    port(

    sysclk : in std_logic;

    sysrst : in std_logic;

    clkdiv : out std_logic

    );

    end entity;

    architecture arch of clkdiv is

    component halfAdder is

    port(

    ah : in std_logic;

    bh : in std_logic;

    sh : out std_logic;

    ch : out std_logic;

    );

    end component;

    signal cnt : std_logic_vector(3 downto 0);

    signal cn1 : std_logic_vector(3 downto 0);

    signal carr : std_logic_vector(3 downto 1);

    signal tmp : std_logic;

    [/INDENT]begin

    h0: halfAdder port map(cnt(0), '1', cn1(0), carr(1));

    h1: halfAdder port map(cnt(1), carr(1), cn1(1), carr(2));

    h2: halfAdder port map(cnt(2), carr(2), cn1(2), carr(3));

    cn1(3) <= cnt(3) xor carr(3);

    process(sysclk, sysrst)

    constant clow : std_logic_vector(3 downto 0) := x"7";

    constant chigh : std_logic_vector(3 downto 0) := x"F";

    begin

    if sysrst = '0' then

    cnt <= x"0";

    elsif sysclk = '1' and sysclk'event then

    cnt <= cn1;

    if cnt < clow then

    tmp <= '0';

    elsif cnt >= clow and cnt < chigh then

    tmp <= '1';

    else

    cnt <= x"0";

    end if;

    end if;

    clkdiv <= tmp;

    [/INDENT]end process;

    [/INDENT]end architecture;

    Maybe it can be improved, but at least I can make it fit in the CPLD since a reduction of ~16% than using the classic "variable <= variable + '1';

    Thanks all you guys,
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Maybe it can be improved, but at least I can make it fit in the CPLD since a reduction of ~16% than using the classic "variable <= variable + '1';

    --- Quote End ---

    Seriously, I don't understand what you are talking about. The "classic variable = variable + 1" consumes exactly 4 MAX 3000 macrocells for a 4-bit counter, as expectable. You can use the Quartus binary counter template as reference, as suggested. Hopefully, your code can keep up. I couldn't check it, because I miss your halfAdder component.

    Particularly the 16% number sounds dubious. What are you comparing with?

    P.S.: Assuming your code is calculating correctly (your first one didn't, as I showed), it's still consuming extra resources, because it's double registering the result. That's something, the compiler can't optimize away, because it thinks you mean it. So it surely won't achieve the 4 macrocells reference.

    P.P.S.: Of course, you are able to achieve the minimal implementation also using halfadders, or whatever style you prefer, respectively are required to. But the sequential code must create only a single level of registers, one for each counter bit. The design compiler should be clever enough to minimize the combinational part (the adder logic) to the basic arithmetic operation.

    One more supplement: I erroneously stated, that the result is double registered. But you are consuming additional resources by decoding an unsuitable range for the clkdiv output. As long as you don't require aparticular coding, you can simply output the counter MSB, which returns to the minimal 4 macrocell solution.

    It's also interesting to see, how a counter is implemented in a MAX3000 CPLD. Even though you can suggest adders with carry, the compiler won't use it. At least up to a 32 bit counter, it uses a huge logic term combining all DFF outputs. If you consult the MAX3000 hardware handbook, you'll understand why. Of course it's completely different when synthesizing FPGA hardware.