Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Counting number of asserted register bits in VHDL

Reply
Thread Tools

Counting number of asserted register bits in VHDL

 
 
bucketonuts@gmail.com
Guest
Posts: n/a
 
      05-14-2013
Hello,

I have a status register of width, R_SIZE. This is a generic so the register width may be different depending on the application. The R_SIZE is limited to values, 4, 8 and 16.

Each bit in the register is set by different module as an indication of that module's done status. These status bits are asserted for only one clock and may be asserted again as each module may run its application multiple times on different data.

I need to count the number of bits set in the status register on each clock and accumulate a total to match a predetermined "max" value.

I thought I'd use the VHDL 'generate' statement to compile RTL based on R_SIZE as follows.

=================== start RTL =====================
architecture behave of b is

component modx port(
mod_cmplt : out std_logic
);
end component modx;

signal mod_cmplt : std_logic_vector(15 downto 0);
signal cmplt_cnt : integer range 0 to 512;
signal next_cmplt_cnt : integer range 0 to 512;

begin
mod_cmplt(15 downto R_SIZE) <= (others => '0');

g1: for i in 0 to R_SIZE-1 generate
u_modx : modx port map(
mod_cmplt => mod_cmplt(i)
);
end generate;

process (mod_cmplt, cmplt_cnt)
begin
next_cmplt_cnt <= cmplt_cnt;

gen4: if R_SIZE = 4 generate
next_cmplt_cnt <= mod_cmplt(0) + mod_cmplt(1) + mod_cmplt(2) +
mod_cmplt(3) + cmplt_cnt;
end generate;

gen8: if R_SIZE = 8 generate
next_cmplt_cnt <= mod_cmplt(0) + mod_cmplt(1) + mod_cmplt(2) +
mod_cmplt(3) + mod_cmplt(4) + mod_cmplt(5) +
mod_cmplt(6) + mod_cmplt(7) + cmplt_cnt;
end generate;

gen16:if R_SIZE = 16 generate
next_cmplt_cnt <= mod_cmplt(0) + mod_cmplt(1) + mod_cmplt(2) +
mod_cmplt(3) + mod_cmplt(4) + mod_cmplt(5) +
mod_cmplt(6) + mod_cmplt(7) + mod_cmplt( +
mod_cmplt(9) + mod_cmplt(10) + mod_cmplt(11) +
mod_cmplt(12) + mod_cmplt(13) + mod_cmplt(14) +
mod_cmplt(15) + cmplt_cnt;
end generate

end process;

process (reset, clk)
begin
if (reset = '1') then
cmplt_cnt <= 0;
elsif (clk'event and clk='1')
cmplt_cnt <= next_cmplt_cnt;
end if;
end process

end behave;
================================ end RTL =================

The first error I get is a syntax error:

Error-[IEEEVHDLSYNTAXERR] Syntax error

gen4: if R_SIZE = 4 generate
^
Syntax error detected during VHDL parsing.

I don't know what to do about this. Is there a better way to code what I want the system to do?

Thank you.

 
Reply With Quote
 
 
 
 
GaborSzakacs
Guest
Posts: n/a
 
      05-14-2013
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Hello,
>
> I have a status register of width, R_SIZE. This is a generic so the register width may be different depending on the application. The R_SIZE is limited to values, 4, 8 and 16.
>
> Each bit in the register is set by different module as an indication of that module's done status. These status bits are asserted for only one clock and may be asserted again as each module may run its application multiple times on different data.
>
> I need to count the number of bits set in the status register on each clock and accumulate a total to match a predetermined "max" value.
>
> I thought I'd use the VHDL 'generate' statement to compile RTL based on R_SIZE as follows.
>
> =================== start RTL =====================
> architecture behave of b is
>
> component modx port(
> mod_cmplt : out std_logic
> );
> end component modx;
>
> signal mod_cmplt : std_logic_vector(15 downto 0);
> signal cmplt_cnt : integer range 0 to 512;
> signal next_cmplt_cnt : integer range 0 to 512;
>
> begin
> mod_cmplt(15 downto R_SIZE) <= (others => '0');
>
> g1: for i in 0 to R_SIZE-1 generate
> u_modx : modx port map(
> mod_cmplt => mod_cmplt(i)
> );
> end generate;
>
> process (mod_cmplt, cmplt_cnt)
> begin
> next_cmplt_cnt <= cmplt_cnt;
>
> gen4: if R_SIZE = 4 generate
> next_cmplt_cnt <= mod_cmplt(0) + mod_cmplt(1) + mod_cmplt(2) +
> mod_cmplt(3) + cmplt_cnt;
> end generate;
>
> gen8: if R_SIZE = 8 generate
> next_cmplt_cnt <= mod_cmplt(0) + mod_cmplt(1) + mod_cmplt(2) +
> mod_cmplt(3) + mod_cmplt(4) + mod_cmplt(5) +
> mod_cmplt(6) + mod_cmplt(7) + cmplt_cnt;
> end generate;
>
> gen16:if R_SIZE = 16 generate
> next_cmplt_cnt <= mod_cmplt(0) + mod_cmplt(1) + mod_cmplt(2) +
> mod_cmplt(3) + mod_cmplt(4) + mod_cmplt(5) +
> mod_cmplt(6) + mod_cmplt(7) + mod_cmplt( +
> mod_cmplt(9) + mod_cmplt(10) + mod_cmplt(11) +
> mod_cmplt(12) + mod_cmplt(13) + mod_cmplt(14) +
> mod_cmplt(15) + cmplt_cnt;
> end generate
>
> end process;
>
> process (reset, clk)
> begin
> if (reset = '1') then
> cmplt_cnt <= 0;
> elsif (clk'event and clk='1')
> cmplt_cnt <= next_cmplt_cnt;
> end if;
> end process
>
> end behave;
> ================================ end RTL =================
>
> The first error I get is a syntax error:
>
> Error-[IEEEVHDLSYNTAXERR] Syntax error
>
> gen4: if R_SIZE = 4 generate
> ^
> Syntax error detected during VHDL parsing.
>
> I don't know what to do about this. Is there a better way to code what I want the system to do?
>
> Thank you.
>


I'm not up enough on VHDL to tell you if it's even valid
to have generate statements within a process, but the point is
that you don't need them here. Since mod_cmplt is always the
same size regardless of the value of R_SIZE, you can just use
if ... elsif ... else without the generates. Or even use a case
statement. Basically there's nothing in your equations that
requires generate statements. And note that because R_SIZE is
known at compile time it won't create extra logic.

--
Gabor
 
Reply With Quote
 
 
 
 
kevin.neilson@xilinx.com
Guest
Posts: n/a
 
      05-14-2013
Yeah, it seems like something much simpler like this would work fine:

process (reset, clk)
variable sum : integer := 0;
begin
if (reset = '1') then
cmplt_cnt <= 0;
elsif (clk'event and clk='1')
for k in 0 to R_SIZE - 1 loop
sum := sum + mod_cmplt(k);
end loop;
cmplt_cnt <= cmplt_cnt + sum;
end if;
end process;
 
Reply With Quote
 
bucketonuts@gmail.com
Guest
Posts: n/a
 
      05-15-2013
On Tuesday, May 14, 2013 4:52:31 PM UTC-4, Gabor Sz wrote:
>
>
>
> I'm not up enough on VHDL to tell you if it's even valid
>
> to have generate statements within a process, but the point is
>
> that you don't need them here. Since mod_cmplt is always the
>
> same size regardless of the value of R_SIZE, you can just use
>
> if ... elsif ... else without the generates. Or even use a case
>
> statement. Basically there's nothing in your equations that
>
> requires generate statements. And note that because R_SIZE is
>
> known at compile time it won't create extra logic.
>
>
>
> --
>
> Gabor


Thank you. I thought about this but didn't know what would happen to the adder if only 8 modx modules were instantiated. Even though the if-else branch for 16 modx's wouldn't be reached, the adder would still have inputs for modx[8]to modx[15] which would not be driven.
Also, you are correct, generate statements may not be located in a process.
Thanks again.
 
Reply With Quote
 
bucketonuts@gmail.com
Guest
Posts: n/a
 
      05-15-2013
On Tuesday, May 14, 2013 7:05:00 PM UTC-4, (E-Mail Removed) wrote:
> Yeah, it seems like something much simpler like this would work fine:
>
>
>
> process (reset, clk)
>
> variable sum : integer := 0;
>
> begin
>
> if (reset = '1') then
>
> cmplt_cnt <= 0;
>
> elsif (clk'event and clk='1')
>
> for k in 0 to R_SIZE - 1 loop
>
> sum := sum + mod_cmplt(k);
>
> end loop;
>
> cmplt_cnt <= cmplt_cnt + sum;
>
> end if;
>
> end process;


Thank you - this looks interesting. So sum gets evaluated at clk'event in time for cmplt_cnt to be updated with the new value of sum?
 
Reply With Quote
 
GaborSzakacs
Guest
Posts: n/a
 
      05-15-2013
(E-Mail Removed) wrote:
> On Tuesday, May 14, 2013 4:52:31 PM UTC-4, Gabor Sz wrote:
>>
>>
>> I'm not up enough on VHDL to tell you if it's even valid
>>
>> to have generate statements within a process, but the point is
>>
>> that you don't need them here. Since mod_cmplt is always the
>>
>> same size regardless of the value of R_SIZE, you can just use
>>
>> if ... elsif ... else without the generates. Or even use a case
>>
>> statement. Basically there's nothing in your equations that
>>
>> requires generate statements. And note that because R_SIZE is
>>
>> known at compile time it won't create extra logic.
>>
>>
>>
>> --
>>
>> Gabor

>
> Thank you. I thought about this but didn't know what would happen to the adder
> if only 8 modx modules were instantiated. Even though the if-else

branch for
> 16 modx's wouldn't be reached, the adder would still have inputs for

modx[8]
> to modx[15] which would not be driven.
> Also, you are correct, generate statements may not be located in a process.
> Thanks again.


Actually the adder would not have extra undriven inputs _because_ those
branches are not reached, and the synthesizer only implements code that
is reached. For the cases where you don't have the maximum R_SIZE,
there would be some unused (and undriven) signals, but these would
generally get trimmed at or after physical synthesis. If you used
the other example with a loop, you could size the mod_cmplt vector
using R_SIZE and then there would be no unused signals. If you like
to avoid warnings during synthesis and build, then that is a cleaner
approach.

--
Gabor
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      05-15-2013
A nice little problem to illustrate VHDL RTL...

I don't know if it makes a real difference, but constraining the range of sum is seldom a bad idea:

variable sum : natural range 0 to mod_cmplt'length;

Don't forget to initialize sum to 0 before the loop, on every clock cycle. Variable declaration initializations in processes only happen once, at time0.

Also, syntactic tricks are required to add a std_logic bit to an integer and get an integer result:

sum := sum + to_integer(unsigned(0 => mod_cmplt(k)));

Or simply:

if mod_complt(k) = '1' then
sum := sum + 1;
end if;

Since cmplt_cnt is an integer, you need to make sure it never overflows. Presumably it would be set to zero once it reaches some limit where somethinghappens. If you want cmplt_cnt to roll over, either use mod (modulo operator) or make cmplt_cnt an unsigned instead of integer type (sum can still beinteger, and it cannot overflow).

More syntactic sugar: when iterating in a loop over the range of a vector, use vector'range as the loop index range:

for k in mod_cmplt'range loop

Finally, if you want to pipeline the sum and cmplt_cnt updates, just updatecnt_cmplt before sum is initialized:

pipelined: process (rst, clk) is
variable sum : natural range 0 to mod_cmplt'length;
begin
if rst = '1' then
cmplt_cnt <= 0;
sum := 0; -- used as register, so reset it
elsif rising_edge(clk) then
cmplt_cnt <= cmplt_cnt + sum; -- sum is register here
sum := 0; -- sum is combinatorial hereafter
for k in mod_complt'range loop
sum := sum + to_integer(unsigned(0 => mod_cmplt(k)));
end loop;
end if;
end process pipelined;

Andy
 
Reply With Quote
 
bucketonuts@gmail.com
Guest
Posts: n/a
 
      05-15-2013
On Wednesday, May 15, 2013 11:47:16 AM UTC-4, Andy wrote:
> A nice little problem to illustrate VHDL RTL...
>
>
>
> I don't know if it makes a real difference, but constraining the range ofsum is seldom a bad idea:
>
>
>
> variable sum : natural range 0 to mod_cmplt'length;
>
>
>
> Don't forget to initialize sum to 0 before the loop, on every clock cycle.. Variable declaration initializations in processes only happen once, at time 0.
>
>
>
> Also, syntactic tricks are required to add a std_logic bit to an integer and get an integer result:
>
>
>
> sum := sum + to_integer(unsigned(0 => mod_cmplt(k)));
>
>
>
> Or simply:
>
>
>
> if mod_complt(k) = '1' then
>
> sum := sum + 1;
>
> end if;
>
>
>
> Since cmplt_cnt is an integer, you need to make sure it never overflows. Presumably it would be set to zero once it reaches some limit where something happens. If you want cmplt_cnt to roll over, either use mod (modulo operator) or make cmplt_cnt an unsigned instead of integer type (sum can still be integer, and it cannot overflow).
>
>
>
> More syntactic sugar: when iterating in a loop over the range of a vector, use vector'range as the loop index range:
>
>
>
> for k in mod_cmplt'range loop
>
>
>
> Finally, if you want to pipeline the sum and cmplt_cnt updates, just update cnt_cmplt before sum is initialized:
>
>
>
> pipelined: process (rst, clk) is
>
> variable sum : natural range 0 to mod_cmplt'length;
>
> begin
>
> if rst = '1' then
>
> cmplt_cnt <= 0;
>
> sum := 0; -- used as register, so reset it
>
> elsif rising_edge(clk) then
>
> cmplt_cnt <= cmplt_cnt + sum; -- sum is register here
>
> sum := 0; -- sum is combinatorial hereafter
>
> for k in mod_complt'range loop
>
> sum := sum + to_integer(unsigned(0 => mod_cmplt(k)));
>
> end loop;
>
> end if;
>
> end process pipelined;
>
>
>
> Andy


Thanks, Andy. I'm new to VHDL. It took me most of the morning to figure outhow to add a std_logic bit to an integer (to_integer). You make some very good points in the rest of your post as well.
 
Reply With Quote
 
kevin.neilson@xilinx.com
Guest
Posts: n/a
 
      05-16-2013
Andy,
Thanks--I wasn't sure if the variable had to be initialized to zero. I don't use variables often.

I elided the type conversion in my code snippet (even though that's where Ispend half my VHDL development time). I tried your std_logic->integer conversion above and Synplify didn't seem to be liking it, and I ended up having to do a ridiculous conversion like this:

sum := sum + to_integer(unsigned(std_logic_vector'(0=>mod_cmplt (k))));

This is why Verilog is awesome. You want to add a real number and the msb of an integer and a slice of a character string? No problem; no conversions required.
-Kevin
 
Reply With Quote
 
Nicolas Matringe
Guest
Posts: n/a
 
      05-16-2013
Le 16/05/2013 21:42, (E-Mail Removed) a écrit :

> This is why Verilog is awesome. You want to add a real number and the msb of an integer and
> a slice of a character string? No problem; no conversions required.


That's weak typing's advantage. But it lets you so easily shoot yourself
in the foot...

Nicolas
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Portable/standard way of counting number of bits in variable? Dale Dellutri C Programming 9 04-04-2009 03:40 PM
counting up instead of counting down edwardfredriks Javascript 6 09-07-2005 03:30 PM
what about unsigned and signed 8 bits number, 16 bits, etc?? sarmin kho Python 2 06-15-2004 06:40 PM
Re: what about unsigned and signed 8 bits number, 16 bits, etc?? Miki Tebeka Python 1 06-14-2004 03:19 PM
8-Bits vs 12 or 16 bits/pixel; When does more than 8 bits count ? Al Dykes Digital Photography 3 12-29-2003 07:08 PM



Advertisments