FPGARelated.com
Forums

Got UART Working!!! need syntax help with using ascii/buffer scheduling.

Started by jleslie48 January 26, 2009
Ok finally,

I've got a working UART.  I initially had it monitor the receive line
and echo back out the character that it received.

I then changed it so that just sent the the letter 'U' by stuffing the
hex code in the TX_DATA_IN buffer:

TX_DATA_IN( 7 DOWNTO 0 ) <= x"55";

so

1)   instead of manually  coverting 'U' to x'55', how do I use a
string literal to do the job.
for instance in C, I would simply write:

tx_data_in = 'U';

which is the same as the c code:

tx_data_in = 0x55;

my point is, I want to be able to use the ascii character instead of
the hexidecimal code.


2) I want a scheduler so that I can put out whole messages. I want to
be able to write on the uart, "I got it\n"

   I can see a language element in VHDL called string:

constant char_sequence : string := "I got it";

but I'm not sure if that is the right way to do it. in addition, I
don't now how to send the characters of char_sequence out
sequentially.

here is my transmit process:

-------------------------------------------------------------------------------------------------
--  LATCHING NEW TRANSMIT DATA FROM RECEIVE UART  ( TX_DATA_IN
[ 7-0 ] )
-------------------------------------------------------------------------------------------------
P7:  PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, RX_READ_BUFFER_STB,
RX_DATA_OUT( 7 DOWNTO 0 )  )
BEGIN
     IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN
          IF ( UART_RESET_BUFFER = '0' ) THEN
               IF ( RX_READ_BUFFER_STB  = '1' ) THEN
                    TX_DATA_IN( 7 DOWNTO 0 ) <= x"55";
               END IF;
          END IF;
     END IF;
END PROCESS P7;

now the x"55"; is gonna have to change, but I imagine that this
process will need
to an entity in another process that is aware of the characters "I got
it" and schedule the
8 characters (I, ,g,o,t, ,i,t) to go out.

Sincerely,

Jon








On Mon, 26 Jan 2009 09:31:01 -0800 (PST), jleslie48 wrote:

>1) instead of manually coverting 'U' to x'55', how do I use a >string literal to do the job. >for instance in C, I would simply write: > >tx_data_in = 'U'; > >which is the same as the c code: > >tx_data_in = 0x55; > >my point is, I want to be able to use the ascii character instead of >the hexidecimal code.
The VHDL is pretty straightforward, but clumsy because of the various type conversions you need. You can convert the character (NOT string) literal 'U' to the corresponding integer using CHARACTER'POS(). Then you need to convert the integer to std_logic_vector in the usual way. It's probably worth the trouble of creating a function: function to_slv(c: character) return std_logic_vector is begin return std_logic_vector(to_unsigned(character'pos(c)), 8)); end; (don't forget to "use ieee.numeric_std.all" as appropriate). Once you've written the function, it's easy: tx_data_in <= to_slv('U'); One small warning: historically some synthesis tools have not handled 'POS attributes, but I think you'll find it's now OK for character types in all modern tools.
>2) I want a scheduler so that I can put out whole messages. I want to >be able to write on the uart, "I got it\n"
In hardware? Then you'll need to count your way through the string. VHDL strings are array(1 to N) of character. If this were a testbench you could easily do variable my_message: string := "I got it" & CR & LF; ... for i in my_message'range loop SEND_A_CHARACTER(my_message(i)); end loop; But in hardware you need to maintain an explicit counter that will count its way through your string, copying the appropriate character to your Tx register at the appropriate clock cycle as indicated by some "ready" flag. Then, of course, you increment the counter ready for next time. And please note that strings do NOT get a trailing NULL character, unless you choose to add it explicitly.
>------------------------------------------------------------------------------------------------- >-- LATCHING NEW TRANSMIT DATA FROM RECEIVE UART ( TX_DATA_IN >[ 7-0 ] ) >------------------------------------------------------------------------------------------------- >P7: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, RX_READ_BUFFER_STB, >RX_DATA_OUT( 7 DOWNTO 0 ) ) >BEGIN > IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN > IF ( UART_RESET_BUFFER = '0' ) THEN > IF ( RX_READ_BUFFER_STB = '1' ) THEN > TX_DATA_IN( 7 DOWNTO 0 ) <= x"55"; > END IF; > END IF; > END IF; >END PROCESS P7;
That's it; where you now do TX_DATA_IN <= x"55", instead do TX_DATA_IN <= to_slv(msg(i)); i <= i + 1; (assuming i is a signal of some integer type). But that somewhat begs the question: where do you plan to store "msg"? If it's a constant, the synthesis tool will sort it out for you; if you want it to be a variable, you'll need to think about where the storage physically lives, how to load it from some other piece of hardware etc. By the way, is TX_DATA_IN wider than 8 bits? If not, then don't waste your breath specifying (7 downto 0) on each assignment. And get into the habit of using rising_edge(C) instead of the ugly and obsolete idiom (C='1' and C'event). There used to be a time when some synthesis tools didn't understand rising_edge, but that hasn't been the case for years. Using 'event just looks archaic. -- 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 Jan 26, 1:40 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Mon, 26 Jan 2009 09:31:01 -0800 (PST), jleslie48 wrote: > >1) instead of manually coverting 'U' to x'55', how do I use a > >string literal to do the job. > >for instance in C, I would simply write: > > >tx_data_in = 'U'; > > >which is the same as the c code: > > >tx_data_in = 0x55; > > >my point is, I want to be able to use the ascii character instead of > >the hexidecimal code. > > The VHDL is pretty straightforward, but clumsy because of the > various type conversions you need. You can convert the > character (NOT string) literal 'U' to the corresponding > integer using CHARACTER'POS(). Then you need to convert > the integer to std_logic_vector in the usual way. It's > probably worth the trouble of creating a function: > > function to_slv(c: character) return std_logic_vector is > begin > return std_logic_vector(to_unsigned(character'pos(c)), 8)); > end; > > (don't forget to "use ieee.numeric_std.all" as appropriate). > > Once you've written the function, it's easy: > > tx_data_in <= to_slv('U'); > > One small warning: historically some synthesis tools have > not handled 'POS attributes, but I think you'll find it's > now OK for character types in all modern tools. > > >2) I want a scheduler so that I can put out whole messages. I want to > >be able to write on the uart, "I got it\n" > > In hardware? Then you'll need to count your way through the > string. VHDL strings are array(1 to N) of character. > If this were a testbench you could easily do > > variable my_message: string := "I got it" & CR & LF; > ... > for i in my_message'range loop > SEND_A_CHARACTER(my_message(i)); > end loop; > > But in hardware you need to maintain an explicit counter > that will count its way through your string, copying > the appropriate character to your Tx register at the > appropriate clock cycle as indicated by some "ready" > flag. Then, of course, you increment the counter > ready for next time. And please note that strings > do NOT get a trailing NULL character, unless you choose > to add it explicitly. > > >------------------------------------------------------------------------------------------------- > >-- LATCHING NEW TRANSMIT DATA FROM RECEIVE UART ( TX_DATA_IN > >[ 7-0 ] ) > >------------------------------------------------------------------------------------------------- > >P7: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, RX_READ_BUFFER_STB, > >RX_DATA_OUT( 7 DOWNTO 0 ) ) > >BEGIN > > IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN > > IF ( UART_RESET_BUFFER = '0' ) THEN > > IF ( RX_READ_BUFFER_STB = '1' ) THEN > > TX_DATA_IN( 7 DOWNTO 0 ) <= x"55"; > > END IF; > > END IF; > > END IF; > >END PROCESS P7; > > That's it; where you now do TX_DATA_IN <= x"55", > instead do > > TX_DATA_IN <= to_slv(msg(i)); > i <= i + 1; > > (assuming i is a signal of some integer type). > > But that somewhat begs the question: where do you > plan to store "msg"? If it's a constant, the synthesis > tool will sort it out for you; if you want it to be > a variable, you'll need to think about where the > storage physically lives, how to load it from some > other piece of hardware etc. > > By the way, is TX_DATA_IN wider than 8 bits? If not, > then don't waste your breath specifying (7 downto 0) > on each assignment. And get into the habit of using > rising_edge(C) instead of the ugly and obsolete > idiom (C='1' and C'event). There used to be a time > when some synthesis tools didn't understand rising_edge, > but that hasn't been the case for years. Using 'event > just looks archaic. > -- > 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.
ooohhhhhh.... looks like what I want. I added to_slv to the architecture, but I get synth errors: ERROR:HDLParsers:3324 - "C:/jon/fpga_uarted_01/2009_01_26/ LOKI_New_H_Project_VHDL/Code_Versions/10 - New_Xilinx_Wrap_Data/ LOKI_Top/LOKI_Top.vhd" Line 131. IN mode Formal SIZE of to_unsigned with no default value must be associated with an actual value. ERROR:HDLParsers:854 - "C:/jon/fpga_uarted_01/2009_01_26/ LOKI_New_H_Project_VHDL/Code_Versions/10 - New_Xilinx_Wrap_Data/ LOKI_Top/LOKI_Top.vhd" Line 131. The expression can not be converted to type std_logic_vector. ERROR:HDLParsers:164 - "C:/jon/fpga_uarted_01/2009_01_26/ LOKI_New_H_Project_VHDL/Code_Versions/10 - New_Xilinx_Wrap_Data/ LOKI_Top/LOKI_Top.vhd" Line 131. parse error, unexpected CLOSEPAR, expecting SEMICOLON
On Jan 26, 3:22 pm, jleslie48 <j...@jonathanleslie.com> wrote:
> On Jan 26, 1:40 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com> > wrote: > > > > > On Mon, 26 Jan 2009 09:31:01 -0800 (PST), jleslie48 wrote: > > >1) instead of manually coverting 'U' to x'55', how do I use a > > >string literal to do the job. > > >for instance in C, I would simply write: > > > >tx_data_in = 'U'; > > > >which is the same as the c code: > > > >tx_data_in = 0x55; > > > >my point is, I want to be able to use the ascii character instead of > > >the hexidecimal code. > > > The VHDL is pretty straightforward, but clumsy because of the > > various type conversions you need. You can convert the > > character (NOT string) literal 'U' to the corresponding > > integer using CHARACTER'POS(). Then you need to convert > > the integer to std_logic_vector in the usual way. It's > > probably worth the trouble of creating a function: > > > function to_slv(c: character) return std_logic_vector is > > begin > > return std_logic_vector(to_unsigned(character'pos(c)), 8)); > > end; > > > (don't forget to "use ieee.numeric_std.all" as appropriate). > > > Once you've written the function, it's easy: > > > tx_data_in <= to_slv('U'); > > > One small warning: historically some synthesis tools have > > not handled 'POS attributes, but I think you'll find it's > > now OK for character types in all modern tools. > > > >2) I want a scheduler so that I can put out whole messages. I want to > > >be able to write on the uart, "I got it\n" > > > In hardware? Then you'll need to count your way through the > > string. VHDL strings are array(1 to N) of character. > > If this were a testbench you could easily do > > > variable my_message: string := "I got it" & CR & LF; > > ... > > for i in my_message'range loop > > SEND_A_CHARACTER(my_message(i)); > > end loop; > > > But in hardware you need to maintain an explicit counter > > that will count its way through your string, copying > > the appropriate character to your Tx register at the > > appropriate clock cycle as indicated by some "ready" > > flag. Then, of course, you increment the counter > > ready for next time. And please note that strings > > do NOT get a trailing NULL character, unless you choose > > to add it explicitly. > > > >------------------------------------------------------------------------------------------------- > > >-- LATCHING NEW TRANSMIT DATA FROM RECEIVE UART ( TX_DATA_IN > > >[ 7-0 ] ) > > >------------------------------------------------------------------------------------------------- > > >P7: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, RX_READ_BUFFER_STB, > > >RX_DATA_OUT( 7 DOWNTO 0 ) ) > > >BEGIN > > > IF ( CLK_16_6MHZ = '1' AND CLK_16_6MHZ'EVENT ) THEN > > > IF ( UART_RESET_BUFFER = '0' ) THEN > > > IF ( RX_READ_BUFFER_STB = '1' ) THEN > > > TX_DATA_IN( 7 DOWNTO 0 ) <= x"55"; > > > END IF; > > > END IF; > > > END IF; > > >END PROCESS P7; > > > That's it; where you now do TX_DATA_IN <= x"55", > > instead do > > > TX_DATA_IN <= to_slv(msg(i)); > > i <= i + 1; > > > (assuming i is a signal of some integer type). > > > But that somewhat begs the question: where do you > > plan to store "msg"? If it's a constant, the synthesis > > tool will sort it out for you; if you want it to be > > a variable, you'll need to think about where the > > storage physically lives, how to load it from some > > other piece of hardware etc. > > > By the way, is TX_DATA_IN wider than 8 bits? If not, > > then don't waste your breath specifying (7 downto 0) > > on each assignment. And get into the habit of using > > rising_edge(C) instead of the ugly and obsolete > > idiom (C='1' and C'event). There used to be a time > > when some synthesis tools didn't understand rising_edge, > > but that hasn't been the case for years. Using 'event > > just looks archaic. > > -- > > 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. > > ooohhhhhh.... > > looks like what I want. > > I added to_slv to the architecture, but I get synth errors: > > ERROR:HDLParsers:3324 - "C:/jon/fpga_uarted_01/2009_01_26/ > LOKI_New_H_Project_VHDL/Code_Versions/10 - New_Xilinx_Wrap_Data/ > LOKI_Top/LOKI_Top.vhd" Line 131. IN mode Formal SIZE of to_unsigned > with no default value must be associated with an actual value. > ERROR:HDLParsers:854 - "C:/jon/fpga_uarted_01/2009_01_26/ > LOKI_New_H_Project_VHDL/Code_Versions/10 - New_Xilinx_Wrap_Data/ > LOKI_Top/LOKI_Top.vhd" Line 131. The expression can not be converted > to type std_logic_vector. > ERROR:HDLParsers:164 - "C:/jon/fpga_uarted_01/2009_01_26/ > LOKI_New_H_Project_VHDL/Code_Versions/10 - New_Xilinx_Wrap_Data/ > LOKI_Top/LOKI_Top.vhd" Line 131. parse error, unexpected CLOSEPAR, > expecting SEMICOLON
never mind on this one. its a missmatched paren's problem. the line: return std_logic_vector(to_unsigned(character'pos(c)), 8)); should read: return std_logic_vector(to_unsigned(character'pos(c), 8)); I should of read the error messages more carefully.
On Mon, 26 Jan 2009 12:36:24 -0800 (PST), jleslie48 wrote:

>the line: > return std_logic_vector(to_unsigned(character'pos(c)), 8)); > >should read: > return std_logic_vector(to_unsigned(character'pos(c), 8));
yeah, sorry. I reckon I'm entitled to an occasional mismatched parenthesis in a NG post :-) -- 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 Jan 26, 4:01 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Mon, 26 Jan 2009 12:36:24 -0800 (PST), jleslie48 wrote: > >the line: > > return std_logic_vector(to_unsigned(character'pos(c)), 8)); > > >should read: > > return std_logic_vector(to_unsigned(character'pos(c), 8)); > > yeah, sorry. I reckon I'm entitled to an occasional > mismatched parenthesis in a NG post :-) > -- > 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.
No worries. BTW worked like a charm. I know functions and procedures are going to be key to getting the big project done, and now the first one is written. Excellent Now to digest part 2) of your answer...
In and email Jonathan Leslie said:
> > TX_DATA_IN( 7 DOWNTO 0 ) <=3D x"55"; > What is wrong with the way you have it written above? > > JL:: - nothing if all I want is a single character on the outbound, but t=
he idea is to get to a point where I can put message strings on the outboun= d uart. My app will need message packets sent out, and making long strings= of hex code makes for a maintenance nightmare.
> > having a string of > TX_DATA_IN( 7 DOWNTO 0 ) <=3D x"55"; > -- send char > TX_DATA_IN( 7 DOWNTO 0 ) <=3D x"45"; > -- send char > TX_DATA_IN( 7 DOWNTO 0 ) <=3D x"62"; > -- send char > > is gonna get real annoying I'm building up to making a > communication package where I can send out on my uart > > send_to_uart("UUT:init"); > > or > > send_to_uart("UUT:shutdown"); > > > > 1) Instead of using a test for the clock being 1 and an event, you > should use rising_edge(clock). This is a standard form and will make > the simulation match the synthesis better. > JL:: - check. thanks for semantic correction. > > > > > 2) The above should be a single process and not combined with > anything else. > JL:: Quite right, I think I misspoke. I mean that the routine needs to b=
e able to handle a "parameter" (using a c term) in
> place of the x"55" where some other routine establishes what exactly is g=
oing to be sent on the TX line.
> > > It will check for the trigger just as you have it > written. When found, it will use the character currently pointed to > by the index and increment the index. Remember that HDL describes > hardware and this is a description of the transmit holding register > and the logic controlling its timing. BTW, is this a holding > register or the transmitter data register (the one that shifts the > data out)? If the latter, you need to describe both the loading and > the shifting in one process. > > JL:: not sure what your getting at here. I don't see anything to increme=
nt an index. Now as far as how the tx_data_in is used,
> either as a register or transmitter data register, well that's a good que=
stion. I'm gonna have to dig a little on that one. You need to *add* a counter. The only way you can access the individual characters in the string is to use an index. Thinking of this in hardware, there will be a tx shift register, a tx holding register and a character source which does not need to be a register, but can be. The two registers need to define their controls and actions in the same or different clocked processes. The character source is controlled by a counter which also needs to be defined in a clocked process. The character source can be defined in an unclocked process or in a concurrent statement. In the process it would be a case statement. In a concurrent statement it would be a selected statement, IIRC (the one that uses "with"). I can tell that you are still trying to code in C. When you refer to this as 'the routine needs to be able to handle a "parameter"' that says to me that you are thinking of a subroutine that is called by a higher routine. VHDL does not work like that really. A process is *not* a subroutine. A process defines hardware that runs separately from the other hardware in the design. Here is a way to visualize the difference. When you program in C, you would normally use a flowchart. That shows sequences of operations. When you program in an HDL, you would instead use a data flow diagram. That shows different operations on data that happen at the same time. In a flowchart, blocks can be used that represent subroutines that can be separately charted in levels. In a data flow diagram, each block is a process that runs all the time and acts on whatever data is presented to it.
> The way I'm thinking is that I'm gonna need a fifo buffer where the trans=
mit characters are placed and as long as that buffer is not empty the P7 pr= ocess will take a character, load it into the tx_data_in register, and send= it on its way. the fifo buffer handler will then move its pointer to the = next character in the fifo. You would only need a FIFO if you can't control the rate that characters are sent to the Xmitter. Since you are producing the characters, you can control that. Actually, the same is true for a Tx Holding register. It is only there so that a CPU can have a full character time to send the next character to the xmitter. The xmitter has timing to control the character shifting. When it is complete, the next data is loaded into the TxData register. A TxRdy signal is asserted at this time and the counter is incremented so the next character is presented. Having a poor memory for detail, I always have to use templates or look at existing code in order to write HDL. So I'll use pseudo code here, meaning don't trust my details... constant TstData : string(0 to 15) :=3D "Testing 1, 2, 3!"; signal TxCntr : integer range 0 to 15; TxNxtData <=3D TstData (TxCntr); -- Data source control, provide string data to the UART, repeat every 16 chars process SelectCntr ( clk, reset ) is begin if (reset =3D '1') then TxCntr <=3D 0; elsif ( rising_edge (clk) ) then if ( TxRdy =3D '0' ) then TxWrite <=3D '0'; else if ( TxWrite =3D '0' ) then TxWrite <=3D '1'; if ( TxCntr =3D 15 ) then TxCntr <=3D 0; else TxCntr <=3D TxCntr + 1; end if; end if; end if; end if; end process; -- This code should be replaced with your UART code process UART_Tx ( clk, reset ) is begin if (reset =3D '1') then TxCntr <=3D 0; elsif ( rising_edge (clk) ) then if ( TxBitCnt =3D 9 ) then if ( TxWrite =3D '1' ) then TxData <=3D '0' & TxNxtData; TxRdy <=3D '0'; TxBitCnt <=3D 0; elsif ( TxBitTiming =3D '1' ) then TxRdy <=3D '1'; end if; elsif ( TxBitTiming =3D '1' ) then TxData <=3D TxData ( TxData'high - 1 downto 0 ) & '1'; TxBitCnt <=3D TxBitCnt + 1; end if; end if; end process; Does this make sense? Do you see how this is different from writing C code? Rick
> --- On Mon, 1/26/09, Rick Collins <gnuarm.2006@arius.com> wrote: > > > From: Rick Collins <gnuarm.2006@arius.com> > Subject: Re: RS232 Uart is working!! now to get it cleaned up. > To: jon@jonathanleslie.com > Date: Monday, January 26, 2009, 2:16 PM > > > At 01:34 PM 1/26/2009, you wrote: > > Ok finally, > > > > I've got a working UART. I initially had it monitor the receive line > > and echo back out the character that it received. > > > > I then changed it so that just sent the the letter 'U' by stuffing the > > hex code in the TX_DATA_IN buffer: > > > > TX_DATA_IN( 7 DOWNTO 0 ) <=3D x"55"; > > > > so > > > > 1) instead of manually converting 'U' to x'55', how do I use a > > string literal to do the job. > > for instance in C, I would simply write: > > > > tx_data_in =3D 'U'; > > > > which is the same as the c code: > > > > tx_data_in =3D 0x55; > > > > my point is, I want to be able to use the ascii character instead of > > the hexidecimal code. > > What is wrong with the way you have it written above? Although the > above is a character literal and not a string. A string would be > "abcd". To send that you would need a loop that sends each character > in turn. You can either put a check for TxRdy explicity in the loop > code or you can make a function that waits for TxRdy and sends one > character. Then call this function in the loop. > > Opps, I guess I was thinking of C code. You can do something > similiar in VHDL using an index to address the string. > > > 2) I want a scheduler so that I can put out whole messages. I want to > > be able to write on the uart, "I got it\n" > > > > I can see a language element in VHDL called string: > > > > constant char_sequence : string :=3D "I got it"; > > > > but I'm not sure if that is the right way to do it. in addition, I > > don't now how to send the characters of char_sequence out > > sequentially. > > > > here is my transmit process: > > > > -----------------------------------------------------------------------=
--------------------------
> > -- LATCHING NEW TRANSMIT DATA FROM RECEIVE UART ( TX_DATA_IN > > [ 7-0 ] ) > > -----------------------------------------------------------------------=
--------------------------
> > P7: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, RX_READ_BUFFER_STB, > > RX_DATA_OUT( 7 DOWNTO 0 ) ) > > BEGIN > > IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN > > IF ( UART_RESET_BUFFER =3D '0' ) THEN > > IF ( RX_READ_BUFFER_STB =3D '1' ) THEN > > TX_DATA_IN( 7 DOWNTO 0 ) <=3D x"55"; > > END IF; > > END IF; > > END IF; > > END PROCESS P7; > > > > now the x"55"; is gonna have to change, but I imagine that this > > process will need > > to be an entity in another process that is aware of the characters "I g=
ot
> > it" and schedule the > > 8 characters (I, ,g,o,t, ,i,t) to go out. > > 1) Instead of using a test for the clock being 1 and an event, you > should use rising_edge(clock). This is a standard form and will make > the simulation match the synthesis better. > > 2) The above should be a single process and not combined with > anything else. It will check for the trigger just as you have it > written. When found, it will use the character currently pointed to > by the index and increment the index. Remember that HDL describes > hardware and this is a description of the transmit holding register > and the logic controlling its timing. BTW, is this a holding > register or the transmitter data register (the one that shifts the > data out)? If the latter, you need to describe both the loading and > the shifting in one process. > > Rick
Having a poor memory for detail, I always have to use templates or
look at existing code in order to write HDL.  So I'll use pseudo code
here, meaning don't trust my details...

constant TstData : string(0 to 15) := "Testing 1, 2, 3!";
signal TxCntr : integer range 0 to 15;

TxNxtData <= TstData (TxCntr);

-- Data source control, provide string data to the UART, repeat every
16 chars
process SelectCntr ( clk, reset ) is
begin
  if (reset = '1') then
    TxCntr <= 0;
  elsif ( rising_edge (clk) ) then
    if ( TxRdy = '0' ) then
      TxWrite <= '0';
    else
      if ( TxWrite = '0' ) then
        TxWrite <= '1';
        if ( TxCntr = 15 ) then
          TxCntr <= 0;
        else
          TxCntr <= TxCntr + 1;
        end if;
      end if;
    end if;
  end if;
end process;

-- This code should be replaced with your UART code
process UART_Tx ( clk, reset ) is
begin
  if (reset = '1') then
    TxCntr <= 0;
  elsif ( rising_edge (clk) ) then
    if ( TxBitCnt = 9 ) then
      if ( TxWrite = '1' ) then
        TxData <= '0' & TxNxtData;
        TxRdy <= '0';
        TxBitCnt <= 0;
      elsif ( TxBitTiming = '1' ) then
        TxRdy <= '1';
      end if;
    elsif ( TxBitTiming = '1' ) then
      TxData <= TxData ( TxData'high - 1 downto 0 ) & '1';
      TxBitCnt <= TxBitCnt + 1;
    end if;
  end if;
end process;

Does this make sense?  Do you see how this is different from writing C
code?

Rick

Yeah I'm gonna fall into that linear C programming trap a lot.

And I haven't met a programmer yet worth his weight that didn't
"use templates or look at existing code"

Plus its been 20 years since I programmed using flowcharts,
I've always worked at the mathematical algorithm level  then to pseudo
code,
then source code.  Always in a linear fashion fitting in with either C/
pascal. I
think when you code threads in C is the closest you get to this
environment.
never liked threads ;)

the SelectCntr process as you pseudo coded up, will use its clk
to make the looper go through the the TstData, but the routine is
going to
need a governor  of some sorts so that message only goes out once yes?
I mean that either I have to control the clk to it or make another
semaphore that
turns on on reset and off on TxCntr = 15.

now before I went home tonight I took a quick look at the inner
workings of my Uart_tx.

it seems to have two entities, a transmit_xyz, and a "water brigade"
fifo.   Should be
interesting in the morning.  - Jon




On Jan 26, 8:26 pm, jleslie48 <j...@jonathanleslie.com> wrote:
> > Yeah I'm gonna fall into that linear C programming trap a lot. > > And I haven't met a programmer yet worth his weight that didn't > "use templates or look at existing code" > > Plus its been 20 years since I programmed using flowcharts, > I've always worked at the mathematical algorithm level then to pseudo > code, > then source code. Always in a linear fashion fitting in with either C/ > pascal. I > think when you code threads in C is the closest you get to this > environment. > never liked threads ;)
The flow chart thing was just to illustrate how HDL is different from a software programming language. But you are still trying to relate software to HDL. I suggest that you just forget software and learn from scratch.
> the SelectCntr process as you pseudo coded up, will use its clk > to make the looper go through the the TstData, but the routine is > going to > need a governor of some sorts so that message only goes out once yes? > I mean that either I have to control the clk to it or make another > semaphore that > turns on on reset and off on TxCntr = 15.
You tell me if it goes out once or indefinitely. If you only want it to go out once, you can change it to stop when the counter reaches 16. You don't need to add another signal. Although it can be useful at times to have a separate signal from a concurrent assignment for the enable on a register. By being able to plot the enable in the simulator, it can help to find bugs. BTW, in simulation, I have always found it awkward to step the code like I was debugging software. Rather I put up waveforms as if I was debugging hardware. Stepping code can be very messy when the simulation moves between the different processes. Also, each process runs when any sensitive signal changes although it may not result in any code being run, such as on the falling edge of a register clock. Just a suggestion. I'm sure each has their own preferences. constant TstData : string(0 to 15) := "Testing 1, 2, 3!"; signal TxCntr : integer range 0 to 16; TxNxtData <= TstData (TxCntr); -- Data source control, provide string data to the UART, repeat every 16 chars process SelectCntr ( clk, reset ) is begin if (reset = '1') then TxCntr <= 0; elsif ( rising_edge (clk) ) then if ( TxRdy = '0' ) then TxWrite <= '0'; else if ( TxWrite = '0' and TxCntr <> 16 ) then TxWrite <= '1'; TxCntr <= TxCntr + 1; end if; end if; end if; end process; This will run one time and the counter will reach 16 and stop.
> now before I went home tonight I took a quick look at the inner > workings of my Uart_tx. > > it seems to have two entities, a transmit_xyz, and a "water brigade" > fifo. Should be > interesting in the morning. - Jon
Is this a 16550 UART? The 16xxx line of UARTs has a number of models all with backward compatibility, AFAIK. I'm not sure exactly which model first adds a FIFO rather than just a holding register (one level FIFO), but it shouldn't make a difference to your design. There will be a two signal handshake, a TxRegRdy (or TxHoldRdy) which tells the data generator that the FIFO/Tx holding register is ready to receive a new character. The data generator has to generate a write signal to put the character into the UART. It is that simple. The UART should be edge sensitive to the write signal. The handshake above will work with that. But if the handshake from the UART does not toggle on writing each Actually, if your data generator in the final design can accommodate the handshake above, you won't need the FIFO. No point in adding any complexity that is not needed. Rick
jleslie48 wrote:

> And I haven't met a programmer yet worth his weight that didn't > "use templates or look at existing code" > Plus its been 20 years since I programmed using flowcharts, > I've always worked at the mathematical algorithm level then to pseudo > code, > then source code. Always in a linear fashion fitting in with either C/ > pascal.
The reference design here: http://mysite.verizon.net/miketreseler/ is a single process (aka: sequential, linear, single threaded) vhdl design that just happens to be a uart. (But read Jonathan's stuff first) -- Mike Treseler