FPGARelated.com
Forums

RS232 UART: Hello world program finally done.

Started by jleslie48 February 19, 2009
Well through trial and terror I finally have a reasonable "hello
world" program that I think is worthy.  Thanks goes out big time to
Jonathan Bromley and Rick for all their input.

Jonathan's finite state machine, JB_Data_Generator in combination with
the UART example from Xilinx were the combination that allows a
programmer to get his first program fpga program running where he can
print "hello world" onto a screen via the UART port.

I added a few bells and whistles to make the program test the FPGA
board as well, pushbuttons as well as keyboard entry (via the uart
port) are all explored.

the heart of the processor of the messages is the JB_DATA_GENERATOR,
which can process a commanded string
of messages.  Here is my final test commanded string:

         generic map
           ( PC_bits => 9
           , the_program =>
               -- Long startup delay
               op_DELAY & 200
&                                            --2 bytes long
               -- Welcome message
               op_MESSAGE & tua(LF& "program begin 090219 jl02-11
label jump"&LF) & EOM &
               op_LABEL & 01 &
               op_MESSAGE & tua("wait for +"&LF) & EOM &
               -- Wait for a "+" from the keyboard...
               op_WAIT_FOR_CHAR & tua("+") &
               -- and then print another message
               op_LABEL & 02 &
               op_MESSAGE & tua("abc wait for -"&LF) & EOM &
               -- Wait for a "-" from the keyboard
               op_WAIT_FOR_CHAR & tua("-") &
               op_MESSAGE &tua("wait for button push"&LF) &EOM &
               -- and then go back to the beginning! - no delay this
time.

               op_WAIT_FOR_LBL &   -- new test here!  lets see if we
can get this to work


               op_LABEL & 03 &
               op_MESSAGE & tua("the left button has been pushed.
thank you "&LF) & EOM &
               op_WAIT_FOR_LBL &

               op_LABEL & 04 &
               op_MESSAGE & tua("right pb has been pushed. your
welcome."&LF) & EOM &
               op_WAIT_FOR_LBL &

               op_HALT
           )

The big thing that was added to JB's base program was the op_LABEL and
OP_WAIT_FOR_LBL commands.
the model now allows for any number of messages to be added using the
3-tupple: LABEL, MESSAGE, WAIT_FOR_LABEL.

The result is, when the calling process sets the label (in my case
either 2, 3, 4) the corresponding message will print.  I hooked up
labels 3 and 4 to the pushbuttons left and right respectively,
debounced the inputs, waited for the falling edge of the pushbutton,
and then signaled the process JB_DATA_GENERATOR to print the correct
message.  Here is the sample output copied from a terminal session:

program begin 090219 jl02-11 label jump
wait for +
abc wait for -
wait for button push
right pb has been pushed. your welcome.
right pb has been pushed. your welcome.
right pb has been pushed. your welcome.
the left button has been pushed. thank you
right pb has been pushed. your welcome.
the left button has been pushed. thank you
right pb has been pushed. your welcome.

In the data_generator I ran into a bit of problem not realizing the
parallel nature of the value updates.  when
trying to use a created index, I need to wait a clock cycle in order
for the update to the index to take effect. So I originally wrote the
wait for label jump as so:

        when waiting_for_lbl =>
          if (lbl_data  /= x"00") then
              lbl_needed <= '0';
              temp_label_index <= to_integer(unsigned(lbl_data(3
downto 0)));
              PC <= the_label(temp_label_index);  --lbl
              gen_state <= new_PC;
              end if;

but strange things were happening.  PC was being updated with the
value of the_label(0) rather than
the_label(2|3|4)  By putting things on the testbench and simulating
the putton push, I could see that
temp_label_index and PC were both updated at the same time, and the
new value of temp_label_index was
not "in effect" to the next clock cycle.  To fix the problem, I
changed waiting_for_lbl to a two clock cycle implementation as such:

        when waiting_for_lbl =>
          if (lbl_data  /= x"00") then
              lbl_needed <= '0';
              temp_label_index <= to_integer(unsigned(lbl_data(3
downto 0)));
              gen_state <= waiting_for_lbl2;
              end if;
        when waiting_for_lbl2 =>
              PC <= the_label(temp_label_index);  --lbl
              gen_state <= new_PC;
              temp_label_index <= 0;

Now, this print is far from bulletproof.  Most evil is that the if two
signals to print come in at the same time, only the first one prints,
and the second gets ignored.  some sort of queue or wait state needs
to be build for this to be fixed, but alas, Its looking like I'm going
to be put on a new project on Monday, so this one will be regulated to
non-billable hours.