Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20688 Discussions

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

Altera_Forum
Honored Contributor II
1,380 Views

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
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
440 Views

TO_BE_DONE

0 Kudos
Altera_Forum
Honored Contributor II
440 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
440 Views

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?
0 Kudos
Altera_Forum
Honored Contributor II
440 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
440 Views

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

0 Kudos
Altera_Forum
Honored Contributor II
440 Views

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,
0 Kudos
Altera_Forum
Honored Contributor II
440 Views

 

--- 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.
0 Kudos
Reply