...........
WHEN send =>
busy <= '1';
IF(clk_count < (50 * freq)) THEN --do not exit for 50us
busy <= '1';
IF(clk_count < freq) THEN --negative enable
e <= '0';
ELSIF(clk_count < (14 * freq)) THEN --positive enable half-cycle
e <= '1';
ELSIF(clk_count < (27 * freq)) THEN --negative enable half-cycle
e <= '0';
END IF;
clk_count := clk_count + 1;
state <= send;
ELSE
clk_count := 0;
state <= ready;
END IF;
..........
IMO if you have comments they should be correct or don't include them in the first place
Do this. Read the datasheet the question below about why the enable goes 0-1-0 is shown in the timing diagram.OK thanks.... I will go through the HD44780 datasheet.
a strobe is some thing that goes from a default state to a active state and returns to the default state in a set period of time. The pulse width of the strobe will generally be fixed but the time between pulses are allowed to vary.In this case the strobe is used to enable the read or the writes of the registers in the display. The whole reason for that snippet of code is to pulse the enable high and space those pulses far enough apart to met the timing requirements of the LCD display.Also wanted to know why is the enable toggled in these lines (sorry but I do not know the concept of strobing). What can happen if I dont do so. And how is this toggling rate fixed (assuming that its total time period will be atleast 50usec; as per the description here).
BTW do you know of any other (simple) code for LCD controller pls.
Thanks,
Hobbyiclearner
Yes they re called generics and parameters in vhdl and verilog respectively. The code in question used a constant instead, but the major problem was the use of inline comments within the code that don't match the code. That's a big no-no IMO. It's better to have no comments in the code if you aren't going to edit them to be correct.I'm not sure if similar approach can be applied to FPGAs, but when I program in microcontrollers, I usually add every hardware dependent information parametrized, being situed at the top of the code along with other head parameters ( e.g. numerically defining the above oscillator as 50000000 value in a constant used to calculate other time dependent constants ). This way one would never worry about to review the code which turned more portable to other designs.
IF ( clk_count < DELAY_50US ) THEN
Except the delay isn't 50 us it was 50 * 50 (in MHz) or 20 ns * 50 which is only 1 us, hence the comment is wrong and can change depending on the freq constant used, which in the documentation says you can change to other frequencies if you don't have 50 MHz.
It would have been more appropriate to use 50 * 1 (i.e. 50 * period; -- in us) or something similar so the constant would be period and not freq.
WHEN initialize =>
busy <= '1';
clk_count := clk_count + 1;
IF(clk_count < (10 * freq)) THEN --function set
lcd_data <= "00111100"; --2-line mode, display on
--lcd_data <= "00110100"; --1-line mode, display on
--lcd_data <= "00110000"; --1-line mdoe, display off
--lcd_data <= "00111000"; --2-line mode, display off
[B]e <= '1';[/B]
state <= initialize;
ELSIF(clk_count < (60 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
[B] e <= '0';[/B]
state <= initialize;
ELSIF(clk_count < (70 * freq)) THEN --display on/off control
lcd_data <= "00001100"; --display on, cursor off, blink off
--lcd_data <= "00001101"; --display on, cursor off, blink on
--lcd_data <= "00001110"; --display on, cursor on, blink off
--lcd_data <= "00001111"; --display on, cursor on, blink on
--lcd_data <= "00001000"; --display off, cursor off, blink off
--lcd_data <= "00001001"; --display off, cursor off, blink on
--lcd_data <= "00001010"; --display off, cursor on, blink off
--lcd_data <= "00001011"; --display off, cursor on, blink on
[B]e <= '1';[/B]
state <= initialize;
ELSIF(clk_count < (120 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
[B] e <= '0'[/B];
state <= initialize;
ELSIF(clk_count < (130 * freq)) THEN --display clear
lcd_data <= "00000001";
[B]e <= '1';[/B]
state <= initialize;
ELSIF(clk_count < (2130 * freq)) THEN --wait 2 ms
lcd_data <= "00000000";
[B]e <= '0';[/B]
state <= initialize;
ELSIF(clk_count < (2140 * freq)) THEN --entry mode set
lcd_data <= "00000110"; --increment mode, entire shift off
--lcd_data <= "00000111"; --increment mode, entire shift on
--lcd_data <= "00000100"; --decrement mode, entire shift off
--lcd_data <= "00000101"; --decrement mode, entire shift on
[B]e <= '1';[/B]
state <= initialize;
ELSIF(clk_count < (2200 * freq)) THEN --wait 60 us
lcd_data <= "00000000";
[B]e <= '0';[/B]
state <= initialize;
ELSE --initialization complete
clk_count := 0;
busy <= '0';
state <= ready;
END IF;
Thanks for the time ads-ee. But I will like to differ here. The literal 'freq' is defined here as an integer constant = 50. So it is 50*50 clock pulses or 2500 clock pulses each of 1 clock pulse duration ie. 20ns duration , ie. total duration is 2500*20ns or 50000 nsec or 50usec. So maybe the comment is OK.
Whoop,
The initialization sequence is just another series of writes and reads of the registers in the display so they also need the enable strobes.
I had understood the purpose of having an initalization sequence. All I want to know that the enable here also has been toggled from 0 to 1 to 0 and so on. (see the bold texts in the code snippet of my previous post). What is the purpose of doing so.
Hobbyiclearner
ENTITY lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
[B]busy : OUT STD_LOGIC := '1';[/B] --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_controller;
WHEN power_up =>
busy <= '1';
IF(clk_count < (50000 * freq)) THEN --wait 50 ms
clk_count := clk_count + 1;
state <= power_up;
ELSE --power-up complete
clk_count := 0;
rs <= '0';
rw <= '0';
[B]lcd_data <= "00110000";[/B]
state <= initialize;
END IF;
WHEN send =>
[B] busy <= '1';[/B]
IF(clk_count < (50 * freq)) THEN --do not exit for 50us
busy <= '1';
IF(clk_count < freq) THEN --negative enable
e <= '0';
ELSIF(clk_count < (14 * freq)) THEN --positive enable half-cycle
e <= '1';
ELSIF(clk_count < (27 * freq)) THEN --negative enable half-cycle
e <= '0';
END IF;
clk_count := clk_count + 1;
state <= send;
ELSE
clk_count := 0;
state <= ready;
END IF;
1. Not necessary if reset_n is used appropriately in all modules. With many FPGA, an asynchronous register reset to '1' is also enforcing a '1' power-up level. Specifying it explicitly may avoid a warning.
2. Apparently, the first initialize step sets 8-bit data length. Review the HD44780 command set.
3. For maximum performance, you'll read LCD busy state instead of performing a nominal delay. That's the most common application of reading LCD data. In a noisy environment it can be also useful to check if the display is still holding the expected data and configuration settings.
Consider that the code isn't 100 percent perfect. I'm not motivated to correct it.Pls. do answer the 3rd query as well.
I'm not motivated to correct it.
What motivation is required pls?
Thanks,
Hobbyiclearner.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?