Thread: [myhdl-list] Problems converting an integer assignment into VHDL
Brought to you by:
jandecaluwe
From: Angel E. <ang...@gm...> - 2012-10-11 08:32:00
|
Hi, I got an issue with conversion to VHDL, where MyHDL seems to do the wrong thing (although most likely it's me who is doing it wrong). The problem is that MyHDL maps an integer assignment into an intbv signal as a direct integer assignment in VHDL, instead of using a to_unsigned conversion. That is, I got a signal declared as follows: signal s_my_signal: unsigned(29 downto 0); Then I do: s_my_signal.next = s_my_signal.max - 1 which in VHDL becomes: s_my_signal.next <= 1073741824 - 1; Which is wrong. Instead I expected it to be: s_my_signal.next <= to_unsigned(1073741824 - 1, 30); Or something of the sort. I thought that I could fix the problem by doing: s_my_signal.next = intbv(1073741824.max)[len(s_2pps_counter):] Which would be unnecessarily verbose (IMHO) but in fact it makes matters worse, as it converts into: s_2pps_counter <= 1073741824(30-1 downto 0); Is there something I'm doing wrong? Additionally, is this the best way to initialize an unsigned signal to all 1's? This is probably not in the "MyHDL style" but for now I'm just trying to convert an existing VHDL module into MyHDL just to get the feel of things. Thanks, Angel |
From: Norbo <Nor...@gm...> - 2012-10-11 09:24:48
|
Am 11.10.2012, 10:31 Uhr, schrieb Angel Ezquerra <ang...@gm...>: > Hi, > > I got an issue with conversion to VHDL, where MyHDL seems to do the > wrong thing (although most likely it's me who is doing it wrong). > > The problem is that MyHDL maps an integer assignment into an intbv > signal as a direct integer assignment in VHDL, instead of using a > to_unsigned conversion. > > That is, I got a signal declared as follows: > > signal s_my_signal: unsigned(29 downto 0); > > Then I do: > > s_my_signal.next = s_my_signal.max - 1 > > which in VHDL becomes: > > s_my_signal.next <= 1073741824 - 1; > > Which is wrong. Instead I expected it to be: > > s_my_signal.next <= to_unsigned(1073741824 - 1, 30); > Yup that causes problems. which is funny because if you write in the myhdl code: s_my_signal.next <= 1073741824 - 1; the result is: s_my_signal <= to_unsigned(1073741824 - 1, 30); or if you write: CONST_MAX=s_my_signal.max @always(clk.posedge) def ttt(): s_my_signal.next <= CONST_MAX - 1; which converts to: s_my_signal <= to_unsigned(1073741824 - 1, 30); if you write: s_my_signal.next = int(s_my_signal.max) - 1 it converts to: s_my_signal <= to_unsigned(1073741824 - 1, 30); or if you write: s_my_signal.next = intbv(s_my_signal.max) - 1 it converts to: s_my_signal <= to_unsigned(1073741824 - 1, 30); so it turns out that the converter doesn't recognise the "s_my_signal.max" as an const integer, but instead as a signal. This seems to be also the case for the simulator. e.g: In a combinatorical process this leads to a -> combinatorical loop error, when there is actually none. sigTest=Signal(intbv(0)[4:]) @always_comb def comb_setConst(): sigTest.next=int(sigTest.max)-1 leads to the error message: --myhdl.AlwaysCombError: signal (sigTest) used as inout in always_comb function argument but it could be written like this: sigTest=Signal(intbv(0)[4:]) maxvalue=sigTest.max @always_comb def comb_setConst(): sigTest.next=maxvalue-1 this would make the simulator core happy and would be fine if the sensitivity list is not empty!! greetings Norbert |
From: Angel E. <ang...@gm...> - 2012-10-11 10:06:19
|
Thank you Norbo. My comments below. On Thu, Oct 11, 2012 at 11:24 AM, Norbo <Nor...@gm...> wrote: > Am 11.10.2012, 10:31 Uhr, schrieb Angel Ezquerra > <ang...@gm...>: > >> Hi, >> >> I got an issue with conversion to VHDL, where MyHDL seems to do the >> wrong thing (although most likely it's me who is doing it wrong). >> >> The problem is that MyHDL maps an integer assignment into an intbv >> signal as a direct integer assignment in VHDL, instead of using a >> to_unsigned conversion. >> >> That is, I got a signal declared as follows: >> >> signal s_my_signal: unsigned(29 downto 0); >> >> Then I do: >> >> s_my_signal.next = s_my_signal.max - 1 >> >> which in VHDL becomes: >> >> s_my_signal.next <= 1073741824 - 1; >> >> Which is wrong. Instead I expected it to be: >> >> s_my_signal.next <= to_unsigned(1073741824 - 1, 30); >> > > Yup that causes problems. which is funny because if you write in the myhdl > code: > > s_my_signal.next <= 1073741824 - 1; > > the result is: > > s_my_signal <= to_unsigned(1073741824 - 1, 30); > > or if you write: > > CONST_MAX=s_my_signal.max > @always(clk.posedge) > def ttt(): > s_my_signal.next <= CONST_MAX - 1; > > > which converts to: > > s_my_signal <= to_unsigned(1073741824 - 1, 30); > > > if you write: > > s_my_signal.next = int(s_my_signal.max) - 1 > > it converts to: > > s_my_signal <= to_unsigned(1073741824 - 1, 30); > > > > or if you write: > > s_my_signal.next = intbv(s_my_signal.max) - 1 > > it converts to: > > s_my_signal <= to_unsigned(1073741824 - 1, 30); The problem is even easier to run into, since the convertor fails if you do not add anything. This: s_2pps_counter.next = int(s_2pps_counter.min) Converts into: s_2pps_counter <= 0; Which is wrong, while this: s_2pps_counter.next = int(s_2pps_counter.min) + 0 Converts into: s_2pps_counter <= to_unsigned(0 + 0, 30); Which is correct. Another failure is that this: s_2pps_counter.next = int(s_2pps_counter.min) + 0 Converts into: s_2pps_counter <= to_integer(0 + 0); Which is also wrong. So you cannot just use "int" to make sure that .min and .max are properly interpreted. > so it turns out that the converter doesn't recognise the "s_my_signal.max" > as an const integer, but instead as a signal. > This seems to be also the case for the simulator. That seems to be the problem indeed. > e.g: In a combinatorical process this leads to a -> combinatorical loop > error, when there is actually none. > > > sigTest=Signal(intbv(0)[4:]) > @always_comb > def comb_setConst(): > sigTest.next=int(sigTest.max)-1 > > > leads to the error message: > > --myhdl.AlwaysCombError: signal (sigTest) used as inout in always_comb > function argument > > > > but it could be written like this: > > sigTest=Signal(intbv(0)[4:]) > maxvalue=sigTest.max > @always_comb > def comb_setConst(): > sigTest.next=maxvalue-1 > > this would make the simulator core happy and would be fine if the > sensitivity list is not empty!! Yes, it seems that using an intermediate variable to get the value of s_my_signal.max works fine and is an easy work around. That being said, is this technique to set a signal to all '1' the one you guys would use? Or is there a more idiomatic way? Cheers, Angel |
From: Ben <ben...@gm...> - 2012-10-11 11:48:45
|
On Thu, Oct 11, 2012 at 12:06 PM, Angel Ezquerra <ang...@gm...> wrote: > That being said, is this technique to set a signal to all '1' the one > you guys would use? Or is there a more idiomatic way? > With all my respect, you are looking at it the wrong way. I know you are trying to 'translate' a module from VHDL to MyHDL, but you should understand that both language are far from being 'equivalent'. With MyHDL, you are climbing in the abstraction, and trying to write your MyHDL so that it looks like the VHDL can only produce poor code. Try to take some time, and think of the functionality of your module again, do that the MyHDL way, with all the power of Python, you could get some nice surprises. Your code should become simpler. I understand it's difficult at first to completely grasp the power of the tool you have at hand. You saw it running, it has some nice features, but where do they end ? I saw lately some nice examples with the signal containers for instance, especially the one that did not necessitate any modification of the MyHDL source code, support for it is there, simply because it's python. Your value of 111....111, what is it ? an invalid state ? an uninitialised state ? a valid one? Each of those answer has it's own way to write it. You should step up and forget about the 1 and the 0 ... Hope this helps. Have fun coding ! Benoît. |
From: Angel E. <ang...@gm...> - 2012-10-11 12:22:05
|
Benoit, thank you for your comment. I think your advice is sensible. However I have two purposes with this: 1. Learn the nits of the language. What can be done and what cannot be done 2. See how I can use MyHDL on a project that already uses VHDL #1 is the reason why I am trying to convert an existing module. I know what it must do so it is easy to try the current behavior. I purposely tried to directly translate it, rather than coding it from scratch just to see what VHDL constructs translate well to MyHDL and which do not. I hope this will also teach which constructs are synthesizable and which are not. My intention is to rewrite it again from scratch once this intial learning phase is done. Most importantly however, purpose #2 places several fundamental limitations on how I can use the language. In particular I am bound to use the interfaces that are provided to me by the rest of the modules on our project, most of which I cannot control. All our interfaces use std_logic_vectors and often these std_logic_vectors group several fields (which are simply concatenated). This is often quite low level (which I guess is common when writing synthesizable VHDL code) and forces me to work with and "think in bits" even if that is not the natural level of abstraction of MyHDL. For example our current interfaces sometimes use the "all 1" value to indicate that some data is invalid. My first approach to this in MyHDL was to "forget about the bits" and set the value of that signal using its max property (minus 1). However this does not work that well (as discussed on another thread). This is exactly the kind of thing I am trying to discover. I think it would be much easier to follow your advice if I were to use MyHDL on a project that were started from scratch. But unfortunately that is not the case :-( Cheers, Angel On Thu, Oct 11, 2012 at 1:48 PM, Ben <ben...@gm...> wrote: > On Thu, Oct 11, 2012 at 12:06 PM, Angel Ezquerra > <ang...@gm...> wrote: >> That being said, is this technique to set a signal to all '1' the one >> you guys would use? Or is there a more idiomatic way? >> > > With all my respect, you are looking at it the wrong way. > > I know you are trying to 'translate' a module from VHDL to MyHDL, but > you should understand that both language are far from being > 'equivalent'. With MyHDL, you are climbing in the abstraction, and > trying to write your MyHDL so that it looks like the VHDL can only > produce poor code. > > Try to take some time, and think of the functionality of your module > again, do that the MyHDL way, with all the power of Python, you could > get some nice surprises. Your code should become simpler. > > I understand it's difficult at first to completely grasp the power of > the tool you have at hand. You saw it running, it has some nice > features, but where do they end ? I saw lately some nice examples with > the signal containers for instance, especially the one that did not > necessitate any modification of the MyHDL source code, support for it > is there, simply because it's python. > > Your value of 111....111, what is it ? an invalid state ? an > uninitialised state ? a valid one? Each of those answer has it's own > way to write it. You should step up and forget about the 1 and the 0 > ... > > Hope this helps. > > Have fun coding ! > Benoît. |
From: Christopher F. <chr...@gm...> - 2012-10-11 14:52:41
|
<snip> > > > so it turns out that the converter doesn't recognise the "s_my_signal.max" > as an const integer, but instead as a signal. > This seems to be also the case for the simulator. > e.g: In a combinatorical process this leads to a -> combinatorical loop > error, when there is actually none. > > > sigTest=Signal(intbv(0)[4:]) > @always_comb > def comb_setConst(): > sigTest.next=int(sigTest.max)-1 > > Yes, in a generator an "buried" constant can't be used. The converter will not walk down the structure (list, dict, class, etc) to find the value. On the right hand side the only valid types are for conversion: int, long, intbv, bool A Signal can also be on the right hand side as lot as the Signal contains one of the above types. Another method vs. converting to an int would be Max = sigTest.max @always_comb def com_setConst(): sigTest.next = Max-1 The error that occurred in simulation is slightly different. Because you could use the above in an @always decorator and in simulation it will work but it will not convert. The in / out is to protect from infinite recursive delta cycles. @always_comb def hdl(): sigTest.next = not sigTest Regards, Chris |
From: Christopher F. <chr...@gm...> - 2012-10-11 15:15:49
|
On 10/11/2012 9:52 AM, Christopher Felton wrote: > <snip> >> >> >> so it turns out that the converter doesn't recognise the "s_my_signal.max" >> as an const integer, but instead as a signal. >> This seems to be also the case for the simulator. >> e.g: In a combinatorical process this leads to a -> combinatorical loop >> error, when there is actually none. >> >> >> sigTest=Signal(intbv(0)[4:]) >> @always_comb >> def comb_setConst(): >> sigTest.next=int(sigTest.max)-1 >> >> > > Yes, in a generator an "buried" constant can't be used. > The converter will not walk down the structure (list, > dict, class, etc) to find the value. On the right hand > side the only valid types are for conversion: > > int, long, intbv, bool > I didn't mention the special case of tuple of ints and list of signals. These two cases a structure can be used on the right hand side. .chris |
From: Angel E. <ang...@gm...> - 2012-10-11 16:48:29
|
On Thu, Oct 11, 2012 at 4:52 PM, Christopher Felton <chr...@gm...> wrote: > <snip> >> >> >> so it turns out that the converter doesn't recognise the "s_my_signal.max" >> as an const integer, but instead as a signal. >> This seems to be also the case for the simulator. >> e.g: In a combinatorical process this leads to a -> combinatorical loop >> error, when there is actually none. >> >> >> sigTest=Signal(intbv(0)[4:]) >> @always_comb >> def comb_setConst(): >> sigTest.next=int(sigTest.max)-1 >> >> > > Yes, in a generator an "buried" constant can't be used. > The converter will not walk down the structure (list, > dict, class, etc) to find the value. On the right hand > side the only valid types are for conversion: > > int, long, intbv, bool Does this include the result of calling a function that returns one of these types? > A Signal can also be on the right hand side as lot as > the Signal contains one of the above types. > > > Another method vs. converting to an int would be > > Max = sigTest.max > @always_comb > def com_setConst(): > sigTest.next = Max-1 > > > The error that occurred in simulation is slightly different. > Because you could use the above in an @always decorator and > in simulation it will work but it will not convert. The > in / out is to protect from infinite recursive delta cycles. > > @always_comb > def hdl(): > sigTest.next = not sigTest > > Regards, > Chris I understand that (currently?) MyHDL limits the usage of containers in synthesizable code. However, in this case I was not trying to use a custom container that I created myself. I was trying to use one of the fields of one of the built-in MyHDL data types. Technical issues aside, wouldn't it make sense for MyHDL to support those? This was quite surprising to me... Angel |
From: Norbo <Nor...@gm...> - 2012-10-11 18:52:58
|
> Yes, it seems that using an intermediate variable to get the value of > s_my_signal.max works fine and is an easy work around. > > That being said, is this technique to set a signal to all '1' the one > you guys would use? Or is there a more idiomatic way? I actually never came across this in that way before. Thanks for pointing it out, so i didn't have to run into it again!. When i did something similar the configuration looked somehow like this: def somefunc(clk,in,out,sss,BIT_WIDTH=8): sig1=Signal(intbv(0)[BIT_WIDTH:]) @always(clk.posedge) def readbla(): sig1.next=(2**BIT_WIDTH)-1 well and the other possibilities would be: sig1=Signal(intbv(0)[8:]) const_AllOne=(2**sig1._nrbits)-1 @always(clk.posedge) def readbla(): sig1.next=const_AllOne or the allready discussed quite similar one: sig1=Signal(intbv(0)[8:]) const_AllOne=sig1.max-1 @always(clk.posedge) def readbla(): sig1.next=const_AllOne iam not able to produce any other usefull way for this right now. But i actually also would prefer the direct use of the "signal.max". This seems to be at least somehow realated: http://sourceforge.net/mailarchive/message.php?msg_id=29738279 MEP would be the next step right?. greetings Norbo |
From: Christopher F. <chr...@gm...> - 2012-10-11 19:49:51
|
On 10/11/2012 1:52 PM, Norbo wrote: > >> Yes, it seems that using an intermediate variable to get the value of >> s_my_signal.max works fine and is an easy work around. >> >> That being said, is this technique to set a signal to all '1' the one >> you guys would use? Or is there a more idiomatic way? > > I actually never came across this in that way before. Thanks for pointing > it out, so i didn't have to run into it again!. > When i did something similar the configuration looked somehow like this: > > > def somefunc(clk,in,out,sss,BIT_WIDTH=8): > sig1=Signal(intbv(0)[BIT_WIDTH:]) > @always(clk.posedge) > def readbla(): > sig1.next=(2**BIT_WIDTH)-1 > > > well and the other possibilities would be: > > sig1=Signal(intbv(0)[8:]) > const_AllOne=(2**sig1._nrbits)-1 > @always(clk.posedge) > def readbla(): > sig1.next=const_AllOne > > > or the allready discussed quite similar one: > > sig1=Signal(intbv(0)[8:]) > const_AllOne=sig1.max-1 > @always(clk.posedge) > def readbla(): > sig1.next=const_AllOne > > > iam not able to produce any other usefull way for this right now. > But i actually also would prefer the direct use of the "signal.max". > This seems to be at least somehow realated: > http://sourceforge.net/mailarchive/message.php?msg_id=29738279 > MEP would be the next step right?. > > > greetings > Norbo > For me, I have adopted more of the 'intbv' versus a 'bv'. I don't use the intbv(0)[8:] as much but rather use intbv(0, min=0, max=256). And usually /256/ will be some variable, parameter (named argument), etc. sig_in = intbv(0, min=0, max=MaxInput) ... # set to max value sig_in.next = MaxInput-1 For me using the /local variable/ isn't a work around :) Looking through some of my examples I don't often explicitly set to the max. Jan's essay on Ints is worth a read if you have not. http://jandecaluwe.com/hdldesign/counting.html Regards, Chris |