FPGARelated.com
Forums

UART RS232 "hello world" program trial and terror.

Started by jleslie48 January 28, 2009
rickman <gnuarm@gmail.com> wrote:
(snip, I wrote)

>> There are some people interested in porting old computer >> designs, such as the Apple II, to FPGA. In that case, it >> might make sense to include the original tristate lines.
(snip)
> This is a good example of what I was thinking of. If I were porting > such a design, although "port" is not really the correct term because > there is no existing HDL code, I would not describe tri-state buffers > in my code.
Well, some people still use schematic capture for new designs. In this case, the old design is a schematic on paper.
> I would describe a selection function which was a top > level OR with each of the "tri-state" buffers being replaced by an AND > gate.
Say, for example, the Apple II with add-in cards. One could have the main board as a verilog module, and add-in cards (serial, disk, video) as separate modules that are included and then loaded into the synthesis tools.
> If there were timing issues that required the bus to "remember" > the last driven state, I would add a latch with the enable driven by > an OR of all of the individual enables. I don't see how you could > expect a synthesis tool to do anything other than to replace the tri- > state drivers with the OR-AND multiplexer and I don't see any reason > to even try to duplicate a design at that level.
There might have been discussion on the need to keep old data on the Apple II bus. Otherwise, one should be happy if the tools convert tristate to AND/OR logic. That would complicate the verilog code for a system bus, though. For anything within a module, I agree at least 99%. -- glen
On Jan 30, 5:20=A0pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Fri, 30 Jan 2009 13:39:41 -0800 (PST), jleslie48 wrote: > >Ok, boys, things are finishing up on a high note this week. > > Good to hear. > > A few suggestions for your consideration.... > > >P16: =A0PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, TX_BUFFER_FULL, > >TX_WRITE_BUFFER_STB, > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 lprj_MESS_TRAN, =A0 =A0project_name=
_cnt,
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 lprj_PERSON_TRAN, =A0person_mess_cn=
t,
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 lprj_RECEIVE_TRAN, RECEIVE_MAX, =A0=
=A0 =A0RECEIVE_MESS
> >( 0 TO lprj_RECEIVE_MAX ) =A0) > > AAAARGH. =A0A clocked process should be sensitized ONLY > to its clock (and its asynchronous reset, if it has one). > It does nothing unless there's an active edge on the > clock, so there is no point in having the process wake > up because of changes on other signals; that's just a waste > of simulation effort and an unnecessary obfuscation. > > > > >BEGIN > > =A0 =A0 IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN > > =A0 =A0 =A0 =A0 =A0IF ( UART_RESET_BUFFER =A0 =3D '0' ) THEN > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 IF =A0 =A0( ( lprj_MESS_TRAN =A0 =A0 =A0=3D=
'1' ) AND
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ( TX_BUFFER_FULL =A0 =A0 =
=A0=3D '0' ) AND
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ( TX_WRITE_BUFFER_STB =3D '=
0' ) =A0) THEN
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 --TX_DATA_I=
N( 7 DOWNTO 0 ) <=3D PROJECT_NAME
> >( lprj_MESS_CNT ); > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TX_DATA_IN =
<=3D to_slv(project_name_stg
> >( project_name_cnt )); > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 ELSIF ( ( lprj_PERSON_TRAN =A0 =A0=3D '1' )=
AND
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ( TX_BUFFER_FULL =A0 =A0 =
=A0=3D '0' ) AND
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ( TX_WRITE_BUFFER_STB =3D '=
0' ) =A0) THEN
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TX_DATA_IN =
<=3D to_slv(person_mess_stg
> >( person_mess_cnt )); > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 ELSIF ( ( lprj_RECEIVE_TRAN =A0 =3D '1' ) A=
ND
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ( TX_BUFFER_FULL =A0 =A0 =
=A0=3D '0' ) AND
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ( TX_WRITE_BUFFER_STB =3D '=
0' ) =A0) THEN
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TX_DATA_IN(=
7 DOWNTO 0 ) <=3D RECEIVE_MESS( RECEIVE_MAX );
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 END IF; > > =A0 =A0 =A0 =A0 =A0END IF; > > =A0 =A0 END IF; > >END PROCESS P16; > > As a software guy you must surely see the value in factoring-out > the common conditional expression > > =A0 TX_BUFFER_FULL=3D'0' AND TX_WRITE_BUFFER_STB=3D'0' > > but that's the least of my worries. =A0This code appears to be > some kind of data-stream generator that happens - just happens - > to be sending its data to a UART, rather than a memory or an > Ethernet interface or an LCD display or whatever. =A0It seems > grotesque that its control flow is so intimately tangled with > the internal details of the UART; such an approach is stacking > up many, many problems for the future as your design grows. > > Furthermore, it looks pretty strange to me that the code that > indexes/counts its way through the strings is so completely > disconnected from the code that picks up characters in > those strings; that's a good recipe for getting off-by-one > timing errors (as you've discovered). =A0Think about those > old software mantras about "coherence and coupling": > coherent (i.e. closely related) activities should go > together in a common piece of code such as a process; > coupling of one piece of activity to another is bad > and should be avoided - keep your functional blocks > as decoupled as possible. > > PLEASE give some consideration to establishing a clear, > simple, UNIFORM interface between your blocks. > > As I've pointed out before, the easiest way to do that is > often (not always, but often) to have a ready/valid handshake. > The data consumer asserts "ready" on any clock cycle in > which it can have data written to it. =A0The producer > asserts "valid" on any clock cycle where its data > output is useful. =A0On clock cycles where "ready" and > "valid" are BOTH true, both parties agree that an item > of data is transferred. =A0At this point: > 1.the producer must EITHER > =A0 (a) update its output to be the next data item in > =A0 =A0 =A0 sequence, leaving "valid" true; OR > =A0 (b) drop its "valid" signal to false so that the > =A0 =A0 =A0 consumer does not try to take data on the next clock. > 2.the consumer must EITHER > =A0 (a) drop its "ready" signal to false so that "valid" on > =A0 =A0 =A0 the next clock would not transfer any data, OR > =A0 (b) hold "ready" true, and be prepared to accept new > =A0 =A0 =A0 data on the next clock. > > In this way you can almost completely decouple the > producer and consumer, with only the data and this simple > two-wire clocked handshake between them. =A0Producers and > consumers can then be mixed-and-matched in a very simple way. > > It should be pretty easy to re-jig your UART control signals > to conform to this arrangement. =A0And it will be VERY easy > to rework your data producer to do likewise. > > Enjoy your weekend :-) > -- > 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.
all very good points. I didn't write this, my "fpga guy" did. all I know is that it did actually work, and I've only gotten so far as be sure it does actually work, and that for every message, he adds a new boolean semaphore; definitely not a very scalable solution. I'm sure that is how the redundant boolean checks creeped in. My first cleanup was to at least reduce the strings to something that I could actually read. The side effect being that the first character of the string got clobbered and that answer will reside in the spagetti code that you pointed out. Meantime its not immediately obvious to me from the testbench: http://jleslie48.com/fpga_uartjl_01/11jlmod/ccuart01/screencap/screencap10_= missingfirstletter.png I see the "T" getting in, to the datastream, but I haven't found where it got clobbered. I do know the code is a complete mess. The source code is here if anyone is interested: http://jleslie48.com/fpga_uartjl_01/11jlmod/ccuart01/source/LOKI_Top.vhd http://jleslie48.com/fpga_uartjl_01/11jlmod/ccuart01/source/