Thread: [myhdl-list] toVerilog and memories
Brought to you by:
jandecaluwe
From: Tom D. <td...@di...> - 2005-07-03 06:55:50
|
I am trying to model generate Verilog for some simple memories. For example: def ram(dout,din,addr,we,clk=None,depth=4) : memL = [Signal(intbv(0,min=0,max=2**8)) for i in range(depth)] while 1: yield posedge(clk) if we: memL[addr] = din.val dout.next = memL[addr] I want addr to be a Signal as well. I get an error that it needs to be an int. If I use the value of addr, then it simulates fine but I get a list comprehension error when running it through toVerilog. Is there a way to do this and get it through toVerilog? Thanks, Tom |
From: David B. <dav...@fr...> - 2005-07-05 19:21:41
|
Tom, In order to fix the error message on addr, replace memL[addr] with memL[int(addr.val)]. Unfortunately the current version of the Verilog translator doesn't suppo= rt signal list (array) translation. Jan, do you plan to support it in the next release(s)? Regards, David. Selon Tom Dillon <td...@di...>: > I am trying to model generate Verilog for some simple memories. For exa= mple: > > def ram(dout,din,addr,we,clk=3DNone,depth=3D4) : > memL =3D [Signal(intbv(0,min=3D0,max=3D2**8)) for i in range(depth)] > > while 1: > yield posedge(clk) > if we: > memL[addr] =3D din.val > dout.next =3D memL[addr] > > I want addr to be a Signal as well. I get an error that it needs to be > an int. > > If I use the value of addr, then it simulates fine but I get a list > comprehension error when running it through toVerilog. > > Is there a way to do this and get it through toVerilog? > > Thanks, Tom > > > > ------------------------------------------------------- > SF.Net email is sponsored by: Discover Easy Linux Migration Strategies > from IBM. Find simple to follow Roadmaps, straightforward articles, > informative Webcasts and more! Get everything you need to get up to > speed, fast. http://ads.osdn.com/?ad_id=3D7477&alloc_id=3D16492&op=3Dcl= ick > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > |
From: Tom D. <td...@di...> - 2005-07-05 19:59:15
|
David, Thanks, I had that part figured out and that made it work in myhdl simulation. I was looking into the _toVerilog code to see how difficult it would be to add support but haven't spent enough time on it yet. I have never used python code generation so it is all a little new to me but very interesting. Thanks, Tom David Brochart wrote: >Tom, > >In order to fix the error message on addr, replace memL[addr] with >memL[int(addr.val)]. >Unfortunately the current version of the Verilog translator doesn't support >signal list (array) translation. >Jan, do you plan to support it in the next release(s)? > >Regards, > >David. > > > >Selon Tom Dillon <td...@di...>: > > > >>I am trying to model generate Verilog for some simple memories. For example: >> >>def ram(dout,din,addr,we,clk=None,depth=4) : >> memL = [Signal(intbv(0,min=0,max=2**8)) for i in range(depth)] >> >> while 1: >> yield posedge(clk) >> if we: >> memL[addr] = din.val >> dout.next = memL[addr] >> >>I want addr to be a Signal as well. I get an error that it needs to be >>an int. >> >>If I use the value of addr, then it simulates fine but I get a list >>comprehension error when running it through toVerilog. >> >>Is there a way to do this and get it through toVerilog? >> >>Thanks, Tom >> >> >> >>------------------------------------------------------- >>SF.Net email is sponsored by: Discover Easy Linux Migration Strategies >>from IBM. Find simple to follow Roadmaps, straightforward articles, >>informative Webcasts and more! Get everything you need to get up to >>speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click >>_______________________________________________ >>myhdl-list mailing list >>myh...@li... >>https://lists.sourceforge.net/lists/listinfo/myhdl-list >> >> >> > > > > >------------------------------------------------------- >SF.Net email is sponsored by: Discover Easy Linux Migration Strategies >from IBM. Find simple to follow Roadmaps, straightforward articles, >informative Webcasts and more! Get everything you need to get up to >speed, fast. http://ads.osdn.com/?ad_idt77&alloc_id492&op=click >_______________________________________________ >myhdl-list mailing list >myh...@li... >https://lists.sourceforge.net/lists/listinfo/myhdl-list > > > |
From: Jan D. <ja...@ja...> - 2005-07-06 13:40:38
|
David Brochart wrote: > Tom, > > In order to fix the error message on addr, replace memL[addr] with > memL[int(addr.val)]. > Unfortunately the current version of the Verilog translator doesn't support > signal list (array) translation. > Jan, do you plan to support it in the next release(s)? I understand the need and I think it´s possible to support a limited form of list comprehensions. There are a number of (Verilog-related) issues though that have to be resolved, so we need to think carefully first and come up with a good spec. I will give the start by replying in detail to Tom´s original mail - stay tuned. Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Jan D. <ja...@ja...> - 2005-07-07 22:04:31
|
Tom Dillon wrote: > I am trying to model generate Verilog for some simple memories. For > example: > > def ram(dout,din,addr,we,clk=None,depth=4) : > memL = [Signal(intbv(0,min=0,max=2**8)) for i in range(depth)] > while 1: > yield posedge(clk) > if we: > memL[addr] = din.val > dout.next = memL[addr] > > I want addr to be a Signal as well. I get an error that it needs to be > an int. Use int(addr) to convert it to an int. (Signals support this function.) > If I use the value of addr, then it simulates fine but I get a list > comprehension error when running it through toVerilog. > > Is there a way to do this and get it through toVerilog? Not with the current version. What would be needed is support to map a list comprehension to a verilog memory. I haven´t tackled this yet, partly because verilog memories have all kinds of limitations that obfuscate what can and what should be supported. Newer Verilogs (2001 and SystemVerilog) seem to do away with limitations, but (as always with Verilog) things aren´t very clear. We will need expertise to move forward carefully. As to your model, I see the value, and how it could be done. Basically, we would need to support a list comprehension internally in a generator, and map it to a local Verilog memory. I´ll discuss the details to try to come up with an implementation spec. First, why a list of Signals? In MyHDL philosophy (as in VHDL) you would use plain variables internally. In your model, you actually use it like that, otherwise the assignment would read memL[int(addr)].next = din In Verilog 1995, you can only have a memory out of regs, so the natural base type for the supported list comprehension would be an intbv (and not an int for example). Therefore, only the following kind of list comprehension would be supported: memL = [intbv(0)[8:] for i in range(depth)] Secondly, toVerilog has to able to infer and use type and bit width information, or at least be sure that the simulation will take care of it. Because of this, an intbv has always to be assigned by modifying its contents, not by overriding it: a = intbv(0)[8:] a = 500 // not supported by toVerilog a[:] = 500 // supported (note that simulation will flag an error) Similarly, the memory assignment would have to look as follows: memL[int(addr)][:] = din // OK for toVerilog while the following would not work: memL[int(addr)] = din // not OK for toVerilog Currently, toVerilog always uses an explicit bit width in the Verilog output. For example: a = intbv(0)[8:] a[4:] = c a[:] = d is mapped to: reg [7:0] a; a[3:0] = c; a[7:0] = d; However, Verilog 1995 doesn´t permit bit or slice access to memory elements. The workaround would be to introduce a special case for the special [:] slice. For example: a[:] = c memL[int(addr)][:] = din would then be mapped to: a = c; memL[addr] = din; Now, what to do with true slices and indexing in the MyHDL code? Even though Verilog 1995 doesn´t support it on memories, newer Verilogs (2001 and SystemVerilog) do (I think). So, I would just do the conversion in the obvious way and leave it to the user to change his MyHDL code if his Verilog doesn´t support it. I don´t want to introduce Verilog conversion modes - it´s a street without and end (and probably circular in fact :-)). Ok - so much for my initial feedback. Other feedback, thoughts, experiments, welcome. Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-07-07 23:17:20
|
Jan, Thanks for the response. > As to your model, I see the value, and how it could be done. Basically, > we would need to support a list comprehension internally in a generator= , > and map it to a local Verilog memory. I=B4ll discuss the details to > try to come up with an implementation spec. To use MyHDL effectively for making logic, I would like to be able to=20 synthesize the Verilog generated, that is my real end goal. So I would=20 really add the requirement that the subset of Verilog used was=20 synthesizable by a decent FPGA synthesis tool. Alternatively, and really needed as well, is a way to include a black=20 box into the simulation(Verilog)/synthesis flow. So you would use a=20 MyHDL function for behavioral MyHDL simulation, then substitute in a=20 block box when either doing co-simulation or synthesis. Possible an=20 attribute on the function or something to trigger this. If the black box was an easier solution for the memory, it seems like=20 that may be OK for now. I have not looked into that yet. Generic synthesizable memories are very easy in Verilog and that=20 actually would not be a bad solution. Also, I would use Verilog 2001 if it helps in any way. Our synthesis and=20 simulation tools all support it. > > First, why a list of Signals? In MyHDL philosophy (as in VHDL) you > would use plain variables internally. In your model, you actually > use it like that, otherwise the assignment would read > > memL[int(addr)].next =3D din I'm still a little new to MyHDL and was thinking anything going=20 toVerilog needed to be a signal or int. My mistake. > > In Verilog 1995, you can only have a memory out of regs, so the natural > base type for the supported list comprehension would be an intbv > (and not an int for example). Therefore, only the following kind of lis= t > comprehension would be supported: > > memL =3D [intbv(0)[8:] for i in range(depth)] I would be happy with only being able to build a memory with that style. > > Secondly, toVerilog has to able to infer and use type and > bit width information, or at least be sure that the simulation will tak= e > care of it. Because of this, an intbv has always to be > assigned by modifying its contents, not by overriding it: > > a =3D intbv(0)[8:] > a =3D 500 // not supported by toVerilog > a[:] =3D 500 // supported (note that simulation will flag an error) > > Similarly, the memory assignment would have to look as follows: > > memL[int(addr)][:] =3D din // OK for toVerilog > > while the following would not work: > > memL[int(addr)] =3D din // not OK for toVerilog Would it be possible to flag that as a warning? I am still really just experimenting with MyHDL but am trying to take=20 some our real logic there to give it a test drive. It is working well,=20 but there isn't much we build that doesn't have memories inside the FPGA. Any ideas on how hard it is to implement a black box type connection?=20 That would keep me on my experimentation path and give me a way to solve=20 anything later too. You just need module name, signal connections, and=20 parameters. While it would be nice to be able to toVerilog lists, I think there will=20 be other structures that need to be coded properly on the Verilog side=20 to end up being inferred properly by synthesis. Anyhow, I'm willing to help make changes or test or do whatever I can.=20 Let me know. Tom |
From: Jan D. <ja...@ja...> - 2005-07-08 22:25:36
|
Tom Dillon wrote: > To use MyHDL effectively for making logic, I would like to be able to > synthesize the Verilog generated, that is my real end goal. So I would > really add the requirement that the subset of Verilog used was > synthesizable by a decent FPGA synthesis tool. I agree completely, it should even be a superset. (In some areas, it already is in fact.) Are verilog memories actually synthesized by your synthesis tool (and which is it)? I don´t know of an ASIC tool that has this, though I see how this could work for FPGAs. That would be very useful of course, and a strong argument to support it. > Alternatively, and really needed as well, is a way to include a black > box into the simulation(Verilog)/synthesis flow. So you would use a > MyHDL function for behavioral MyHDL simulation, then substitute in a > block box when either doing co-simulation or synthesis. Possible an > attribute on the function or something to trigger this. I agree that this is needed also. I had been thinking about it, but I haven´t tackled the details. > I am still really just experimenting with MyHDL but am trying to take > some our real logic there to give it a test drive. It is working well, > but there isn't much we build that doesn't have memories inside the FPGA. > > Any ideas on how hard it is to implement a black box type connection? > That would keep me on my experimentation path and give me a way to solve > anything later too. You just need module name, signal connections, and > parameters. > > Anyhow, I'm willing to help make changes or test or do whatever I can. > Let me know. Here is my proposed plan: I will work on an implementation of list comprehensions mapped to Verilog memories, along the lines described om my previous mail. I´ll post an alpha release to the newsgroup for you and others to test it before committing it to the next release. Give me a few days (can´t start before Tuesday) - if it takes longer I´ll post about the progress. I´ll think about the black box feature. It would really be useful though to start a discussion here about the details of such a feature (in a new thread). Getting a well thought-out, detailed spec is a large part of the solution! To get started, some issues to consider: - what should the user interface be exactly (as simple as possible) - how to handle parameters Regards, Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-07-09 18:21:49
|
Jan, > Are verilog memories actually synthesized by your synthesis tool (and > which is it)? I don=B4t know of an ASIC tool that has this, though I > see how this could work for FPGAs. That would be very useful of > course, and a strong argument to support it. Yes, we use Mentor Precision and it works very well. It will infer all=20 kinds of memory structures and map to the appropriate FPGA memory. It=20 keeps the source more or less generic and makes the synthesis tool do=20 the work. > > Here is my proposed plan: > > I will work on an implementation of list comprehensions mapped to > Verilog memories, along the lines described om my previous mail. I=B4ll > post an alpha release to the newsgroup for you and others to test it > before committing it to the next release. > > Give me a few days (can=B4t start before Tuesday) - if it takes longer > I=B4ll post about the progress. Sounds great. Let me know if you need any help. Tom |
From: Tom D. <td...@di...> - 2005-07-09 19:02:35
|
OK, here is my start to a black box implementation discussion. > > I=B4ll think about the black box feature. It would really be useful > though to start a discussion here about the details of such a feature > (in a new thread). Getting a well thought-out, detailed spec is a large > part of the solution! To get started, some issues to consider: > - what should the user interface be exactly (as simple as possible) > - how to handle parameters > > For the interface I would propose something like this: portD =3D {'xPort':xSig,'aPort':aSig,'bPort':bSig} parmD =3D {'parm1':num1,'parm2':num2} blackBox('modName','instName',portD,partD) modName is the module name you are connecting to, instName the instance=20 name, both just strings. Then just the port dictionary, connects MyHDL=20 signals (xSig,aSig,bSig) to the port names. Same with the parameter=20 dictionary. num1 and num2 are both python numbers, but could be=20 anything, just needs to be turned into a string. blackBox() is a MyHDL function. The MyHDL source that contains this=20 would need to knwo toVerilog was running and substitute the blackBox()=20 for the behavior model used during MyHDL simulation. What we need on the Verilog side is: modName #( .parm1(num1), .parm2(num2) ) instName ( .xPort(xSig), .aPort(aSig), .bPort(bSig) ) I think that would do it, but I probably have not thought this all the=20 way through. Tom |
From: Jan D. <ja...@ja...> - 2005-11-10 15:41:17
|
Tom Dillon wrote: > OK, here is my start to a black box implementation discussion. I was looking for something more general. See: http://myhdl.jandecaluwe.com/doku.php/meps:mep-101 Jan -- Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Electronic design with Python: http://myhdl.jandecaluwe.com |
From: Jan D. <ja...@ja...> - 2005-07-20 13:01:40
Attachments:
_toVerilog.tar.gz
|
Jan Decaluwe wrote: > Here is my proposed plan: > > I will work on an implementation of list comprehensions mapped to > Verilog memories, along the lines described om my previous mail. I´ll > post an alpha release to the newsgroup for you and others to test it > before committing it to the next release. Attached you find a patch to MyHDL to support Verilog memories. A list comprehension with intbv elements in a generator is converted to a Verilog memory. To install the patch, replace the myhdl/_toVerilog directory in a 0.4.1 installation by the attached directory. There are several constraints, but I'm not providing an example in order to ensure that the error handling is tested also :-) Regards, Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-07-26 22:41:53
|
Jan, That works great, I use it with the following code: memL =3D [intbv(0,min=3Ddout._min,max=3Ddout._max) for i in range(depth= )] =20 while 1: yield posedge(clk) if we: memL[int(addr)][:] =3D din # print "ram: wrote %d to %d"%(din,addr) dout.next =3D memL[int(addr)] This synthesized into Virtex blockRAM using Mentor Precision just fine. Now, I should have thought of this earlier, but I am working=20 sequentially here. ROMs are also needed and easy to infer in synthesis. It would be very=20 good if the following would produce a case statement in Verilog: def rom(dout,addr,clk=3DNone,dataL=3DNone) : """ rom : rom module Inputs: addr : input address clk : clock for synchronous roms, =3D=3D None for async Outputs: dout : output port, width determines width of rom Params: dataL : list of values for rom, length is depth of rom """ memL =3D [intbv(data,min=3Ddout._min,max=3Ddout._max) for data in dataL= ] =20 while 1: yield posedge(clk) dout.next =3D memL[int(addr)] You would need to be able to figure out that the values in memL never=20 get modified after it is defined. The important thing here, is the memL define and the dout.next=20 assignment need to get mapped to a case statement: always @(posedge clk) case(addr) : 0 : dout <=3D dataL[0] ; 1 : dout <=3D dataL[1] ; . . . This also works in XST. Now you may also want some control around this, or possibly asynchronous=20 so only the list needs to become the case statement, that case statement=20 may end up inside come control statements. Possibly a clock enable. This is very helpful. There are also dual port ROMs, so you would need=20 two case statements on the same list, with a separate address into the li= st. You can also initialize the values of a RAM. This is more obscure and=20 I've never actually used it. But it too can be inferred from HDL. I will=20 forward the coding style when I find it. I could not find it today. Anyhow, thanks for the help thus far on the memories and let me know=20 what you think of the rom idea. Tom =20 Jan Decaluwe wrote: > Jan Decaluwe wrote: > >> Here is my proposed plan: >> >> I will work on an implementation of list comprehensions mapped to >> Verilog memories, along the lines described om my previous mail. I=B4l= l >> post an alpha release to the newsgroup for you and others to test it >> before committing it to the next release. > > > Attached you find a patch to MyHDL to support Verilog memories. > > A list comprehension with intbv elements in a generator is > converted to a Verilog memory. > > To install the patch, replace the myhdl/_toVerilog directory > in a 0.4.1 installation by the attached directory. > > There are several constraints, but I'm not providing an example > in order to ensure that the error handling is tested also :-) > > Regards, > > Jan > |
From: Jan D. <ja...@ja...> - 2005-08-01 15:41:11
|
Tom Dillon wrote: > Jan, > > That works great, I use it with the following code: > > memL = [intbv(0,min=dout._min,max=dout._max) for i in range(depth)] > while 1: > yield posedge(clk) > if we: > memL[int(addr)][:] = din > # print "ram: wrote %d to %d"%(din,addr) > dout.next = memL[int(addr)] > > This synthesized into Virtex blockRAM using Mentor Precision just fine. Ok. The code was committed to the next release. -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-08-01 19:13:43
|
Jan, How difficult to add the capability to handle the following? memL = [intbv(0,min=dout._min,max=dout._max) for i in range(depth)] def wrLogic() : while 1: yield posedge(clk) if we: memL[int(wr_addr)][:] = din def rdLogic() : while 1: yield posedge(clk) dout.next = memL[int(rd_addr)] WL = wrLogic() RL = rdLogic() return WL,RL This would allow true dual port capability like most FPGAs now have. I overlooked this in my initial posting. Also may want a rd_clk and wr_clk. You would need to pull the reg definition out of the process and give a unique name to it. If I do this now, it generates everything correct but leaves out the reg define. Tom Jan Decaluwe wrote: > Tom Dillon wrote: > >> Jan, >> >> That works great, I use it with the following code: >> >> memL = [intbv(0,min=dout._min,max=dout._max) for i in range(depth)] >> while 1: >> yield posedge(clk) >> if we: >> memL[int(addr)][:] = din >> # print "ram: wrote %d to %d"%(din,addr) >> dout.next = memL[int(addr)] >> >> This synthesized into Virtex blockRAM using Mentor Precision just fine. > > > Ok. The code was committed to the next release. > |
From: Jan D. <ja...@ja...> - 2005-08-02 20:30:30
|
(I think something went wrong with gmane yesterday, and the following message from Tom Dillon didn=B4t show up in gmane. So I repost it -- Jan Decaluwe) Tom Dillon wrote: > Jan, >=20 > How difficult to add the capability to handle the following? >=20 > memL =3D [intbv(0,min=3Ddout._min,max=3Ddout._max) for i in range(dept= h)] > def wrLogic() : > while 1: > yield posedge(clk) > if we: > memL[int(wr_addr)][:] =3D din >=20 > def rdLogic() : > while 1: > yield posedge(clk) > dout.next =3D memL[int(rd_addr)] >=20 > WL =3D wrLogic() > RL =3D rdLogic() > return WL,RL >=20 > This would allow true dual port capability like most FPGAs now have. >=20 > I overlooked this in my initial posting. Also may want a rd_clk and wr_= clk. >=20 > You would need to pull the reg definition out of the process and give a= =20 > unique name to it. >=20 > If I do this now, it generates everything correct but leaves out the re= g=20 > define. >=20 > Tom >=20 >=20 > Jan Decaluwe wrote: >=20 >> Tom Dillon wrote: >> >>> Jan, >>> >>> That works great, I use it with the following code: >>> >>> memL =3D [intbv(0,min=3Ddout._min,max=3Ddout._max) for i in range(de= pth)] >>> while 1: >>> yield posedge(clk) >>> if we: >>> memL[int(addr)][:] =3D din >>> # print "ram: wrote %d to %d"%(din,addr) >>> dout.next =3D memL[int(addr)] >>> >>> This synthesized into Virtex blockRAM using Mentor Precision just fin= e. >> >> >> >> Ok. The code was committed to the next release. >> >=20 >=20 > ------------------------------------------------------- > SF.Net email is sponsored by: Discover Easy Linux Migration Strategies > from IBM. Find simple to follow Roadmaps, straightforward articles, > informative Webcasts and more! Get everything you need to get up to > speed, fast. http://ads.osdn.com/?ad_id=3D7477&alloc_id=3D16492&op=3Dcl= ick > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list >=20 --=20 Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Jan D. <ja...@ja...> - 2005-08-04 19:33:35
|
Tom Dillon wrote: > Jan, > > How difficult to add the capability to handle the following? See below for some qualifications to your proposal first and if you agree. I would like to come up with a general solution for RAM support, also including a way to convert to assign statements for simple combinatorial blocks, as discussed in other posts. I'm working on this currently and I think it should be possible to release something early next week. > memL = [intbv(0,min=dout._min,max=dout._max) for i in range(depth)] Note that .min and .max are supported attributes of intbv's and Signals - no need to use the private attributes. (This should never be required - if there seems a need for it, let me know.) > def wrLogic() : > while 1: > yield posedge(clk) > if we: > memL[int(wr_addr)][:] = din > > def rdLogic() : > while 1: > yield posedge(clk) > dout.next = memL[int(rd_addr)] > > WL = wrLogic() > RL = rdLogic() > return WL,RL > > This would allow true dual port capability like most FPGAs now have. > > I overlooked this in my initial posting. Also may want a rd_clk and wr_clk. That is no problem - clocks will be as defined in the sourcecode. > You would need to pull the reg definition out of the process and give a > unique name to it. Exactly - like for signals. The logic of MyHDL (similar to VHDL) is to use a list of Signals in this case: signals are used for communication between generators, variables internally. So the code would look like: memL = [Signal(intbv(...)) for i in range(depth)] def wrLogic() : while 1: yield posedge(clk) if we: memL[int(wr_addr)].next = din def rdLogic() : while 1: yield posedge(clk) dout.next = memL[int(rd_addr)] > If I do this now, it generates everything correct but leaves out the reg > define. That qualifies as a bug - it should give an error. (The principle is: if the MyHDL simulation works and the conversion succeeds, the converted code should be correct.) I noticed that this was bug was present for non-list types also and I have already added code to my development version that flags this situation as a conversion error. Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-08-04 19:56:55
|
Jan, >> memL = [intbv(0,min=dout._min,max=dout._max) for i in range(depth)] > > > Note that .min and .max are supported attributes of intbv's and > Signals - no need to use the private attributes. (This should never > be required - if there seems a need for it, let me know.) Thanks. > > memL = [Signal(intbv(...)) for i in range(depth)] > > def wrLogic() : > while 1: > yield posedge(clk) > if we: > memL[int(wr_addr)].next = din > > def rdLogic() : > while 1: > yield posedge(clk) > dout.next = memL[int(rd_addr)] In this example I could use rd_clk and wr_clk instead of clk twice? That looks very good, and I now better understand intbv vs. Signal. So by definition, an intbv is a variable and Signal is a signal. I started out thinking I could only use Signals if going through toVerilog. Tom |
From: Jan D. <ja...@ja...> - 2005-08-05 08:57:20
|
Tom Dillon wrote: > >> >> memL = [Signal(intbv(...)) for i in range(depth)] >> >> def wrLogic() : >> while 1: >> yield posedge(clk) >> if we: >> memL[int(wr_addr)].next = din >> >> def rdLogic() : >> while 1: >> yield posedge(clk) >> dout.next = memL[int(rd_addr)] > > > > In this example I could use rd_clk and wr_clk instead of clk twice? Definitely. > That looks very good, and I now better understand intbv vs. Signal. So > by definition, an intbv is a variable and Signal is a signal. Yes, but be careful to put them against each other like that. intbv is just one of the variable types that toVerilog can handle, others are int, bool, and enum. Likewise, toVerilog can handle Signals constructed from a number of base types. See also the manual 6.4.3: Supported types. It may also be a good idea to take a fresh look at the examples in 6.6. Especially enum usage in 6.6.4 should be of interest to FPGA designers. > I started > out thinking I could only use Signals if going through toVerilog. Certainly not. What happens is that variables and Signals should be used as in VHDL, and that variable assignment is mapped to blocking assignment, and signal assignment to non-blocking assignment. Regards, Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Jan D. <ja...@ja...> - 2005-08-19 10:47:44
|
Tom Dillon wrote: > ROMs are also needed and easy to infer in synthesis. It would be very > good if the following would produce a case statement in Verilog: > > def rom(dout,addr,clk=None,dataL=None) : > """ > rom : rom module > > Inputs: > addr : input address > clk : clock for synchronous roms, == None for async > Outputs: > dout : output port, width determines width of rom > Params: > dataL : list of values for rom, length is depth of rom > """ > > memL = [intbv(data,min=dout._min,max=dout._max) for data in dataL] > while 1: > yield posedge(clk) > dout.next = memL[int(addr)] > > > You would need to be able to figure out that the values in memL never > get modified after it is defined. > > The important thing here, is the memL define and the dout.next > assignment need to get mapped to a case statement: > > always @(posedge clk) > case(addr) : > 0 : dout <= dataL[0] ; > 1 : dout <= dataL[1] ; > . > . I like this. It is a feature where conversion can have an additional productivity advantage, as as lists/tuples of constants are easier to create and maintain in Python than in Verilog. Now for the details: It's not necessary to use an additional memL object - the code could just simply refer to the defining list dataL instead. That list would not be present in Verilog - all constants would be directly present in the code. I assume that's Ok for the synthesis tools? There's no need for these constants to be intbv's - plain int's are just fine and easier. To make sure that a list of constants cannot be modified outside the scope of toVerilog, I propose to use a tuple instead. Note that a tuple cannot be modified after creation, which maps nicely to the concept of a Rom. No doubt this may cause some initial confusion with users who use lists for everything, but I think it's worthwhile to document and explain this. Note that a tuple can easily be created from a list: t = tuple(AnyList) So in short: a tuple of ints used in an assignment in the way you described, would be expanded into an equivalent case statement. About the case statement: should it have synthesis attributes like parallel_case, full_case? Should there be a default fallback or not? > Now you may also want some control around this, or possibly asynchronous > so only the list needs to become the case statement, that case statement > may end up inside come control statements. Possibly a clock enable. > > This is very helpful. There are also dual port ROMs, so you would need > two case statements on the same list, with a separate address into the > list. All the above will come without additional effort. The high-level assignment will be mapped to a case statement, and all context that surrounds it will be there as usual. I have an initial implementation ready along the lines above and I could generate a new snapshot. If there is feedback, send it quickly because next week I have another assignment. Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-08-19 14:22:49
|
Jan Decaluwe wrote: > > I like this. It is a feature where conversion can have an additional > productivity advantage, as as lists/tuples of constants are easier > to create and maintain in Python than in Verilog. Yes, we now build roms from a python script for just that reason. > > Now for the details: > > It's not necessary to use an additional memL object - the code could > just simply refer to the defining list dataL instead. That list would > not be present in Verilog - all constants would be directly present > in the code. I assume that's Ok for the synthesis tools? This sounds like a great idea. When you say directly present in the code, you mean in the MyHDL source, correct? In Verilog you would need the case statement addressed by the index and outputting the value from the rom on a wire that would connect to where it was needed. > > There's no need for these constants to be intbv's - plain int's > are just fine and easier. I think ints would be OK for the right side of the assignment in Verilog since it can figure out the width from the left. > > So in short: a tuple of ints used in an assignment in the way you > described, would be expanded into an equivalent case statement. > > About the case statement: should it have synthesis attributes like > parallel_case, full_case? Should there be a default fallback or > not? The cases are mutually exclusive since a unique address selects each one. I have have never put attribute on them and they get inferred fine. You should only have enough cases as the length of the tuple, since if your address is bigger synthesis will figure out you don't use them all optimize the rom. This is important since not all roms end up in built in memories, sometimes in combinatorial logic or registers. So I would either use the default for the last one, or leave it out. Leaving it out will probably produce a synthesis warning. > > All the above will come without additional effort. The high-level > assignment will be mapped to a case statement, and all context > that surrounds it will be there as usual. Dual port roms as well? That is great. > > I have an initial implementation ready along the lines above and > I could generate a new snapshot. If there is feedback, send it > quickly because next week I have another assignment. I would love to give it a try. Also if it includes the list of signals fix from the previous posting that would be very useful. Tom |
From: Jan D. <ja...@ja...> - 2005-08-19 14:57:44
|
Tom Dillon wrote: >> >> Now for the details: >> >> It's not necessary to use an additional memL object - the code could >> just simply refer to the defining list dataL instead. That list would >> not be present in Verilog - all constants would be directly present >> in the code. I assume that's Ok for the synthesis tools? > > > This sounds like a great idea. > > When you say directly present in the code, you mean in the MyHDL source, > correct? No, I mean that the tuple will not be mapped to something in Verilog. All constants from the tuple will be directly put at the appropriate place in the Verilog case statement, like so: # in MyHDL: theTuple = (72, 35, 9, 109 ...) // Verilog output .... always @(posedge clk) begin: RL // ROM case (addr) 0: dout <= 72; 1: dout <= 35; 2: dout <= 9; 3: dout <= 194; ... Is that OK? >> About the case statement: should it have synthesis attributes like >> parallel_case, full_case? Should there be a default fallback or >> not? > > > The cases are mutually exclusive since a unique address selects each > one. I have have never put attribute on them and they get inferred fine. > > You should only have enough cases as the length of the tuple, since if > your address is bigger synthesis will figure out you don't use them all > optimize the rom. This is important since not all roms end up in built > in memories, sometimes in combinatorial logic or registers. > > So I would either use the default for the last one, or leave it out. > Leaving it out will probably produce a synthesis warning. Ok, I'll make the last one the default. I'll include the synthesis pragma's for now - I don't see how they can hurt and perhaps other tools need them. > I would love to give it a try. Also if it includes the list of signals fix from the previous posting that would be very useful. Yes, I'll prepare a snapshot with that fix and the ROM support. Jan -- Jan Decaluwe - Resources bvba - http://jandecaluwe.com Losbergenlaan 16, B-3010 Leuven, Belgium Using Python as a hardware description language: http://jandecaluwe.com/Tools/MyHDL/Overview.html |
From: Tom D. <td...@di...> - 2005-08-19 15:21:39
|
Jan Decaluwe wrote: > Tom Dillon wrote: > > > No, I mean that the tuple will not be mapped to something in Verilog. > All constants from the tuple will be directly put at the appropriate > place in the Verilog case statement, like so: > > # in MyHDL: theTuple = (72, 35, 9, 109 ...) > > // Verilog output > .... > always @(posedge clk) begin: RL > // ROM > case (addr) > 0: dout <= 72; > 1: dout <= 35; > 2: dout <= 9; > 3: dout <= 194; > ... > > Is that OK? Yes. > > Ok, I'll make the last one the default. I'll include the synthesis > pragma's for now - I don't see how they can hurt and perhaps other > tools need them. Sounds, good. I will run it through all the tools we have to test it. > >> I would love to give it a try. Also if it includes the list of >> signals fix from the previous posting that would be very useful. > > > Yes, I'll prepare a snapshot with that fix and the ROM support. Great. Tom |
From: <dan...@we...> - 2005-07-27 16:09:12
|
Jan, I tried a simple example with the memory and to implement it with ISE 6.3, but ran into some problems. I am not sure whether I did something wrong how I wrote the MyHDL code or need to do some special ISE settings? I basically pulled in the generated Verilog file into a ISE project with the standard settings and ran it through implementation. Here is the MyHDL code that I used: def ram(clk, dout, din, addr, we, d_width=8, depth=4) : memL = [intbv(0)[d_width:] for i in range(depth)] while 1: yield posedge(clk) if we: memL[int(addr.val)][:] = din.val dout.next = memL[int(addr.val)] and that is the generated Verilog code: module inst_ram ( clk, dout, din, addr, we ); input [0:0] clk; output [7:0] dout; reg [7:0] dout; input [7:0] din; input [1:0] addr; input we; always @(posedge clk) begin: _MYHDL1_BLOCK reg [8-1:0] memL [0:4-1]; if (we) begin memL[addr] = din; end dout <= memL[addr]; end endmodule The first thing ISE tripped over was that the memL array is inside the always statement. Moving it out from there made it go on, but then there is a blocking and nonblocking assignment inside the always statement and that one it did not like either. Is it possible to change that with the toVerilog conversion? I also recognized that the 'clk' signal is specified as input [0:0] whereas the 'we' signal is specified only as input. Regards Guenter Jan Decaluwe wrote: > Jan Decaluwe wrote: > >> Here is my proposed plan: >> >> I will work on an implementation of list comprehensions mapped to >> Verilog memories, along the lines described om my previous mail. I´ll >> post an alpha release to the newsgroup for you and others to test it >> before committing it to the next release. > > > Attached you find a patch to MyHDL to support Verilog memories. > > A list comprehension with intbv elements in a generator is > converted to a Verilog memory. > > To install the patch, replace the myhdl/_toVerilog directory > in a 0.4.1 installation by the attached directory. > > There are several constraints, but I'm not providing an example > in order to ensure that the error handling is tested also :-) > > Regards, > > Jan > |
From: Tom D. <td...@di...> - 2005-07-28 04:11:50
|
>The first thing ISE tripped over was that the memL array is inside the >always statement. Moving it out from there made it go on, but then there >is a blocking and nonblocking assignment inside the always statement and >that one it did not like either. > >Is it possible to change that with the toVerilog conversion? > > > Guenter makes a good point here. We will actually need the array to be defined outside the always block and accessible from multiple always blocks. For a true dual port (dual clock) we need something like the following: reg [7:0] mem [31:0]; always @(posedge write_clock) if (wea) mem[addr_write] <= data_in; always @(posedge read_clock) data_out <= mem[addr_read]; Tom |
From: <dan...@we...> - 2005-07-28 13:21:35
|
Hello, Tom Dillon wrote: ... > > For a true dual port (dual clock) we need something like the following: > > reg [7:0] mem [31:0]; > > always @(posedge write_clock) > if (wea) > mem[addr_write] <= data_in; > > always @(posedge read_clock) > data_out <= mem[addr_read]; > > Tom I tried to implement a dual-port RAM with synchronous read. The Xilinx XST manual provides a Verilog template for that. Basically if the XST finds a Verilog construct in the form of that template, it will implement it as a dual-port RAM. Following is the Verilog code for a dual-port RAM with synchronous read (read through). module raminfr (clk, we, a, dpra, di, spo, dpo); input clk; input we; input [4:0] a; input [4:0] dpra; input [3:0] di; output [3:0] spo; output [3:0] dpo; reg [3:0] ram [31:0]; reg [4:0] read_a; reg [4:0] read_dpra; always @(posedge clk) begin if (we) ram[a] <= di; read_a <= a; read_dpra <= dpra; end assign spo = ram[read_a]; assign dpo = ram[read_dpra]; endmodule Now I tried to implement that in myhdl so that toVerilog would create the respective Verilog. My show stopper was that I did not really know how to implement the assign statement. I searched through the mailing list archive and found a post from March 2nd of this year with the subject "syntax sugar?" from Haitao Zhang. He wrote: > assign a = expr > > In myhdl one has to do > def assign_blk(): > while 1: > yield signals in expr > a.next = expr > > or: > def assign_blk(): > def blk(): > a.next = expr > return always_comb(blk) > > AND one needs to keep track of all the generators: > assign_blk_list.append(assign_blk()) First that looked simple, just implement it as combinatorial logic, but then there is that comment about needing to keep track of the generators that I did not understand. Maybe somebody can give me some explanation about why I need to keep track of the generators? Does it not work as a combinatorial logic implementation by itself? I tried to go on, without considering the assign statement for now and ran into another issue with the two read_* registers. Below is my myhdl code. When doing it as below I have the problem, that toVerilog specifies the registers inside the always statement. I commented about that already yesterday with the memory array. I tried to avoid that by explicit initializing the python variables outside the while loop, which is now commented out. But that only brought me a type mismatch error message, probably because I am passing a signal to the dp_ram_py() function. def dp_ram_py(clk, we, addr, di, spo, dp_addr, dpo): memL = [intbv(0)[d_width:] for i in range(a_width^2)] #read_addr = intbv(0)[a_width:] #read_dp_addr = intbv(0)[a_width:] while 1: yield posedge(clk) if we: memL[int(addr.val)][:] = di.val read_addr = addr read_dp_addr = dp_addr spo.next = memL[int(read_addr.val)] dpo.next = memL[int(read_dp_addr.val)] I would appreciate any help how to solve that. Thanks in advance. Guenter |