Thread: [myhdl-list] Incorrect conclusions in TSConIT paper
Brought to you by:
jandecaluwe
From: Jan D. <ja...@ja...> - 2012-06-22 14:57:30
|
I came across a paper that compares HDLs: http://referaat.cs.utwente.nl/TSConIT/download.php?id=1144 Many conclusions and remarks about MyHDL are incorrect for the following reasons: 1) the author doesn't fully understand the nature of MyHDL/Python. This can be excused for a newbie; perhaps we have to do a better job explaining. 2) Some conclusions are based on non-functional code. No excuses here; conclusions based on code that doesn't work are not acceptable. I will first explain the conceptual errors, and then go into the details of the incorrect code (for those interested). The author makes the common error of equating MyHDL with conversion. But MyHDL is primarily about modeling in general. Conversion is really just a workaround to play well with the backend tools in established design flows. For example, he states that MyHDL only supports intbv and not floating point, which is completely wrong. For modeling purposes, any type can be used as the underlying type of a Signal. Conversion is restricted to intbv and a few other types (because its primary target is synthesis) but when the purpose is modeling and system verification, why worry about conversion? The author has critique on duck typing (which has indeed disadvantages) but fails to recognize that it is exactly this that allows MyHDL models to be written in a type-independent way. The author complains about verboseness and large amounts of conditional statements, but fails to take advantage of the idiomatic Python way to work with booleans: empty = Signal(bool(0)) ... empty.next = (dindex == 0) which would reduce the nr of lines drastically. Finally, the author complains about cryptic messages when conversion fails. Taken on its own, he has a point. It is certainly true that the conversion error reporting can be improved. However, the reason why this is such a blocking problem in this case is a flawed methodology. The author seems to consider the convertor as some kind of compiler which can help to produce working MyHDL code. But this is completely wrong. The goal of the convertor is to convert *working* MyHDL code to equivalent Verilog/VHDL. Creating working MyHDL code has to be done in the Python way. We don't have a compiler that finds a lot of errors. In a super dynamic language like Python, the run-time rules. In MyHDL, this means simulation: http://www.myhdl.org/doc/current/manual/conversion.html#simulate-first My biggest critique on the paper is that the author apparently hasn't done this. When he got stuck with conversion, his immediate reaction should have been to simulate. I believe that even a simple simulation would have revealed basic errors, and correcting those would have made conversion much more friendly. This is a severe critique, and I will show in detail why I came to this conclusion. The author presents the following example: -- from myhdl import * def firfilt (sigin, sigout, coefs, clk): buffer = Signal(intbv(0)[len(sigin)*len(coefs)]) inlen = len(sigin) saved_coefs = coefs colen = len(saved_coefs) @always(clk.posedge) def logic(): buffer.next[inlen:] = sigin buffer.next[:inlen] = buffer[inlen * (colen-1):] tmp = 0 for index in range(colen): mult = saved_coefs[inlen*(index+1):inlen*index] * \ buffer[inlen*(index +1): inlen*index] tmp = tmp + sigin sigout.next = tmp return logic def convert(): sin = Signal(intbv(0)[8:]) sout = Signal(intbv(0)[8:]) coefs = [2, 8, 6 ,20 ,3] clk = Signal(bool(0)) toVHDL(firfilt , sin , sout , coefs , clk ) convert() -- It seems clear that this code has not been simulated and cannot work. First: buffer = Signal(intbv(0)[len(sigin)*len(coefs)]) is most likely wrong as only a single bit is selected, Probably what is meant is a bit vector definition as follows: buffer = Signal(intbv(0)[inlen*colen:]) Furthermore, the following lines: mult = saved_coefs[inlen*(index+1):inlen*index] * \ buffer[inlen*(index +1): inlen*index] tmp = tmp + sigin must be wrong: what can be the purpose of multiplying a sequence of constants with a bit vector? Furthermore, it seems nothing happens with variable mult. Looking at the VHDL version, what was probably intended is something like the following: -- from myhdl import * def firfilt (sigin, sigout, coefs, clk): inlen = len(sigin) colen = len(coefs) buffer = Signal(intbv(0)[inlen*colen:]) @always(clk.posedge) def logic(): buffer.next[inlen:] = sigin buffer.next[:inlen] = buffer[inlen*(colen-1):] tmp = 0 for index in range(colen): c = coefs[index] # select one coefficient mult = c * buffer[inlen*(index +1):inlen*index] tmp = tmp + mult # mult/accumulate sigout.next = tmp return logic def convert(): sin = Signal(intbv(0)[8:]) sout = Signal(intbv(0)[8:]) coefs = (2, 8, 6, 20, 3) # tuple of constants clk = Signal(bool(0)) toVHDL(firfilt , sin , sout , coefs , clk ) convert() -- -- Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com Python as a HDL: http://www.myhdl.org VHDL development, the modern way: http://www.sigasi.com World-class digital design: http://www.easics.com |
From: Christopher F. <chr...@gm...> - 2012-06-25 12:31:00
|
<snip> > > The author complains about verboseness and large amounts > of conditional statements, but fails to take advantage of > the idiomatic Python way to work with booleans: > > empty = Signal(bool(0)) > ... > empty.next = (dindex == 0) > > which would reduce the nr of lines drastically. > I agree this is a large flaw by the author. First, as you mention, you can do better using common Python idioms. Second, I am sure there have been many debates (i.e. references) on the pros/cons of Python/Haskell/Ada. I believe considerable research should be performed on the base languages before the HDLs. IMO for the analysis in the paper to be useful you would need a prior Haskell/Python/Ada analysis on /Conciseness/, /Comprehensibility/, and /Reusablilty/ before comparing the HDLs based on the general language. And the reason you need this is that you leverage prior debates/analysis, where experienced designers have been able to comment. Otherwise the authors probably have an inherent bias because they are more familiar with one language or the other. I suppose the derived HDLs can break the base language feature but knowing that a base language had "conciseness" and the derived HDL doesn't is useful. I am not convinced /conciseness/, via the line/word metric, is useful. We can write a program with very few lines/words that is terse and conclude it is compact but most do *not* find terseness very useful (to me terse is not concise). I think the author (unintentionally?) delved into a philosophical debate by relating the number of words and lines to being concise vs. some actual objective measurement. I would say they completely missed the point on /Reusability/! Regards, Chris |
From: Christopher F. <chr...@gm...> - 2012-06-26 11:52:19
|
On 6/22/2012 9:57 AM, Jan Decaluwe wrote: > The author presents the following example: > > -- > from myhdl import * > > def firfilt (sigin, sigout, coefs, clk): > buffer = Signal(intbv(0)[len(sigin)*len(coefs)]) > inlen = len(sigin) > saved_coefs = coefs > colen = len(saved_coefs) > > @always(clk.posedge) > def logic(): > buffer.next[inlen:] = sigin > buffer.next[:inlen] = buffer[inlen * (colen-1):] > tmp = 0 > for index in range(colen): > mult = saved_coefs[inlen*(index+1):inlen*index] * \ > buffer[inlen*(index +1): inlen*index] > tmp = tmp + sigin > sigout.next = tmp > > return logic The author did a poor job picking their examples. I say this because I don't think their VHDL example is correct, either. They don't provide enough information but for the VHDL example to be correct the instantiator would need to take care of the output word size to handle the bit growth as a result of the multiplies and additions (or limit the input range). I think if they would have verified the VHDL they would have found the VHDL implementation did not meet their requirements (or any requirements for a FIR filter). Also, I don't think the author provides the description of the RAM/ROM for the coefficients in the VHDL example. The VHDL example is not a fair comparison because it would need additional description, somewhere, to define the coefficient array. Where as the MyHDL version the coefficient array description is embedded! Here is my version of the FIR filter in MyHDL that matches the simplified templated: from myhdl import * def firfilt(sig_in, sig_out, coef, clk): buffer = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) \ for ii in range(len(coef))] coef = tuple(coef) mshift = len(sig_in)-1 @always(clk.posedge) def hdl_sop(): sop = 0 # Note this adds an extra delay! (Group delay N/2+2) for ii in range(len(coef)): buffer[ii].next = sig_in if ii == 0 else buffer[ii-1] c = coef[ii] sop = sop + (buffer[ii] * c) sig_out.next = (sop >> mshift) return hdl_sop The testbench can be found here: https://bitbucket.org/cfelton/examples/src/tip/firfilt/test_firfilt.py and some plots of the working filter. http://flic.kr/p/cko2SY http://flic.kr/p/cko2Tj Note: This example is not reasonable for most implementations. A very large combinational path is created for the multiplies and accumulate (MAC). Most implementations would break this up some how, pipelining, multiple clocks ticks (flow control), etc. To be honest, I ran into a couple bumps. I had created the following version first. @always(clk.posedge) def hdl_sop(): buffer[0].next = sig_in sop = sig_in * coef[0] for ii in range(1, len(coef)): buffer[ii].next = buffer[ii-1] sop = sop + (buffer[ii-1] * coef[ii]) sig_out.next = (sop >> mshift) My first off the cuff, solution was to avoid an extra delay by using the sig_in and not the registered version. But this didn't follow the list of signals (LoS) memory template and was not convertible. This can be fixed by not including the LoS access in the expressions. @always(clk.posedge) def hdl_sop(): buffer[0].next = sig_in c = coef[0] sop = sig_in * c for ii in range(1, len(coef)): buffer[ii].next = buffer[ii-1] c = coef[ii] sop = sop + (buffer[ii-1] * c) sig_out.next = (sop >> mshift) This is one of those rules that you have to remember but there is good reason. You are getting the coefficient description (in this case a ROM) without needing a completely separate generator, the description is conveniently embedded. Well almost conveniently, you do have to access the /tuple of ints/ (ToI) separately. If the ToI is not access separately the conversion code would have to infer signals between the ROM description and the expressions, which might not be desirable (at least that is my understanding?). The one thing the authors inadvertently demonstrate, is the *importance* of verifying the design even if the example isn't the main focus. As you point out, how can you make any kind of reasonable argument if one language is more /concise/, /comprehensible/, or /reusable/ if the example is not even functional! Regards, Chris |
From: Norbo <Nor...@gm...> - 2012-06-29 17:43:41
|
Am 26.06.2012, 13:51 Uhr, schrieb Christopher Felton <chr...@gm...>: > On 6/22/2012 9:57 AM, Jan Decaluwe wrote: >> The author presents the following example: >> >> -- >> from myhdl import * >> >> def firfilt (sigin, sigout, coefs, clk): >> buffer = Signal(intbv(0)[len(sigin)*len(coefs)]) >> inlen = len(sigin) >> saved_coefs = coefs >> colen = len(saved_coefs) >> >> @always(clk.posedge) >> def logic(): >> buffer.next[inlen:] = sigin >> buffer.next[:inlen] = buffer[inlen * (colen-1):] >> tmp = 0 >> for index in range(colen): >> mult = saved_coefs[inlen*(index+1):inlen*index] * \ >> buffer[inlen*(index +1): inlen*index] >> tmp = tmp + sigin >> sigout.next = tmp >> >> return logic > > The author did a poor job picking their examples. I say > this because I don't think their VHDL example is correct, > either. They don't provide enough information but for the > VHDL example to be correct the instantiator would need to > take care of the output word size to handle the bit growth > as a result of the multiplies and additions (or limit the > input range). I think if they would have verified the VHDL > they would have found the VHDL implementation did not meet > their requirements (or any requirements for a FIR filter). > > Also, I don't think the author provides the description of > the RAM/ROM for the coefficients in the VHDL example. The > VHDL example is not a fair comparison because it would need > additional description, somewhere, to define the coefficient > array. Where as the MyHDL version the coefficient array > description is embedded! > > Here is my version of the FIR filter in MyHDL that matches > the simplified templated: > > from myhdl import * > def firfilt(sig_in, sig_out, coef, clk): > buffer = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) \ > for ii in range(len(coef))] > coef = tuple(coef) > mshift = len(sig_in)-1 > @always(clk.posedge) > def hdl_sop(): > sop = 0 > # Note this adds an extra delay! (Group delay N/2+2) > for ii in range(len(coef)): > buffer[ii].next = sig_in if ii == 0 else buffer[ii-1] > c = coef[ii] > sop = sop + (buffer[ii] * c) > sig_out.next = (sop >> mshift) > > return hdl_sop > i just tried to run the converted vhdl through quartus and it came up with the following error: Error (10500): VHDL syntax error at firfilt.vhd(39) near text "when"; expecting ";" hm.. maybe its not supported in a clocked process but i am not so sure i have to look at that closer. the next error after i changed to a normal if i got: Error (10405): VHDL error at firfilt.vhd(78): can't determine type of object at or near identifier "shift_right" -- found 0 possible types Note: I changed buffer to bufferVal because it is a reserved keyword in vhdl My version with the initial values would look like this: def firfilt(sig_in, sig_out, coef, clk): bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) for ii in range(len(coef))] coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) for ii in coef] mshift = len(sig_in)-1 @always(clk.posedge) def hdl_sop(): sop = 0 # Note this adds an extra delay! (Group delay N/2+2) bufferVal[0].next=sig_in for ii in range(len(coef)-1): bufferVal[ii+1].next = bufferVal[ii] sop = sop + (bufferVal[ii] * coefs[ii]) sig_out.next = (sop >> mshift) return hdl_sop but there is still the shift error. greetings Norbo |
From: Christopher F. <chr...@gm...> - 2012-06-29 21:16:23
|
<snip> > > My version with the initial values would look like this: > > def firfilt(sig_in, sig_out, coef, clk): > bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) for ii > in range(len(coef))] > coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) for ii in > coef] > mshift = len(sig_in)-1 > @always(clk.posedge) > def hdl_sop(): > sop = 0 > # Note this adds an extra delay! (Group delay N/2+2) > bufferVal[0].next=sig_in > for ii in range(len(coef)-1): > bufferVal[ii+1].next = bufferVal[ii] > sop = sop + (bufferVal[ii] * coefs[ii]) > sig_out.next = (sop >> mshift) > > return hdl_sop > > but there is still the shift error. > > > greetings > Norbo > > I don't think the above would work because the loop doesn't use bufferVal[len(coef)-1) and coef[len(coef)-1]. I think if you ran the testbench it would fail? If the testbench does pass, I think my test conditions are not tight enough then, disregarding the last tap and coefficient should have some effect. I believe you either need the conditional or two loops. Given the original context, I used the conditional vs. an /if/ or two loops. Regards, Chris |
From: Christopher F. <chr...@gm...> - 2012-06-29 20:52:39
|
On 6/29/12 12:43 PM, Norbo wrote: > Am 26.06.2012, 13:51 Uhr, schrieb Christopher Felton > <chr...@gm...>: > >> On 6/22/2012 9:57 AM, Jan Decaluwe wrote: >>> The author presents the following example: >>> >>> -- >>> from myhdl import * >>> >>> def firfilt (sigin, sigout, coefs, clk): >>> buffer = Signal(intbv(0)[len(sigin)*len(coefs)]) >>> inlen = len(sigin) >>> saved_coefs = coefs >>> colen = len(saved_coefs) >>> >>> @always(clk.posedge) >>> def logic(): >>> buffer.next[inlen:] = sigin >>> buffer.next[:inlen] = buffer[inlen * (colen-1):] >>> tmp = 0 >>> for index in range(colen): >>> mult = saved_coefs[inlen*(index+1):inlen*index] * \ >>> buffer[inlen*(index +1): inlen*index] >>> tmp = tmp + sigin >>> sigout.next = tmp >>> >>> return logic >> >> The author did a poor job picking their examples. I say >> this because I don't think their VHDL example is correct, >> either. They don't provide enough information but for the >> VHDL example to be correct the instantiator would need to >> take care of the output word size to handle the bit growth >> as a result of the multiplies and additions (or limit the >> input range). I think if they would have verified the VHDL >> they would have found the VHDL implementation did not meet >> their requirements (or any requirements for a FIR filter). >> >> Also, I don't think the author provides the description of >> the RAM/ROM for the coefficients in the VHDL example. The >> VHDL example is not a fair comparison because it would need >> additional description, somewhere, to define the coefficient >> array. Where as the MyHDL version the coefficient array >> description is embedded! >> >> Here is my version of the FIR filter in MyHDL that matches >> the simplified templated: >> >> from myhdl import * >> def firfilt(sig_in, sig_out, coef, clk): >> buffer = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) \ >> for ii in range(len(coef))] >> coef = tuple(coef) >> mshift = len(sig_in)-1 >> @always(clk.posedge) >> def hdl_sop(): >> sop = 0 >> # Note this adds an extra delay! (Group delay N/2+2) >> for ii in range(len(coef)): >> buffer[ii].next = sig_in if ii == 0 else buffer[ii-1] >> c = coef[ii] >> sop = sop + (buffer[ii] * c) >> sig_out.next = (sop >> mshift) >> >> return hdl_sop >> > > i just tried to run the converted vhdl through quartus and it came up with > the following error: > > Error (10500): VHDL syntax error at firfilt.vhd(39) near text "when"; > expecting ";" > > hm.. maybe its not supported in a clocked process but i am not so sure i > have to look at that closer. > the next error after i changed to a normal if i got: > > Error (10405): VHDL error at firfilt.vhd(78): can't determine type of > object at or near identifier "shift_right" -- found 0 possible types > > > > > Note: I changed buffer to bufferVal because it is a reserved keyword in > vhdl > > > > My version with the initial values would look like this: > > def firfilt(sig_in, sig_out, coef, clk): > bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) for ii > in range(len(coef))] > coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) for ii in > coef] > mshift = len(sig_in)-1 > @always(clk.posedge) > def hdl_sop(): > sop = 0 > # Note this adds an extra delay! (Group delay N/2+2) > bufferVal[0].next=sig_in > for ii in range(len(coef)-1): > bufferVal[ii+1].next = bufferVal[ii] > sop = sop + (bufferVal[ii] * coefs[ii]) > sig_out.next = (sop >> mshift) > > return hdl_sop > > but there is still the shift error. > > > greetings > Norbo > > > I didn't follow the reason for adding the LoS with initial values? Why did you add the coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) \ for ii in coef] ? Yes, in GHDL I get the following error for the converted VHDL. ghdl -c pck_myhdl_08dev.vhd firfilt.vhd firfilt.vhd:46:36: ';' is expected instead of 'when' I am running the latest 0.8dev and didn't check with 0.7. I am not sure what the the error is, when I have a little more time I can investigate (or maybe someone else has some insight). I did add cosimulation with Verilog to the testbench and the cosimulation runs fine (passes tests). The updated code is available in the same location, bitbucket repo. I renamed the "buffer" as well. I also added a reset so I didn't need a special case for checking the output. The circuit would run ok without a reset it just would take N cycles (N being the number of taps) before a valid output is available. Regards, Chris |
From: Christopher F. <chr...@gm...> - 2012-06-29 21:45:29
|
<snip> > Yes, in GHDL I get the following error for the converted VHDL. > > ghdl -c pck_myhdl_08dev.vhd firfilt.vhd > firfilt.vhd:46:36: ';' is expected instead of 'when' > > I am running the latest 0.8dev and didn't check with 0.7. The issue has to do with the python conditionals, if I remove the python conditional then it doesn't error in this spot with GHDL or quartus (I realize Norbo said this in his original response). I do *not* get any errors with GHDL but I do get the shift_right error with quartus and ise. quartus error: can't determine type of object at or near identifier "shift_right" -- found 0 possible types ise error: shift_right can not have such operands in this context IN mode Formal size of to_signed wiht no default value must be associated with an actual value The verilog version synthezied, PaR'd, and bit'd fine. Regards, Chris |
From: Norbo <Nor...@gm...> - 2012-06-30 19:11:29
|
Am 29.06.2012, 23:16 Uhr, schrieb Christopher Felton <chr...@gm...>: > <snip> >> >> My version with the initial values would look like this: >> >> def firfilt(sig_in, sig_out, coef, clk): >> bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) >> for ii >> in range(len(coef))] >> coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) for >> ii in >> coef] >> mshift = len(sig_in)-1 >> @always(clk.posedge) >> def hdl_sop(): >> sop = 0 >> # Note this adds an extra delay! (Group delay N/2+2) >> bufferVal[0].next=sig_in >> for ii in range(len(coef)-1): >> bufferVal[ii+1].next = bufferVal[ii] >> sop = sop + (bufferVal[ii] * coefs[ii]) >> sig_out.next = (sop >> mshift) >> >> return hdl_sop >> >> but there is still the shift error. >> >> >> greetings >> Norbo >> >> > > I don't think the above would work because the loop doesn't use > bufferVal[len(coef)-1) and coef[len(coef)-1]. thanks, of course it should look like this: def firfilt(sig_in, sig_out, coef, clk): bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) for ii in range(len(coef))] coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) for ii in coef] mshift = len(sig_in)-1 @always(clk.posedge) def hdl_sop(): sop = (bufferVal[0] * coefs[0]) # Note this adds an extra delay! (Group delay N/2+2) bufferVal[0].next=sig_in for ii in range(len(coef)-1): bufferVal[ii+1].next = bufferVal[ii] sop = sop + (bufferVal[ii+1] * coefs[ii+1]) sig_out.next = (sop >> mshift) return hdl_sop greetings Norbo |
From: Christopher F. <chr...@gm...> - 2012-07-01 01:48:15
|
On 6/30/12 2:11 PM, Norbo wrote: > def firfilt(sig_in, sig_out, coef, clk): > bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) > for ii in range(len(coef))] > coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) for > ii in coef] > mshift = len(sig_in)-1 > @always(clk.posedge) > def hdl_sop(): > sop = (bufferVal[0] * coefs[0]) > # Note this adds an extra delay! (Group delay N/2+2) > bufferVal[0].next=sig_in > > for ii in range(len(coef)-1): > bufferVal[ii+1].next = bufferVal[ii] > sop = sop + (bufferVal[ii+1] * coefs[ii+1]) > sig_out.next = (sop >> mshift) > > return hdl_sop It should be noted, that the above doesn't work with any current version of code. I think you (Norbo) might have some local changes to create the initial values for a RAM and they probably will be added with the initial value changes but there are a bunch of tools that need to be tested/verified. The above will not work with ROM extraction but appears to work with RAM extraction, but RAM extraction requires initial values (only applicable for FPGAs and not currently implemented) or some method to program the RAM with the initial values. Regards, Chris |
From: Norbo <Nor...@gm...> - 2012-07-03 10:27:09
|
Am 01.07.2012, 03:47 Uhr, schrieb Christopher Felton <chr...@gm...>: > On 6/30/12 2:11 PM, Norbo wrote: >> def firfilt(sig_in, sig_out, coef, clk): >> bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) >> for ii in range(len(coef))] >> coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) >> for >> ii in coef] >> mshift = len(sig_in)-1 >> @always(clk.posedge) >> def hdl_sop(): >> sop = (bufferVal[0] * coefs[0]) >> # Note this adds an extra delay! (Group delay N/2+2) >> bufferVal[0].next=sig_in >> >> for ii in range(len(coef)-1): >> bufferVal[ii+1].next = bufferVal[ii] >> sop = sop + (bufferVal[ii+1] * coefs[ii+1]) >> sig_out.next = (sop >> mshift) >> >> return hdl_sop > > > It should be noted, that the above doesn't work with any current version > of code. I think you (Norbo) might have some local changes to create > the initial values for a RAM and they probably will be added with the > initial value changes but there are a bunch of tools that need to be > tested/verified. > > The above will not work with ROM extraction but appears to work with RAM > extraction, but RAM extraction requires initial values (only applicable > for FPGAs and not currently implemented) or some method to program the > RAM with the initial values. Using a singal (probably declared as constant) which has initialvalues is to my knowledge the number one way to describe some indexable constants in VHDL. I dont think the switch case construct which maps the values is in any way preferable to that other than for the Xilinx tool ROM inference. It is a very basic way to describe some constant values in VHDL. If a tool doesn't support this i personaly would not use it. If there is no ROM or RAM for the device for which the synthesis is done the tool should at least could implement your constant signals with some Vcc or Ground connections wheater it is for an ASIC or an FPGA. Realy if the tool can't do this, its game over. Thats for the VHDL side. The way i have done it in myhdl with the code above is not the preferably way, because a extra signals is missused to implement it altought the list of tuple is allready here as a port input. Mapping a integer list of tuples to the switch case construct is not preferable too i think, because then you need the extra line to map the coef's. c = coef[ii] sop = sop + (buffer[ii] * c) this also creates the variable "c" and as we have seen with the right_shift, convertion, implementation an usage of varibles in a description can easily become a pain. Why risk it when the list of tuple can "easly" be implemented in vhdl or verilog with a signal array with initial values. greetings Norbo |
From: Christopher F. <chr...@gm...> - 2012-07-04 20:06:00
|
On 7/3/12 5:26 AM, Norbo wrote: > Am 01.07.2012, 03:47 Uhr, schrieb Christopher Felton > <chr...@gm...>: > >> On 6/30/12 2:11 PM, Norbo wrote: >>> def firfilt(sig_in, sig_out, coef, clk): >>> bufferVal = [Signal(intbv(0, min=sig_in.min, max=sig_in.max)) >>> for ii in range(len(coef))] >>> coefs = [Signal(intbv(ii, min=min(coef), max=max(coef)+1)) >>> for >>> ii in coef] >>> mshift = len(sig_in)-1 >>> @always(clk.posedge) >>> def hdl_sop(): >>> sop = (bufferVal[0] * coefs[0]) >>> # Note this adds an extra delay! (Group delay N/2+2) >>> bufferVal[0].next=sig_in >>> >>> for ii in range(len(coef)-1): >>> bufferVal[ii+1].next = bufferVal[ii] >>> sop = sop + (bufferVal[ii+1] * coefs[ii+1]) >>> sig_out.next = (sop >> mshift) >>> >>> return hdl_sop >> >> >> It should be noted, that the above doesn't work with any current version >> of code. I think you (Norbo) might have some local changes to create >> the initial values for a RAM and they probably will be added with the >> initial value changes but there are a bunch of tools that need to be >> tested/verified. >> >> The above will not work with ROM extraction but appears to work with RAM >> extraction, but RAM extraction requires initial values (only applicable >> for FPGAs and not currently implemented) or some method to program the >> RAM with the initial values. > > Using a singal (probably declared as constant) which has initialvalues is > to my knowledge the number > one way to describe some indexable constants in VHDL. I dont think the > switch case construct which maps the values is > in any way preferable to that other than for the Xilinx tool ROM inference. The statement wasn't a /for/ or /against/ it simply was pointing out the limitations so that others would not be surprised if they tried the initial value approach with the latest release or latest development. > > It is a very basic way to describe some constant values in VHDL. If a tool > doesn't support this i personaly would not use > it. If there is no ROM or RAM for the device for which the synthesis is > done the tool should at least could implement your constant signals with > some Vcc or Ground connections wheater it is for an ASIC or an FPGA. Realy > if the tool can't do this, its game over. > > Thats for the VHDL side. > > > The way i have done it in myhdl with the code above is not the preferably > way, because a extra signals is missused to implement it altought the list > of tuple is allready here as a port input. Mapping a integer list of > tuples to the switch case construct is not preferable too i think, because > then you need the extra line to map the coef's. > c = coef[ii] > sop = sop + (buffer[ii] * c) > > this also creates the variable "c" and as we have seen with the > right_shift, convertion, implementation an usage of varibles > in a description can easily become a pain. > Why risk it when the list of tuple can "easly" be implemented in vhdl or > verilog with a signal array with initial values. > > > greetings > Norbo For the most part I agree, I like the initial value method and not introducing the separate variable. I am not sure if *all* tools support this method for Verilog and VHDL, though. In addition I don't know if this approach is general enough. These are the problems I see or questions I have: 1. ASIC tools don't have an equivalent RAM/ROM mapping. But you might do the logic implementation. In that case, if you had a tuple of ints or LoS of ints and wanted them implemented in logic, I don't know if the initial value (IV) method would synthesize. ASIC tools will have an external tool (ROM builder) that is used for ROMs but, as stated, if you wanted it in logic I don't know if the IV would work. 2. Does there need to be a method to disable? What if a synthesis tool does not support the IV method. Is it expected that all tools would support IV. 3. What if you want to use logic and not memory? (kinda the same question as the disable). For small lists (tuples) of ints you might not want (or can't) to use a BRAM block. I think it comes down to tool support. For the tuple of ints and/or list of signal with initial value (converts to switch/case and initial values assignments respectively) which tools support which method. The switch/case will be supported by all tools (even if not optimal) but I don't know if the IV is supported by all tools? You have a valid point, the current tuple of its will only convert to a ROM for the Xilinx synthesis tools and not the Altera tools. But it will work for both tools even if not optimal for Altera. Regards, Chris > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > |
From: Christopher F. <chr...@gm...> - 2012-08-01 03:48:57
|
<snip> >> >> The above will not work with ROM extraction but appears to work with RAM >> extraction, but RAM extraction requires initial values (only applicable >> for FPGAs and not currently implemented) or some method to program the >> RAM with the initial values. > > Using a singal (probably declared as constant) which has initialvalues is > to my knowledge the number > one way to describe some indexable constants in VHDL. I dont think the > switch case construct which maps the values is > in any way preferable to that other than for the Xilinx tool ROM inference. > > It is a very basic way to describe some constant values in VHDL. If a tool > doesn't support this i personaly would not use > it. If there is no ROM or RAM for the device for which the synthesis is > done the tool should at least could implement your constant signals with > some Vcc or Ground connections wheater it is for an ASIC or an FPGA. Realy > if the tool can't do this, its game over. <snip> We have had a couple threads on this and I created a wiki page [1] to keep track of the /initial value support/ progress, comments, and opinions. The ROM/RAM is closely related (pre-init ram). I think the biggest hurdle is resolving the options for automatic memory synthesis, mainly for FPGAs, that may not map to other synthesis technologies. Currently, the /case/ statements for ROM will work in any technology but will only be an optimized memory structure in the Xilinx tools. The Altera tools will not extract a ROM. It has been requested that initial values for list of signals be created. The FPGA tools (at least Altera) creates a configuration file to pre-init the BRAMs. We had discussed adding function attributes for conversion configuration. We discussed adding an attribute to disable initial value creation. toVerilog.disable_init toVHDL.disable_init I believe, but I didn't list it in the wiki, we also discussed adding an attribute to enable list of signals initial values. toVerilog.enable_list_init toVHDL.enable_list_init If this makes sense, I believe we have the options covered. The tuple of ints will be converted as is, and a list of signals can be configured to create the array (list of signals) initial values using the VHDL function and Verilog initial block as previously discussed. Regards, Chris [1] http://www.myhdl.org/doku.php/dev:initial_values |
From: Christopher F. <chr...@gm...> - 2012-06-26 12:25:19
|
On 6/22/2012 9:57 AM, Jan Decaluwe wrote: > I came across a paper that compares HDLs: > > http://referaat.cs.utwente.nl/TSConIT/download.php?id=1144 I am not very familiar with /Functional Languages/. I have studied the Kansas Lava in the past, briefly. /Functional Languages/ for HDLs seem to have the same track record as they have had with general programming languages; they appear to be an elegant solution but when the rubber meets the road they are difficult to use. Regards, Chris |