|
Prev: Probelms simulating Xilinx FFT version 3.2 core in ModelSim SE
Next: Xilinx ISE synthesis error (error:3524 Unexpected end of line.)
From: Michael Meeuwisse on 11 Apr 2008 05:44 Hi, I'm working on a little UART to get more familiar with verilog, and right now I have the following input: parameter width = 32; /* Must be multiple of 8 */ input [width - 1: 0] iData; /* number of characters to send for each piece of data - 1 */ parameter chars = width / 8 - 1; The iData first goes in a fifo for buffering and is then read back in as oData: wire [width - 1: 0] oData; Since this is an UART I want to send (always, regardless of width) 8 bits at a time, so I wrote down: reg [7: 0] xData [chars: 0]; And then try to assign oData to this: xData <= oData; I hope a few are now crying "You can't do that!" because that would mean you'd know how to do this instead. Xilinx webpack gives me on that line; Illegal left hand side of nonblocking assignment The error is general enough for google to not find anything relevant afaik. I don't want to do something like: {xData[0], xData[1], ..} = oData; Because I don't know how wide oData will be at this point. I also really don't want to rewrite the fifo to support an other output width than what it's input is. Even if I had to rewrite it, I'll end up with the same problem as above at some point. Hints & Tips are very welcome. Thanks, Michael www.projectvga.org
From: Jonathan Bromley on 11 Apr 2008 05:11 On Fri, 11 Apr 2008 10:44:12 +0100, Michael Meeuwisse <mickeymeeuw(a)g_something> wrote: >parameter width = 32; /* Must be multiple of 8 */ >input [width - 1: 0] iData; > >/* number of characters to send for each piece of data - 1 */ >parameter chars = width / 8 - 1; > >The iData first goes in a fifo for buffering and is then read back in as >oData: > >wire [width - 1: 0] oData; > >Since this is an UART I want to send (always, regardless of width) 8 >bits at a time, so I wrote down: > >reg [7: 0] xData [chars: 0]; > >And then try to assign oData to this: > >xData <= oData; Yup, you can't do that! xData is a "memory" in Verilog-speak, an array of (chars+1) distinct 8-bit variables; you can't assign a single vector to that, any more than you could assign an integer to a complete array in C. The direct (but, in practice, wrong) answer is: integer i; ... for (i=0; i<=chars; i=i+1) xData[i] <= oData[8*i +: 8]; The strange [a +: b] is an "indexed part select", choosing the 8 bits of oData whose lowest-numbered subscript is 8*i. You might expect to do... xData[i] <= oData[8*i + 7: 8*i]; but you're not allowed to do that, because a part-select can't have variable bounds. However, there is probably a better way. Copy "oData" into a wide register: reg [width-1 : 0] byteShifter; ... byteShifter <= oData; and then allow it to shift down 8 bits at a time as you pull bytes out of it: reg [7:0] txByte; ... // send one byte txByte <= byteShifter[7:0]; byteShifter <= byteShifter >> 8; The shift operation obviously puts the *next* 8 bits of "byteShifter" into the right place for the next txByte<=byteShifter[7:0] copy. Armed with this idea you'll probably come up with something a bit simpler. For example, you may prefer to do this byte-shifting at the input end of your FIFO, so that the FIFO is invariably byte-wide - that would be my preference. Generally, if you want sequential access to the pieces of a big vector, it is much cheaper (in hardware) to shift them into place rather than selecting them from their original position. -- Jonathan Bromley, Consultant DOULOS - Developing Design Know-how VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK jonathan.bromley(a)MYCOMPANY.com http://www.MYCOMPANY.com The contents of this message may contain personal views which are not the views of Doulos Ltd., unless specifically stated.
From: Michael Meeuwisse on 11 Apr 2008 06:43 Jonathan Bromley wrote: > Yup, you can't do that! xData is a "memory" in Verilog-speak, > an array of (chars+1) distinct 8-bit variables; you can't > assign a single vector to that, any more than you could assign > an integer to a complete array in C. I figured it was something like that. But since it'd translate to hardware at some point I hoped the compiler was intelligent enough to understand this "re-definition". > The direct (but, in practice, wrong) answer is: > > integer i; > ... > for (i=0; i<=chars; i=i+1) > xData[i] <= oData[8*i +: 8]; > > The strange [a +: b] is an "indexed part select", > choosing the 8 bits of oData whose lowest-numbered > subscript is 8*i. You might expect to do... > > xData[i] <= oData[8*i + 7: 8*i]; > Ok.. but why is this a wrong answer? > However, there is probably a better way. > ... > // send one byte > txByte <= byteShifter[7:0]; > byteShifter <= byteShifter >> 8; > That all makes sense. I think I can pull this off without changing too much. I was already doing something similar for transmitting the actual bits anyway. :) > Armed with this idea you'll probably come up with > something a bit simpler. For example, you may > prefer to do this byte-shifting at the input end > of your FIFO, so that the FIFO is invariably > byte-wide - that would be my preference. > It would simplify the UART somewhat, but then I'd have to shift a number of bytes into the fifo in one clock cycle. I'll stick to what I have for now. > Generally, if you want sequential access to the > pieces of a big vector, it is much cheaper (in hardware) > to shift them into place rather than selecting them > from their original position. Odd. I thought a wire from the original register would be cheaper than logic to get the bits in place. Thanks, Michael www.projectvga.org
From: Jonathan Bromley on 11 Apr 2008 05:49 On Fri, 11 Apr 2008 11:43:06 +0100, Michael Meeuwisse wrote: >> The direct (but, in practice, wrong) answer is: >> >> integer i; >> ... >> for (i=0; i<=chars; i=i+1) >> xData[i] <= oData[8*i +: 8]; >> >> The strange [a +: b] is an "indexed part select", >> choosing the 8 bits of oData whose lowest-numbered >> subscript is 8*i. You might expect to do... >> >> xData[i] <= oData[8*i + 7: 8*i]; >Ok.. but why is this a wrong answer? uh, which answer? oData[8*i+7:8*i] is illegal because it's a part select with variable bounds; in Verilog all expressions must have a statically-determined bit width, and although you and I can do the algebra and see that the slice is evidently 8 bits wide, it's safer for the language to outlaw that sort of thing. The indexed part-select oData[8*i+:8] is legal, at least in Verilog-2001, but creates a big multiplexer to choose the bits - hence my comment later about using a shifter instead. >> Generally, if you want sequential access to the >> pieces of a big vector, it is much cheaper (in hardware) >> to shift them into place rather than selecting them >> from their original position. > >Odd. I thought a wire from the original register would be cheaper than >logic to get the bits in place. Don't take my word for it - try synthesising both versions and see what the tool shows you. For a word of only 2 or 4 bytes the difference is likely to be marginal. -- Jonathan Bromley, Consultant DOULOS - Developing Design Know-how VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK jonathan.bromley(a)MYCOMPANY.com http://www.MYCOMPANY.com The contents of this message may contain personal views which are not the views of Doulos Ltd., unless specifically stated.
From: Michael Meeuwisse on 11 Apr 2008 07:35
Jonathan Bromley wrote: > On Fri, 11 Apr 2008 11:43:06 +0100, Michael Meeuwisse wrote: >>Ok.. but why is this a wrong answer? > > uh, which answer? I meant the for loop. If the compiler unrolls it I don't see how this could be a wrong. Maybe size. >>Odd. I thought a wire from the original register would be cheaper than >>logic to get the bits in place. > > > Don't take my word for it - try synthesising both versions and > see what the tool shows you. For a word of only 2 or 4 bytes > the difference is likely to be marginal. I'll give it a try soon. The solution of using a shift turned out to be 1 extra line and about 4 minor changes, so I'm currently working out the bugs which showed up in the simulation. :) Thanks again, Michael www.projectvga.org |