MyHDL

Could modbv support non powers of two?

I find myself very frequently writing

if reg != reg.max - 1:
reg.next = reg + 1
else:
reg.next = 0

This seems the perfect fit for a modbv, but not yet have I actually encountered this where my max is a power of two (seems hard to believe but it’s true).

In simulation it will accept (almost) arbitrary boundaries for both the min= and max= settings; so you could use reg.next = reg + 1 but that line would simply get converted to reg <= reg + 1; and that may not be what you want.

So perhaps we should add a rider to the docs that modbv are only useful for powers of two … if you are going to convert the design to VHDL or Verilog

If reg is just a counter, the following pattern is often more economical:

if reg == 0:
    reg.next = reg.max - 1
    # Do stuff here
else:
    reg.next = reg - 1
1 Like

Thanks Josy, so I guess your position is no, modbv shouldn’t support non powers of two?

Thanks I’ll keep that in mind, I could run my circular arrays backwards for sure :slight_smile:

Not really, it still is a comparison, no?

It is not a question of what my inclination is; at the moment it does not support conversion of non-powers of 2. Making it convert non-powers of 2 has implications and may end up in less than minimal resources.
Anyway if you have lots of counters with this non-power of 2 requirement, a good idea is to create a re-usable module for it. It makes for nice clean structural code.

I hope this reply doesn’t come across as disrespectful, because I know you are a very active part of this community and so you already have my respect :slight_smile: I am of course aware that currently Modbv does not support non powers of two, and my feature request is firstly a question to those who know more than me (because I know very little) if it would be a sensible thing to do, so I am very interested in your opinion.

I could edit my own modbv which does as I wish (supports any modulo) and I’d be happy enough, I just wish to avoid being selfish, and thought others may find it a useful feature, I can’t be the only one who needs it (I’m really not that special!)

None taken.
The _modbv.py already supports any modulo; in simulation it will enforce values between .min and .max.
For conversion the required changes are in _toVHDL.py and _toVerilog.py where you have to intercept the assignment and replace it by several lines of code. That’s may be not that difficult. But that will kind of break existing code (from other users): code like you describe above

if reg == max - 1:
    reg.next = 0
else:
    reg.next = reg + 1

will then convert to:

if reg = max - 1 then
    if 0 < reg.min then
        reg <= reg.min;
   else
      if  0 >= reg.max then
         reg <= reg.max - 1;
      else
         reg <= 0;
      end if;
   end if ;
else
   if reg + 1 < reg,min then
        reg <= reg.min;
   else
      if reg + 1 >= reg.max then
        reg <= reg.max - 1;
      else
           reg <= reg + 1;
      end if;
   end if;
end if ;

Note that if the right hand side of the assignment is complex, things may get even more complicated.
If you work hard at it, you may eventually clean that up to representable code. I suggest you give it a try.
But I am sure that you will find that writing a re-usable HDL module to do this will be a lot less work.

But with hindsight; I think that the modbv should have be restricted to powers of 2 for simulation also. I estimate that 99.9% of the users use it like that anyway.

Thanks that’s amazing information! :slight_smile: I agree that modbv should behave the same in simulation and conversion.

In my application I don’t use min != 0, and I am only ever incrementing by 1. Maybe for me a counter type would be better, with the choice between saturate/roll over behaviour (because I often want saturating counters as well, but maybe this is all a symptom that I’m still thinking too procedurally?)

Can you give me a little example of how this reusable module would work? I only know how to instantiate modules and pass signals in/out. I couldn’t pass in an “inc” signal because then the increment would be necessarily delayed by one cycle. Is there some way I can tell this new self-contained code to perform its increment behaviour without incurring a 1 clock delay? Or I should pass the signal as a wire? That doesn’t sound right, and I am not sure how to do that, and besides can you use a wire as the input for and if statement?

Unfortunately writing myhdl is my first foray into both HDL and python, and while I’ve been doing it on and off for 18 months now (and have working designs) it isn’t my primary focus and so I still struggle with anything beyond the basics!

Perhaps send me a not too big sample from your code base where you have several counters of your type. I will rewrite it as an example. And add the necessary explanations.