Jump to content
  • 0

Not understanding LCD Display


PoorCollegeStudent

Question

Hello Digilent community,

   I am currently taking my first digital electronics class and my final project is a calculator written in VHDL using a Basys3 board, 16-key keypad, and a 16x2 LCD display with parallel interface, all provided by Digilent. I took a look at the provided example code from the resource library and I just had some questions about how it works. Now, the example code declares a constant before any of the processes, and this constant is an array of std_logic_vectors so it holds a preloaded message "Hello From Digilent" with the necessary function sets and all that preceding the message. In my case, I have to have a way to display the inputs from the keypad on the display and also display the output on the 2nd line of the display. I have the main logic part of the calculator settled, I just want to know how I can direct these signals from the keypad and the output of the computational module (as in the sum, difference, product, etc.) to the LCD display. I have never played with a display before now and never used VHDL or any type of board like the Basys3 before this class, so I guess I'm still quite novice and don't understand a good part of what the example code is telling me. I do get that the state machine is just cycling through the values in the constant and waits for certain delays to pass through before transitioning between certain states.

Since the values on the display have to be updated live as the user inputs numbers from the keypad and also when there is a value computed, how can I shift from having a constant with a preloaded message to something that can update itself as needed? My idea was keep the idea of the array of std_logic_vectors but only have one value (rather than the 23 or 24 that are preloaded in the current example code) that will update with every key press. I'll have two of these, one for the inputs (to show the numbers and operations on the first line) and one for the output (to show on the second line). I'm thinking maybe I declare a variable within a process that will update and be sensitive to the key presses? 

Also, I tried looking around the reference manual and such but I could not find the function code for how to display information on the 2nd line; so far, stuff only displays on the first line. 

Sorry this is such a bulky post. I have had a lot of questions and my professor hasn't been around much. Also, part of this project is learning to interface with new components, so in my case the keypad and lcd display, and I'm not having much luck without any guidance unfortunately. Thank you for taking the time to read this!

P.S. Attached the example vhd file from Digilent here for easy access in case anyone wants to look!

PmodCLP.vhd

Link to comment
Share on other sites

Recommended Posts

1 hour ago, PoorCollegeStudent said:

I am now having some trouble. The inputs will display on the LCD but the output will not. I have testbenched every module and they work as expected. There might be something wrong with the keypad interface. I basically need it to only output once per press rather than continuously like it does now, and I have no way of doing this yet.

To make a single-cycle pulse on 'x_rising_edge' when signal 'x' changes from '0' to '1':

signal x_last              : std_logic := '0';
signal x_rising_edge : std_logic := '0';

 

... inside a clocked process....

if x_last = '0' and x = '1' then
   x_rising_edge <= '1';
else
   x_rising_edge <= '0';
end if;
x_last <= x;

 

Link to comment
Share on other sites

Hello,

 I have come across a new problem. Black boxes across the first line of the display and nothing seems to work, no buttons presses do anything. I think this is a connectivity issue because it worked fine for a while today, and after coming back from eating it started to do this. I will try another computer.

Link to comment
Share on other sites

Update again: Sorry for the spam to everyone who is probably getting these notifications/emails.

The black bars went away when I ran the original example code that displays "Hello From Digilent" which I guess forced the contrast voltage back or something (not really sure how because I don't see anything for that in the code) but I'm not going to question it because it helped.

Link to comment
Share on other sites

@D@n I did assume that at first too, so I looked through my code for an hour but my startup sequence is the same as the one in the example code, so it seems unlikely now (?) The black-box error started to occur right when I plugged in the display to the ports on the board and turned on the board, so I hadnt even run the program yet. Just weird for me all around. Now it's alright though so I think you're right in that the example code sent it through the startup sequence again in a way that mine doesn't, I just can't see why as of yet.

Link to comment
Share on other sites

Hello all,

2:24am update -- I have been able to debounce the keypad somewhat like maybe 85%. Sometimes the number repeats itself once because I guess the keypad itself is VERY jiggly and I'm already accounting for a 400 us bounce limit in my debouncer.. Otherwise, it seems to work fine. It stops after 4 digits and does not continue to display past that. New values can only display after pressing one of the operation buttons (i.e. +, -, *, square) or the equal button. I had to change the negative sign to the center button on the FPGA and a clear button to the right button on the FPGA. Having the "F" key on the keypad was creating very weird results that I did not want to deal with simply because I don't have the time right now given demos are due this Friday. Basically, by setting "F" to a negative sign, the sign would not even display with a press of the "F" key but rather when the first digit was a "2", "3", "6", or "7" (I can't remember since I fixed it since then but I'm pretty sure these were the keys if it even matters). I tried making the negative sign indicated by the three, rightmost LEDs on the Basys3 board and they also lit up with these key values INSTEAD of the designated "F" key. In the code I even made a signal that went high only when "1111" was output by the keypad signals, so I couldn't even see a way this would be the case. Very strange outcome, indeed.

Since assigning the negative sign button to the center button on the FPGA, this issue stopped (thank god) so I have at least concluded that the issue was with the keypad itself and perhaps some timing issues with the debouncer. However, due to the fact that the keys that actually output a negative sign don't really have a clear connection/correlation/relationship I have no clue as to why this error came about.

Thank you all for your help and advice thus far. Tomorrow (thursday), I will be port mapping all the components of the calculator together. I'm thinking of taking a load signal from one of the components and using that to assign a new LCD_CMDS signal that holds the calculated value and have an if-statement assign either of the LCD_CMDS signals to the JB port given the state of the load signal so the display shows the currently desired values (load = high for output, low for input). I'm thinking that if the output is currently being displayed on the LCD, then the press of any number key (i.e. 0 through 9) will reset the display to show the inputs again. As much as I am anxious to try this out, I think I'm at my limit for tonight (this morning).

 

Link to comment
Share on other sites

I am now having some trouble. The inputs will display on the LCD but the output will not. I have testbenched every module and they work as expected. There might be something wrong with the keypad interface. I basically need it to only output once per press rather than continuously like it does now, and I have no way of doing this yet.

Link to comment
Share on other sites

22 minutes ago, hamster said:

To make a single-cycle pulse on 'x_rising_edge' when signal 'x' changes from '0' to '1':

signal x_last              : std_logic := '0';
signal x_rising_edge : std_logic := '0';

 

... inside a clocked process....

if x_last = '0' and x = '1' then
   x_rising_edge <= '1';
else
   x_rising_edge <= '0';
end if;
x_last <= x;

 

Oh right I remember this from an in-class exercise we had once. I'll try it out.

Link to comment
Share on other sites

@PoorCollegeStudent,

You can even put a timer into it as well, forcing only one pulse ever N clock pulses at most:

always @(posedge i_clk)
begin
	pulse <= 1'b0;
	if (btn)
	begin
		pulse <= counter[20];
		counter <= 0;
	end else if (!counter[20])
		counter <= counter + 1'b1;
end

Using this approach, you can set a minimum amount of time between subsequent responses to an input signal.

Dan

Link to comment
Share on other sites

Also a question, will FPGAs act unreliably after being operated/plugged in for a long time (long as in 10+ hours at a time). My demo is today (Friday) and our project still doesn't work unfortunately. Without having touched anything, I came back from dinner to see that the display only seems to like the keys "2", "7", and "9", but perhaps that could be something to do with the keypad decoder. Might not get great marks on this project, but I had a good time on this discussion post. Thank you all for your time and contributions.

Link to comment
Share on other sites

@PoorCollegeStudent,

"will FPGAs act unreliably after being operated/plugged in for a long time"?  Not in my experience.

There can be flaws in your design that will only show up after many hours.  These can be very difficult to debug.

Can I ask you a question, though?  Once you've presented your design and work to your instructure, can you come back and then share with the forum what you did to get your design as far as you got it?  I mean, specifically, how did you go about debugging the design?  I'm curious as to what you did, how you did it, and why you did it--and in general how students in your class handled debugging.

Thanks,

Dan

Link to comment
Share on other sites

Hello Digilent Community,

     I am now officially done with my term and I want to share what my experience was like, as per @D@n's question. I would like to attach our final report here (we got an 86 on it, so please understand that it won't be the rest report haha). It was quite rushed since my partner and I were travelling during the last few days before the turn in date and the code in the appendices are quite scuffed. Vivado won't print PDFs in color and I haven't figured out how to fix the sizing or formatting, which is really inconvenient because it looks bad and not easy to read. If anyone has any questions about the code or writing at all, please feel free to private message me or just respond on this forum by tagging me! The idea behind how we wanted it to work, what it actually became, the struggles we had, and our theory on why it did not work again are included in the report along with our VHDL files and some testbench images. If they end up being too small of pictures, just let me know and i can attach the original ones here so it's easier to see. Thank you all for your help and consideration; it means to the world to me now and it meant the world to me before while I was working on this project.

Link to comment
Share on other sites

Hello all,

Update: I have manged to make keys appear one by one with reliable timing. Thank you to everyone here who helped make this possible. It included an extra state in the current example code's fsm that only goes to the stInitDne when a specific key is pressed. The keys that allow this transition of state would be the number keys (i.e. 0 through 9). I also managed to make it stop at 4 digits and clear when an operation button (+, -, *, =) is pressed in order to make room for the next number. I did this by initializing the LCD_CMDS with blanks and used a counter sensitive to the number keys to replace a specific vector in the LCD_CMDS's array with the corresponding ASCII value. I will put a 5th blank before these numbers to make room for a negative sign.

Currently I am trying to debounce the keys because everytime I test it, the third digit (always the third digit) produces some weird character like a capital C or an alpha symbol. I tried implementing a debouncer into the code, but now it recognizes the keys to the right of the ones pressed. In other words, pressing "1" will show "2" on the display or pressing "8" will display "9". If anyone has any suggestions on how to get around this, that would be great, but for now I'll just keep you all posted when I find a solution.

Link to comment
Share on other sites

Hello,

Just realized the H probably means hex, but using that line of code doesn't work. I've decided beggars can't be choosers since my demo day is in 2 days. I'm sticking to one line of display. 

My strategy right now will be taking the LCD_CMDS signal and initializing it with the first few original commands and 4 blanks. A press of a key on the keypad will replace these blanks with characters and the LCD will update continuously to display these numbers.

I will create a second signal like LCD_CMDS for the output/computed value, and I'll make an if-statement to assign one of two LCD_CMDS signals to the JB port (JA in the example code) so that the LCD will display either the inputs or the output.

Link to comment
Share on other sites

@PoorCollegeStudent,

The "H" reference is an indication that the number just given was given in hexadecimal.  That's why, when I posted my comments about it above, I prefixed the number with 0x--the C-language prefix for hexadecimal numbers, which is also accepted by strtoul(), just not used by the author of that specification.

The trick with issuing the command is that you have to change the RS or "Register Select" pin to zero to indicate a command write, versus "1" to indicate that you wish to write to memory.

Dan

Link to comment
Share on other sites

@D@n Hello,

I had seen that before, but I wasn't aware I could set it using a command. I tried setting a value in my LCD_CMDS signal like 

                4 => "00"&X"40" based on the datasheet but that didn't seem to do anything. It mentions that the second line starts at address 40H, but what does that "H" mean?

Link to comment
Share on other sites

@PoorCollegeStudent,

Check out the display data ram address command.  On page 16, you can discover that when the chip is in 2-line display mode, the first lines display addresses go from 0x0 to 0x27, and the second lines addresses go from 0x40 to 0x67.  So, if you set the address to 0x40, anything you then write should show up on the second line.

Dan

Link to comment
Share on other sites

Hello @D@n, thank you for your response! Yes I have looked at that datasheet because it's also linked from the Digilent website for the LCD display, but I do not think it says anywhere there how I can start displaying on the second line, just how to enable the 2nd line.

 

@hamster I am going to try what you suggest and see what happens. Thanks for letting me know about the debug hub warning too!

Link to comment
Share on other sites

Oh - ignore the Debug Hub message - it just means that your project does not have a debug code (aka. Embedded Virtual Logic Analyser) in the project.

You will need to tinker with the FSM. My first suggestion would be when the user input changes from what is on the screen, jump to the starting state for the FSM so it re-displays everything.

something along the lines of this early on in the FSM, to capture what is on the screen:

      current_bcd <= bcd;

and have the rest of the fsm display what is in "current_bcd"

Then, in the end state of the FSM:

     if bcd /= current_bcd then
        .... do stuff here to restart the FSM, most likely changing lcd_cmd_ptr
     end if;

That way you should have a reasonably responsive display.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...