FPGARelated.com
Forums

Re: rs232 uart: testbench vs real world, and the missing first letter.

Started by Jonathan Bromley February 6, 2009
On Fri, 6 Feb 2009 12:56:38 -0800 (PST), jleslie48 wrote:

>whoa!!!! hold on there! now things are getting interesting!
Yup. You've given me an excuse to waste a lot of time playing around with my little Spartan-3 kit :-)
>thanks for the correct syntax: >op_MESSAGE & tua("Hello"&CR&LF) & EOM &
There's no reason in principle why the generic should not be a string; but, as I pointed out, there are some <cough> features of ISE that mean it is safer to use an array of 8-bit integers instead. So I wrote the tua() conversion function to cast a string to an array of 8-bit ints. CR and LF are character, not integer constants, so they must form part of the STRING (=array of character) that is converted by tua().
>you've got a whole mess of computing power built into the >entity now,
Not anywhere near enough, yet. I do feel, though, that I got a lot more bang per line of code than you did :-)
>and while I'd love to offset this into a picoblaze >C programming environment, I won't have that at my disposal
Whyever not? What's the objection to having a soft core inside the FPGA to do the slow procedural/sequential stuff? No-one is forcing you into TELLING your client it's there... and the great joy of an FPGA is that you can also add as much custom high-speed hardware as you need, alongside the CPU that you need to do the messy-but-slow stuff.
> your state machine built out of VHDL is starting > to look mighty pretty to me.
It was deliberately set up as a tutorial teaser - I hope you don't find that patronizing, it certainly wasn't intended to be so. Unfortunately it does not scale particularly well; each time I add new functionality to it, its performance degrades measurably. The first version (just DELAY and MESSAGE operations) gave me up to 120MHz clock speed in my Spartan-3. Adding the GOTO and WAIT_FOR_CHAR operations degraded the maximum possible speed to about 105MHz. Not a problem so far, but clearly some real design effort will be needed if you want to add any more serious capabilities.
>first off, I just took a quick dander at the new code, >and its set for the 50Mhz clock yes?
yup, sorry, I sent you the wrong version. Well spotted!
>In my 100Mhz world the line: > IF ( BAUD_COUNT = 26 ) THEN >in the P4 process: > >P4: PROCESS ( SYSTEM_CLOCK ) >BEGIN > IF ( SYSTEM_CLOCK = '1' AND SYSTEM_CLOCK'EVENT ) THEN > IF ( BAUD_COUNT = 26 ) THEN > BAUD_COUNT <= 0; > UART_EN_16_X_BAUD <= '1'; > ELSE
[...]
>should be 54 yes?
Yes. (53, I think, because the count is zero-based.) Note I used an INTEGER signal for the count. You may need to tweak its declaration to make its range wide enough. Better still, declare some constants: constant clock_freq_Hz : positive := 100_000_000; constant desired_baud_rate: positive := 115_200; -- let VHDL do the work of computing the divisor! constant baud_rate_divisor: positive := clock_freq_Hz / (desired_baud_rate * 16); and then make the declaration and the code match automatically: signal baud_count: natural range 0 to baud_rate_divisor-1; ... if baud_count = baud_rate_divisor-1 then baud_count <= 0; UART_EN_16_X_BAUD <= '1'; else baud_count <= baud_count + 1; ...
>and this: >TRANSMIT_UART : entity work.uart_tx > port map
[...]
> clk => SYSTEM_CLOCK >isn't the clk here supposed to be: >the 1/6th clock?
No. That was absolutely intentional. I wanted the whole thing clocked from my single system clock. I didn't see the point in your /6 clock, and I still don't. Set the Baud-rate divisor to 53 (so you get 100MHz/54) and let that do the work.
>I think I'm missing something on understanding how these clocks work.
Possibly. If you want something to operate once every N system clocks, it is usually better NOT to use a divided-by-N clock directly, but rather to use a divider similar to your baud rate prescaler and then to write a process like this... if rising_edge(system_clock) then if (enable_once_per_N_system_clocks = '1') then do whatever you want; end if; end if; Your hardware-oriented co-worker will probably be able to help explain why this is so. Please trust me on this.
>"PLEASE DO NOT think about "firing" or "calling" an entity. > An entity instance just sits there, doing its thing, for > the entire life of the universe. It "fires" on every > clock edge, whether you like it or not. " > >Ok, I'm missing something or maybe I'm just not useing the >right words. >In your ver 1.0, the entity data_gen in JB_Loki_Top >generated 1 and only one message output message: > >A >abcdefghijkinsertherelmnopqrstuvwxyz12345678pqr
Because its "program" caused it to do so, and then had a HALT operation that put it into a stuck state so that it made no further progress. It still continues to operate on every clock edge - it's just that it is in an internal state that happens to make no progress; a jump-to-self loop, in software terms.
>now it finished with an op_halt, so I'm guessing that >in the details of data gen I'm going to see that HALT >render data_gen silent, until reboot time, or I imagine >if I give that >reset => '0' a real signal to set the output message to >resend.
Exactly so.
>Again I think I'm mucking up the language of describing what >is the chain of events, but the fact is data_gen put ~something >out once and only once, and I'm quite sure their is a way I can have >that ~something come out again bases on a change of ~some signal.
See the new version. It works. Try it (with the baud divisor appropriately patched to 53 for your higher clock rate).
>I know your going to hate this, but I like that second element of the >generic map >of data_gen being "the_program". It has established some linear >events that are a lot more familiar to me.
That was (more or less) intentional. Think about it for a moment: Your hardware is an invariant lump of silicon. It must, inevitably, do exactly the same thing on each and every clock cycle. But by keeping some state information, and by adjusting the logic's outputs and its future state as a function of that state, we can make the design progress through a series of states and therefore APPEAR to have sequential behaviour. What I gave you was an impossibly primitive programmable machine; "the_program" is precisely its program, and you can even find, explicitly in the design, a PROGRAM COUNTER that steps its way through that program. It is not a huge leap of imagination from there to a proper general-purpose programmable CPU. -- 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@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.
On Feb 6, 5:35=A0pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Fri, 6 Feb 2009 12:56:38 -0800 (PST), jleslie48 wrote: > >whoa!!!! =A0hold on there! =A0now things are getting interesting! > > Yup. =A0You've given me an excuse to waste a lot of time > playing around with my little Spartan-3 kit :-) > > >thanks for the correct syntax: > >op_MESSAGE & tua("Hello"&CR&LF) & EOM & > > There's no reason in principle why the generic > should not be a string; but, as I pointed out, there > are some <cough> features of ISE that mean it is > safer to use an array of 8-bit integers instead. > So I wrote the tua() conversion function to cast > a string to an array of 8-bit ints. =A0CR and LF > are character, not integer constants, so they must > form part of the STRING (=3Darray of character) that > is converted by tua(). > > >you've got a whole mess of computing power built into the > >entity now, > > Not anywhere near enough, yet. =A0I do feel, though, that > I got a lot more bang per line of code than you did :-) > > >and while I'd love to offset this into a picoblaze > >C programming environment, I won't have that at my disposal > > Whyever not? =A0What's the objection to having a soft core > inside the FPGA to do the slow procedural/sequential stuff? > No-one is forcing you into TELLING your client it's there... > and the great joy of an FPGA is that you can also add as > much custom high-speed hardware as you need, alongside > the CPU that you need to do the messy-but-slow stuff. > > > your state machine built out of VHDL is starting > > to look mighty pretty to me. > > It was deliberately set up as a tutorial teaser - I hope > you don't find that patronizing, it certainly wasn't > intended to be so. =A0Unfortunately it does not scale > particularly well; each time I add new functionality > to it, its performance degrades measurably. =A0The first > version (just DELAY and MESSAGE operations) gave me > up to 120MHz clock speed in my Spartan-3. =A0Adding the > GOTO and WAIT_FOR_CHAR operations degraded the maximum > possible speed to about 105MHz. =A0Not a problem so far, > but clearly some real design effort will be needed if > you want to add any more serious capabilities. > > >first off, I just took a quick dander at the new code, > >and its set for the 50Mhz clock yes? > > yup, sorry, I sent you the wrong version. =A0Well spotted! > > > > >In my 100Mhz world the line: > > =A0 =A0 =A0 =A0 =A0IF ( BAUD_COUNT =3D 26 ) THEN > >in the P4 process: > > >P4: =A0PROCESS ( SYSTEM_CLOCK ) > >BEGIN > > =A0 =A0 IF ( SYSTEM_CLOCK =3D '1' AND SYSTEM_CLOCK'EVENT ) THEN > > =A0 =A0 =A0 =A0 =A0IF ( BAUD_COUNT =3D 26 ) THEN > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 BAUD_COUNT <=3D 0; > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 UART_EN_16_X_BAUD =A0 =A0 =A0 =A0<=3D '1'; > > =A0 =A0 =A0 =A0 =A0ELSE > [...] > >should be 54 yes? > > Yes. (53, I think, because the count is zero-based.) > Note I used an INTEGER signal for the count. =A0You may need to > tweak its declaration to make its range wide enough. > Better still, declare some constants: > > =A0 constant clock_freq_Hz : positive :=3D 100_000_000; > =A0 constant desired_baud_rate: positive :=3D 115_200; > =A0 -- let VHDL do the work of computing the divisor! > =A0 constant baud_rate_divisor: positive :=3D =A0 > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0clock_freq_Hz / (desired_baud_rate * 16); > > and then make the declaration and the code match automatically: > > =A0 signal baud_count: natural range 0 to baud_rate_divisor-1; > =A0 ... > =A0 if baud_count =3D baud_rate_divisor-1 then > =A0 =A0 baud_count <=3D 0; > =A0 =A0 UART_EN_16_X_BAUD <=3D '1'; > =A0 else > =A0 =A0 baud_count <=3D baud_count + 1; > =A0 ... > > > > >and this: > >TRANSMIT_UART : entity work.uart_tx > > =A0port map > [...] > > =A0 =A0 =A0 clk =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D> =A0 SYSTEM_CLO=
CK
> >isn't the clk here supposed to be: > >the 1/6th clock? > > No. =A0That was absolutely intentional. =A0I wanted the whole > thing clocked from my single system clock. =A0I didn't see > the point in your /6 clock, and I still don't. =A0Set the > Baud-rate divisor to 53 (so you get 100MHz/54) and let > that do the work. > > >I think I'm missing something on understanding how these clocks work. > > Possibly. =A0If you want something to operate once every N system > clocks, it is usually better NOT to use a divided-by-N clock > directly, but rather to use a divider similar to your baud > rate prescaler and then to write a process like this... > > =A0 if rising_edge(system_clock) then > =A0 =A0 if (enable_once_per_N_system_clocks =3D '1') then > =A0 =A0 =A0 =A0do whatever you want; > =A0 =A0 end if; > =A0 end if; > > Your hardware-oriented co-worker will probably be able to > help explain why this is so. =A0Please trust me on this. > > >"PLEASE DO NOT think about "firing" or "calling" an entity. > > An entity instance just sits there, doing its thing, for > > the entire life of the universe. =A0It "fires" on every > > clock edge, whether you like it or not. =A0" > > >Ok, I'm missing something or maybe I'm just not useing the > >right words. > >In your ver 1.0, the entity data_gen in JB_Loki_Top > >generated 1 and only one message output message: > > >A > >abcdefghijkinsertherelmnopqrstuvwxyz12345678pqr > > Because its "program" caused it to do so, and then > had a HALT operation that put it into a stuck state > so that it made no further progress. =A0It still continues > to operate on every clock edge - it's just that it is > in an internal state that happens to make no progress; > a jump-to-self loop, in software terms. > > >now it finished with an op_halt, so I'm guessing that > >in the details of data gen I'm going to see that HALT > >render data_gen silent, until reboot time, or I imagine > >if I give that > >reset =3D> '0' a real signal to set the output message to > >resend. > > Exactly so. > > >Again I think I'm mucking up the language of describing what > >is the chain of events, but the fact is data_gen put ~something > >out once and only once, and I'm quite sure their is a way I can have > >that ~something come out again bases on a change of ~some signal. > > See the new version. =A0It works. =A0Try it (with the baud divisor > appropriately patched to 53 for your higher clock rate). > > >I know your going to hate this, but I like that second element of the > >generic map > >of data_gen being "the_program". =A0It has established some linear > >events that are a lot more familiar to me. > > That was (more or less) intentional. =A0Think about it for a moment: > Your hardware is an invariant lump of silicon. =A0It must, inevitably, > do exactly the same thing on each and every clock cycle. =A0But by > keeping some state information, and by adjusting the logic's > outputs and its future state as a function of that state, we > can make the design progress through a series of states and > therefore APPEAR to have sequential behaviour. =A0What I gave > you was an impossibly primitive programmable machine; > "the_program" is precisely its program, and you can even find, > explicitly in the design, a PROGRAM COUNTER that steps its way > through that program. =A0It is not a huge leap of imagination > from there to a proper general-purpose programmable CPU. > -- > 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.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com > > The contents of this message may contain personal views which > are not the views of Doulos Ltd., unless specifically stated.
"Whyever not? What's the objection to having a soft core inside the FPGA to do the slow procedural/sequential stuff? No-one is forcing you into TELLING your client it's there... and the great joy of an FPGA is that you can also add as much custom high-speed hardware as you need, alongside the CPU that you need to do the messy-but-slow stuff. " You might be right, but until I get a better feel for what I can do in the VHDL world alone, I am in no position to make that imposition on my customer, and what I haven't mentioned yet, a third party co-developer. This system is meant to be an add-on application to an already existing system made by a competitor. Our competitor has already fielded equipment and my project is to get my application to run on their Virtex II FPGA with as little modification as possible to the legacy system. And as you may guess, these folks did it all without a picoblaze soft core. Now these folks are a company of 100's, and have been developing FPGA for 8+ years, and have proven deliverables and production facilities capable of 10 of 1000's of units. I'm not in much of position to tell them they need to put a softcore picoblaze processor on their board. Remember, your talking to the most knowledgeable person in the field of fpga in my company and you know how little I know. Now is not the time for me to be pushing these kind of design issues. I need to fully explore the capabilities of the fpga so if I do insist on a picoblaze soft core, (whatever that is) I have to be able to answer why I am dismissing the already existing paradigm. I'm not prepared to do that right now, and I will be chopped to pieces (rightfully so,) in about 10 seconds when the customer calls for a design review with all three of us present. As you might of guessed, this project is not about printing Cindy Crawfords measurements. When I built my prototype on a DSP, I was told by dozens of folks I had to do it with a FFT. I didn't even know what an FFT was at the time, and had to spend 4 months just to get something of an FFT to work, and then another month convincing myself that the FFT was not appropriate for the job. Only then did I approach my community to put forth my idea of a non FFT solution. By then though, I had the knowledge to point out why the FFT failed and why my solution solved that issue. I will have to do that with this situation as well. Anyway, its the weekend, and I'm gonna put this stuff down for a day or two, but I'm very excited about analyzing and moviing forward with this version. The rest of you message I'll be addressing on Monday. Sincerely, Jonathan Leslie
On Feb 7, 11:28 am, jleslie48 <j...@jonathanleslie.com> wrote:
> > The rest of you message I'll be addressing on Monday. > > Sincerely, > > Jonathan Leslie
Ok, I'm having a ball with this version. I'm messing with it, and its messages scheme, and now I'm trying to build an actual reset button onto the data_gen process. All the baud rate stuff worked perfectly, and after I have the reset switch going, I think the next step is to update the goto functionality to be a goto LABEL instead of a PC location. So I think a good project is to add the 'OP_LABEL [char]' mnemonic and re-tool the goto to walk through the ROM?? looking for the label. - Jon