Reply by jleslie48 January 30, 20092009-01-30
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/
Reply by glen herrmannsfeldt January 30, 20092009-01-30
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
Reply by Jonathan Bromley January 30, 20092009-01-30
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: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, TX_BUFFER_FULL, >TX_WRITE_BUFFER_STB, > lprj_MESS_TRAN, project_name_cnt, > lprj_PERSON_TRAN, person_mess_cnt, > lprj_RECEIVE_TRAN, RECEIVE_MAX, RECEIVE_MESS >( 0 TO lprj_RECEIVE_MAX ) )
AAAARGH. A 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 > IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN > IF ( UART_RESET_BUFFER = '0' ) THEN > IF ( ( lprj_MESS_TRAN = '1' ) AND > ( TX_BUFFER_FULL = '0' ) AND > ( TX_WRITE_BUFFER_STB = '0' ) ) THEN > --TX_DATA_IN( 7 DOWNTO 0 ) <= PROJECT_NAME >( lprj_MESS_CNT ); > TX_DATA_IN <= to_slv(project_name_stg >( project_name_cnt )); > > ELSIF ( ( lprj_PERSON_TRAN = '1' ) AND > ( TX_BUFFER_FULL = '0' ) AND > ( TX_WRITE_BUFFER_STB = '0' ) ) THEN > TX_DATA_IN <= to_slv(person_mess_stg >( person_mess_cnt )); > > ELSIF ( ( lprj_RECEIVE_TRAN = '1' ) AND > ( TX_BUFFER_FULL = '0' ) AND > ( TX_WRITE_BUFFER_STB = '0' ) ) THEN > TX_DATA_IN( 7 DOWNTO 0 ) <= RECEIVE_MESS( RECEIVE_MAX ); > END IF; > END IF; > END IF; >END PROCESS P16;
As a software guy you must surely see the value in factoring-out the common conditional expression TX_BUFFER_FULL='0' AND TX_WRITE_BUFFER_STB='0' but that's the least of my worries. This 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. It 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). Think 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. The producer asserts "valid" on any clock cycle where its data output is useful. On clock cycles where "ready" and "valid" are BOTH true, both parties agree that an item of data is transferred. At this point: 1.the producer must EITHER (a) update its output to be the next data item in sequence, leaving "valid" true; OR (b) drop its "valid" signal to false so that the consumer does not try to take data on the next clock. 2.the consumer must EITHER (a) drop its "ready" signal to false so that "valid" on the next clock would not transfer any data, OR (b) hold "ready" true, and be prepared to accept new 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. Producers 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. And 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.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.
Reply by jleslie48 January 30, 20092009-01-30
On Jan 29, 11:46 am, jleslie48 <j...@jonathanleslie.com> wrote:
> On Jan 29, 12:35 am, rickman <gnu...@gmail.com> wrote: > > > I have to say that I find your learning process to be very > > interesting. It has been so long for me that I have forgotten exactly > > what it was that I had to learn or unlearn to switch from software to > > HDL. I am getting a feel for that again. > > So glad your enjoying yourself :)))))) > > Rata-fracken,summana,friken,thing-a-mabob....
Ok, boys, things are finishing up on a high note this week. My partner in crime here in NJ got his UART working, and with it albiet not pretty, a working hello world program. Now the producers and consumers are a bit raw, but the throttle on the 16 byte "bucket brigade" fifo seems to be working. His messaging was pretty messy, but using some of the techniques discussed here, I'm starting to clean them up. here is a snippet of the cleaned up code: ---------------------------- constant project_name_stg : string := "Testing 1, 2, 3! and some more characters too!!!"; SIGNAL project_name_cnt : INTEGER RANGE project_name_stg'range; SIGNAL lprj_MESS_TRAN : STD_LOGIC := '0'; constant person_mess_stg : string := "Cindy Crawford's measurments are: 34, 24, 34"; SIGNAL person_mess_cnt : INTEGER RANGE person_mess_stg'range; SIGNAL lprj_person_TRAN : STD_LOGIC := '0'; SIGNAL lprj_PERSON_TRAN_ENABLE : STD_LOGIC := '0'; ... ------------------------------------------------------------------------------------------------- -- SENDING lprj PROJECT MESSAGE TO TRANSMIT UART ( TX_DATA_IN [ 7-0 ] ) ------------------------------------------------------------------------------------------------- P16: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, TX_BUFFER_FULL, TX_WRITE_BUFFER_STB, lprj_MESS_TRAN, project_name_cnt, lprj_PERSON_TRAN, person_mess_cnt, lprj_RECEIVE_TRAN, RECEIVE_MAX, RECEIVE_MESS ( 0 TO lprj_RECEIVE_MAX ) ) BEGIN IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN IF ( UART_RESET_BUFFER = '0' ) THEN IF ( ( lprj_MESS_TRAN = '1' ) AND ( TX_BUFFER_FULL = '0' ) AND ( TX_WRITE_BUFFER_STB = '0' ) ) THEN --TX_DATA_IN( 7 DOWNTO 0 ) <= PROJECT_NAME ( lprj_MESS_CNT ); TX_DATA_IN <= to_slv(project_name_stg ( project_name_cnt )); ELSIF ( ( lprj_PERSON_TRAN = '1' ) AND ( TX_BUFFER_FULL = '0' ) AND ( TX_WRITE_BUFFER_STB = '0' ) ) THEN TX_DATA_IN <= to_slv(person_mess_stg ( person_mess_cnt )); ELSIF ( ( lprj_RECEIVE_TRAN = '1' ) AND ( TX_BUFFER_FULL = '0' ) AND ( TX_WRITE_BUFFER_STB = '0' ) ) THEN TX_DATA_IN( 7 DOWNTO 0 ) <= RECEIVE_MESS( RECEIVE_MAX ); END IF; END IF; END IF; END PROCESS P16; ----------------------------- which while is a vast improvement over what code he gave me: ------------------------- -- ASCII NUMBERS ----------------------------------------------------------------------------- constant N0 : std_logic_vector( 7 DOWNTO 0 ) := x"30"; -- ASCII VALUE FOR UART constant N1 : std_logic_vector( 7 DOWNTO 0 ) := x"31"; -- ASCII VALUE FOR UART constant N2 : std_logic_vector( 7 DOWNTO 0 ) := x"32"; -- ASCII VALUE FOR UART constant N3 : std_logic_vector( 7 DOWNTO 0 ) := x"33"; -- ASCII VALUE FOR UART constant N4 : std_logic_vector( 7 DOWNTO 0 ) := x"34"; -- ASCII VALUE FOR UART ...<the whole alphabet>... ---------------------------------------------------------------------------------------------- -- LOKI PERSON MESSAGE ARRAY - 44 CHARACTERS ---------------------------------------------------------------------------------------------- SUBTYPE REG_A IS STD_LOGIC_VECTOR( 7 DOWNTO 0 ); TYPE LOKI_PERSON IS ARRAY ( INTEGER RANGE <> ) OF REG_A; SIGNAL LOKI_PERSON_TRAN : STD_LOGIC := '0'; CONSTANT LOKI_PERSON_MAX : INTEGER := 43; SIGNAL LOKI_PERSON_CNT : INTEGER RANGE 0 TO LOKI_PERSON_MAX; SIGNAL LOKI_PERSON_TRAN_ENABLE : STD_LOGIC := '0'; SIGNAL PERSON_MESS : LOKI_PERSON( 0 TO LOKI_PERSON_MAX ) := ( CR, AC, AI, AN, AD, AY, SP, AC, AR, AA, AW, AF, AO, AR, AD, PO, AS, SP, AM, AE, AA, AS, AU, AR, AE, AM, AE, AN, AT, AS, SP, AA, AR, AE, SP, N3, N4, SP, N2, N4, SP, N3, N4, CR ); ... ------------------------ However, my version of the code skips the first letter of each of the messages! the problem I'm sure resides in this bit here: mine: ------------------------------------------------------------------------------------------------- -- INITIALIZING lprj PROJECT MESSAGE COUNT ( project_name_cnt ) ------------------------------------------------------------------------------------------------- P10: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, UART_RESET_NEXT, lprj_MESS_TRAN, TX_WRITE_BUFFER_STB ) BEGIN IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN IF ( ( UART_RESET_BUFFER = '0' ) AND ( UART_RESET_NEXT = '1' ) ) THEN project_name_cnt <= project_name_stg'low; ELSIF ( ( lprj_MESS_TRAN = '1' ) AND ( TX_WRITE_BUFFER_STB = '1' ) AND ( project_name_cnt /= project_name_stg'high ) ) THEN project_name_cnt <= ( project_name_cnt + 1 ); END IF; END IF; END PROCESS P10; his: ------------------------------------------------------------------------------------------------- -- INITIALIZING LOKI PROJECT MESSAGE COUNT ( LOKI_MESS_CNT ) ------------------------------------------------------------------------------------------------- P10: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, UART_RESET_NEXT, LOKI_MESS_TRAN, TX_WRITE_BUFFER_STB ) BEGIN IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN IF ( ( UART_RESET_BUFFER = '0' ) AND ( UART_RESET_NEXT = '1' ) ) THEN LOKI_MESS_CNT <= 0; ELSIF ( ( LOKI_MESS_TRAN = '1' ) AND ( TX_WRITE_BUFFER_STB = '1' ) AND ( LOKI_MESS_CNT /= LOKI_MESS_MAX ) ) THEN LOKI_MESS_CNT <= ( LOKI_MESS_CNT + 1 ); END IF; END IF; END PROCESS P10; -------------------------- I'm guessing that project_name_stg'low is coming in at a 1 instead of 0, and the increment therefore goes to 2, and I start with the second character. Since I've also finally got the testbench going, I should be able to see that project_name_cnt increment to 2 before the first character hits the the TXT_DATA_IN. That's what I about to check out. its Testbench time!!! To be continued....
Reply by Jonathan Bromley January 30, 20092009-01-30
On Fri, 30 Jan 2009 12:51:11 -0800 (PST), rickman wrote:

>I don't think I said anything to the contrary. Johnathan's original >code was written 1 based and I changed it to 0 based. Perhaps you are >looking at subsequent code he has posted in reply to my suggestions.
OK, that may be so. It looks as though there has been some traffic on/around this thread that I didn't see, for whatever reason. Apologies if I misinterpreted the history of the thread.
> my string use was in reading a command file to control >the actions and timing of test benches. The line was read intact and >then various operations searched for the commands and values in the >command.
Most of VHDL's (rather limited) string manipulation facilities are sufficiently well packaged that you almost never need to index your way through a string by hand. I've only rarely found any reason to do so. I guess you found the same. [concerning the extra bit that you might need for indexing a 1-based string]
>One bit out if *each* counter that accesses a string, plus and logic >driven by those counters and so on and so forth. Depending on the >application, it could be a significant amount of waste.
I dispute that; the extra bit only arises in the special situation where your string has exactly 2**N characters, in which case 0-based needs N bits to index but 1-based needs N+1 bits. In all other situations there is no additional cost to 1-based. Unless you have a system that takes perverse delight in using 32- or 64-character strings, I can't believe it makes any real difference.
>> &#4294967295; type stringZ is array (natural range <>) of character; >> and use that - but, of course, you would then lose all >> the built-in TEXTIO functionality that is so useful in >> testbenches. > >Unless you define a conversion which would be quite simple I expect.
sure. -- 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.
Reply by rickman January 30, 20092009-01-30
On Jan 29, 7:07=A0am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Thu, 29 Jan 2009 03:48:56 -0800 (PST), rickman wrote: > >No, Jonathan (the other one) did it correctly. =A0 > > Rick, please check your facts. =A0The line of code > > =A0 constant S: string (0 to 3) :=3D "0123"; > > WILL NOT COMPILE in any standards-compliant tool. > I can believe that some synthesis tools bend the > rules and permit 0-based indexing of strings, but > they should not.
I don't think I said anything to the contrary. Johnathan's original code was written 1 based and I changed it to 0 based. Perhaps you are looking at subsequent code he has posted in reply to my suggestions.
> >It would really bug me to have to use > >1 based indexing for strings in synthesized code. > > It bugs me too, but rules is rules. =A0It is quite > unusual to use strings in synthesis, partly because > some older synthesis tools didn't handle CHARACTER > data, but it works now in all the tools I've seen, > so no reason why we shouldn't go ahead - correctly.
Yes, I have never needed to use a string in synthesis and I have never had to index into a string even in a test bench. I don't have the code handy, but my string use was in reading a command file to control the actions and timing of test benches. The line was read intact and then various operations searched for the commands and values in the command.
> >optimization really should be left for the cases > >where it is worth the cost. > > It's nothing to do with optimization; if the code is > illegal, optimization doesn't happen.
I don't know what you are talking about here. I am not suggesting that invalid code should be used. I am saying that I don't have a need to try to optimize string related code. If I did, I would look to see what was produced and if needed I could define my own string type. There is little special about VHDL. Much of it is just code written to define extensions to the language that can be written in different ways if needed.
> >Do you know how this will synthesize? =A0If my string is 1 to 4, will > >the counter be two bits or three? =A0I think I know the answer, it will > >be three. > > I completely agree with you. =A0If you are so desperate to have a > counter that's one bit shorter, you could easily define your > own new string type
One bit out if *each* counter that accesses a string, plus and logic driven by those counters and so on and so forth. Depending on the application, it could be a significant amount of waste.
> =A0 type stringZ is array (natural range <>) of character; > > and use that - but, of course, you would then lose all > the built-in TEXTIO functionality that is so useful in > testbenches.
Unless you define a conversion which would be quite simple I expect. Rick
Reply by rickman January 30, 20092009-01-30
On Jan 29, 8:27 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
> rickman <gnu...@gmail.com> wrote: > > (snip) > > > I believe the same is true for VHDL. But the code above is not using > > an operator. It is using a conditional assignment based on an IF. > > o2_int <= '1'; > > if o1_int = '1' then > > o2_int <= '0'; > > end if; > > The IF evaluates the signal literally. If it is a '1', then o2_int > > gets '0'. If it is ***any*** other value o2_int retains '1'. > > I believe verilog is slightly less literal, but in this case > with the same result. For verilog, if o1_int was 1`bz then > o1_int=1 would be 1`bx. For if(), 1`b1 is true, everything else > is false. Verilog has the === and !== operators for literal > comparisons including 1`bx and 1`bz. > > I might have written > > assign o2_int = ~o1_int; > > or > > assign o2_int = !o1_int; > > both of which will assign 1`bx if o1_int is 1`bz. > > > I would not use tristate logic, partly because of the problem Andreas > > points out, but mainly because it can be confusing and misleading. I > > think it is much better to change the code to match the current > > devices than to retain the code in an obsolete form. I don't think > > there are any issues of "but this code works"! If you are porting it > > to a new device and most likely new tools, it has to be verified from > > scratch anyway. So fixing the out of date code would not add > > significantly to the cost. > > 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. > > Any design with real (74LS367 for example) tristate buffers > should work, but it might be that some such designs depend > on the bus staying in the previous state for some fraction > of a second after all buffers are disabled. That would > seem to me a design bug, but one that might still exist. > > I don't know what the synthesis tools do if you put a > keeper on the tristate bus.
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. 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. 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. Rick
Reply by glen herrmannsfeldt January 29, 20092009-01-29
rickman <gnuarm@gmail.com> wrote:
(snip)
 
> I believe the same is true for VHDL. But the code above is not using > an operator. It is using a conditional assignment based on an IF.
> o2_int <= '1'; > if o1_int = '1' then > o2_int <= '0'; > end if;
> The IF evaluates the signal literally. If it is a '1', then o2_int > gets '0'. If it is ***any*** other value o2_int retains '1'.
I believe verilog is slightly less literal, but in this case with the same result. For verilog, if o1_int was 1`bz then o1_int=1 would be 1`bx. For if(), 1`b1 is true, everything else is false. Verilog has the === and !== operators for literal comparisons including 1`bx and 1`bz. I might have written assign o2_int = ~o1_int; or assign o2_int = !o1_int; both of which will assign 1`bx if o1_int is 1`bz.
> I would not use tristate logic, partly because of the problem Andreas > points out, but mainly because it can be confusing and misleading. I > think it is much better to change the code to match the current > devices than to retain the code in an obsolete form. I don't think > there are any issues of "but this code works"! If you are porting it > to a new device and most likely new tools, it has to be verified from > scratch anyway. So fixing the out of date code would not add > significantly to the cost.
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. Any design with real (74LS367 for example) tristate buffers should work, but it might be that some such designs depend on the bus staying in the previous state for some fraction of a second after all buffers are disabled. That would seem to me a design bug, but one that might still exist. I don't know what the synthesis tools do if you put a keeper on the tristate bus. -- glen
Reply by Jonathan Bromley January 29, 20092009-01-29
On Thu, 29 Jan 2009 09:34:03 -0800 (PST), jleslie48 wrote:

>> but it's online and free :-) >> >> http://www.csee.umbc.edu/help/VHDL/VHDL-Handbook.pdf >> > >LOL, that is exactly the pdf I was looking at >when I composed my post about >the reserved words list needs to be more inclusive ....
sheesh, I hate doing sales on the NG but you give me no choice... for the cost of less than of half-an-hour of a contractor's time you can have one of our GRGs and get a bunch of hints and tricks as well as the lists of what-have-you that you seek... www.doulos.com/content/products/golden_reference_guides.php with apologies to everyone else for the spam! -- 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.
Reply by jleslie48 January 29, 20092009-01-29
On Jan 29, 12:08 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Thu, 29 Jan 2009 08:44:35 -0800 (PST), jleslie48 wrote: > >But I do love the compile time derived constants, like TstData'range, > >TstData'low, high, etc. > >They will make updates to strings much less cumbersome. > > And many other things too. > > >Is there a list of all these "common" words/concepts somewhere online? > > Try this. It's not as good as our Golden Reference Guide > but it's online and free :-) > > http://www.csee.umbc.edu/help/VHDL/VHDL-Handbook.pdf > > They are "predefined attribute names" and the ones you > need to know about are: > > - for array types, variables and signals: > 'range -- the subscript range such as 7 downto 0 > 'low, 'high -- numerically lowest and highest index > 'left, 'right -- leftmost, rightmost index > 'length -- number of indices in the range > > - for discrete types like INTEGER, NATURAL etc > (but NOT for objects of those types): > 'range, 'low, 'high, 'left, 'right > > - for any singular data type like enumerations, > CHARACTER, STD_LOGIC, integers: > 'image, 'value (mainly for assertions and testbench) > These are FUNCTIONS that allow you to convert > things to/from a human-readable string representation. > So, for example, INTEGER'IMAGE(25) returns the string "25". > INTEGER'VALUE("1000") returns the integer 0. > > Not a comprehensive list, but it covers most of the > routinely useful ones. Note these handy idioms: > > -- make a clone of some other array > signal clone: std_logic_vector(original'range); > > -- vector copy-compatible with "original", but > -- with its index range normalized to (N-1 downto 0) > variable normalized: std_logic_vector(original'length-1 downto 0); > > -- loop over the elements of an array > for i in V'range loop > -- do something with V(i) > end loop; > > >I mean I have a bunch of pdf's that have these very formal lists of > >"reserved words" but > >all of them seem to be missing the "reserved" words of the libraries. > > As you correctly said, they're not reserved. The packages > define the names, and you import them by use-ing the package. > > Too many to list here. Take a look at the packages the > next time you have ModelSim open, or get a copy of Peter > Ashenden's "Designer's Guide to VHDL", or go on a > training course :-0 > -- > 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.
-------------------------
> Too many to list here. Take a look at the packages the > next time you have ModelSim open, or get a copy of Peter > Ashenden's "Designer's Guide to VHDL", or go on a > training course :-0
your list of the "good" ones is fine thanks. and the term "predefined attribute names" for these is great. but there are more. For example, "string" is a library type I'm guessing, and for all practical purposes works just like the rest of my "super-set of reserved words/predefined attribute names/procedures/ functions/goodies"
> but it's online and free :-) > > http://www.csee.umbc.edu/help/VHDL/VHDL-Handbook.pdf >
LOL, that is exactly the pdf I was looking at when I composed my post about the reserved words list needs to be more inclusive ....