You are on page 1of 8

-{**************************************************************************

****}
--{ FileName............: Lcd_controller_main.vhd
--{ Project.............: FPGA
--{-----------------------------------------------------------------------------}
--{
--{ Notes: has some design flaws
--{
--{
--{ Physical 'Testbench' for LCD_CONTROLLER
--{ Output signals on prototyping board:
--{
J4-6 260 ns cycle signal
--{
J4-8 1 ms cycle signal
(1 kHz)
--{
J4-10 0.2 ms cycle signal (5 kHz)
--{-----------------------------------------------------------------------------}
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--{-----------------------------------------------------------------------------}
--{
Xilinx primitives libraries used
--{-----------------------------------------------------------------------------}
library UNISIM;
use UNISIM.VComponents.all;
entity LCD_CONTROLLER_MAIN is
port(
CLK_SMT
: in std_logic;
PUSH_RESET: in
PUSH
: in

std_logic;
std_logic_vector(2 downto 1);

LCD_DB
LCD_E
LCD_RS

: out std_logic_vector (7 downto 0);


: out std_logic;
: out std_logic;

PIEZO

: out std_logic;

P1_LIO_A09: out std_logic;


P1_LIO_A13: out std_logic;
P1_LIO_A15: out std_logic
);
end LCD_CONTROLLER_MAIN;
--{-----------------------------------------------------------------------------}
--{
Architecture
--{-----------------------------------------------------------------------------}
architecture LCD_CONTROLLER of LCD_CONTROLLER_MAIN is
component CLOCK_DIV is
generic(

CLK_TIMING_IN_NS : natural;
cycle time (in ns)
CLK_TIMING_OUT_NS: natural
cycle time (in ns)
);
port(
CLK_IN : in std_logic;
CLK_OUT: out std_logic
);
end component;

-- Input clock
-- Input clock

-- Input clock
-- Output clock

component LCD_CONTROLLER is
port(
RST
: in std_logic;
CLK
: in std_logic;
ns cycle time)
START
: in std_logic;
RS
: in std_logic;
select
DATA
: in std_logic_vector (7 downto 0);
E_PORT
: out std_logic;
port
RS_PORT
: out std_logic;
select port
DATA_PORT : out std_logic_vector (7 downto 0);
READY
: out std_logic
);
end component;

-- Reset
-- Clock (>= 250
-- Start flag
-- Register
-- Data
-- Enable signal
-- Register
-- Data port
-- Ready flag

type tstate_main is (wait1, init1, init2, text1, text2, crlf1, crlf2,


text3, text4, idle,
crlf3, crlf4, press1, press2, press3, crlf5, crlf6,
press4, press5, press6);
type
type
type
type

ttextlength
tline
tinitlength
tinitdata

is
is
is
is

range 16 downto 0;
array(ttextlength) of std_logic_vector (7 downto 0);
range 8 downto 0;
array(tinitlength) of std_logic_vector (7 downto 0);

constant init_data
: tinitdata := (x"38",
x"0E", x"01", x"80", x"00");
constant line1
: tline
:= (x"20",
x"4C", x"49", x"53",
x"4D",
x"20", x"20", x"20", x"00");
constant line2
: tline
:= (x"45",
x"65", x"65", x"72",
x"69",
x"2E", x"56", x"2E", x"00");
constant line3
: tline
:= (x"42",
x"6E", x"20", x"31",
x"20",
x"73", x"65", x"64", x"00");
constant line4
: tline
:= (x"42",
x"6E", x"20", x"32",
x"20",
x"73", x"65", x"64", x"00");
signal state
main state amchine
signal text_index

x"38", x"38", x"38", x"06",


x"20", x"20", x"20", x"20",
x"41", x"52", x"20", x"20",
x"6E", x"67", x"69", x"6E",
x"6E", x"67", x"20", x"42",
x"75", x"74", x"74", x"6F",
x"70", x"72", x"65", x"73",
x"75", x"74", x"74", x"6F",
x"70", x"72", x"65", x"73",

: tstate_main;

-- Current state

: ttextlength;

-- Index counter

signal init_index

: tinitlength;

-- Index counter

signal clk
: std_logic;
master clock
signal rst
: std_logic;
signal start
: std_logic;
for writing to LCD
signal ready
: std_logic;
(ready for writing to LCD)
signal rs
: std_logic;
LCD
signal data
: std_logic_vector (7 downto 0);
to LCD

-- Buffered

signal clk_out : std_logic;


signal clk_1ms : std_logic;
(piezo)
signal clk_02ms: std_logic;
(piezo)

-- LCD clock
-- Timing signal

signal push1_p
PUSH1 button
signal push1_d
PUSH1 button
signal push2_p
PUSH2 button
signal push2_d
PUSH2 button

: std_logic_vector (3 downto 0);

-- Debouncing

: std_logic;

-- Debounced

: std_logic_vector (3 downto 0);

-- Debouncing

: std_logic;

-- Debounced

begin
CLK_250NS_I : CLOCK_DIV
generic map (
CLK_TIMING_IN_NS => 13,
CLK_TIMING_OUT_NS => 260
)
port map (
CLK_IN => clk,
CLK_OUT => clk_out
)
;
CLK_1MS_I : CLOCK_DIV
generic map (
CLK_TIMING_IN_NS => 13,
CLK_TIMING_OUT_NS => 1000000
)
port map (
CLK_IN => clk,
CLK_OUT => clk_1ms
)
;
CLK_02MS_I : CLOCK_DIV
generic map (
CLK_TIMING_IN_NS => 13,
CLK_TIMING_OUT_NS => 200000
)
port map (
CLK_IN => clk,
CLK_OUT => clk_02ms

-- Reset signal
-- Start flag
-- Ready flag
-- RS data for
-- Data to write

-- Timing signal

)
;
UUT : LCD_CONTROLLER
port map (
RST
=> rst,
CLK
=> clk_out,
START
=> start,
RS
=> rs,
DATA
=> data,
E_PORT
=> LCD_E,
RS_PORT
=> LCD_RS,
DATA_PORT => LCD_DB,
READY
=> ready
)
;
--{-----------------------------------------------------------------------------}
--{ Descript: Clock buffering
--{-----------------------------------------------------------------------------}
BUFGDLL_INST1: BUFGDLL
port map (
I => CLK_SMT,
O => clk
)
;
--{-----------------------------------------------------------------------------}
--{ Params : <clk_1ms> Clock
--{ Descript: Debounce the input. This is done by checking the
--{
input for a number of cycles and when all of them are
--{
equal the output changes.
--{-----------------------------------------------------------------------------}
process (clk_1ms)
begin
if (rising_edge(clk_1ms)) then
push1_p(0) <= not(PUSH(1));
push1_p(1) <= push1_p(0);
push1_p(2) <= push1_p(1);
push1_p(3) <= push1_p(2);
if (push1_p = "1111") then
push1_d <= '1';
else
if (push1_p = "0000") then
push1_d <= '0';
end if;
end if;
end if;
end process;
process (clk_1ms)
begin
if (rising_edge(clk_1ms)) then
push2_p(0) <= not(PUSH(2));

push2_p(1) <= push2_p(0);


push2_p(2) <= push2_p(1);
push2_p(3) <= push2_p(2);
if (push2_p = "1111") then
push2_d <= '1';
else
if (push2_p = "0000") then
push2_d <= '0';
end if;
end if;
end if;
end process;
--{-----------------------------------------------------------------------------}
--{
Main state machine
--{-----------------------------------------------------------------------------}
--{-----------------------------------------------------------------------------}
--{ Params : <clk> Clock
--{
<rst> Reset
--{ Descript: Main state machine: State register
--{-----------------------------------------------------------------------------}
process (clk, rst)
begin
if (rst = '1') then
start <= '0';
state <= wait1;
else
if (rising_edge(clk)) then
case state is
when wait1 => start <= '0';
-- Make sure LCD
sequence stops
state <= init1;
init_index <= tinitlength'HIGH;
when init1 => if (ready = '1') then
-- Wait for LCD
ready to accept command
data
<= init_data(init_index);
init_index <= init_index - 1;
start
<= '1';
-- Start LCD
sequence
rs
<= '0';
state
<= init2;
end if;
when init2 => if (ready = '0') then
-- Wait for LCD
sequence started
start <= '0';
-- Make sure
sequence not automatically restarted
if (init_index = 0) then
-- Did we just
send the last initialization data?
state
<= text1;
text_index <= ttextlength'HIGH;
else
state <= init1;
end if;
end if;

when text1 => if (ready = '1') then


-ready to accept command
data
<= line1(text_index);
text_index <= text_index - 1;
start
<= '1';
-sequence
rs
<= '1';
state
<= text2;
end if;
when text2 => if (ready = '0') then
-sequence started
start <= '0';
-sequence not automatically restarted
if (text_index = 0) then
-send the last text line 1 data?
state <= crlf1;
else
state <= text1;
end if;
end if;
when crlf1 => if (ready = '1') then
-ready to accept command
data
<= x"C0";
-set: address $40 (2nd line)
start
<= '1';
-sequence
rs
<= '0';
state
<= crlf2;
end if;
when crlf2 => if (ready = '0') then
-sequence started
start
<= '0';
-sequence not automatically restarted
state
<= text3;
text_index <= ttextlength'HIGH;
end if;
when text3 => if (ready = '1') then
-ready to accept command
data
<= line2(text_index);
text_index <= text_index - 1;
start
<= '1';
-sequence
rs
<= '1';
state
<= text4;
end if;
when text4 => if (ready = '0') then
-sequence started
start <= '0';
-sequence not automatically restarted
if (text_index = 0) then
-send the last text line 2 data?
state <= idle;
else
state <= text3;
end if;
end if;
when idle

=> if (push1_d = '1') then


state <= crlf3;
else
if (push2_d = '1') then

Wait for LCD

Start LCD

Wait for LCD


Make sure
Did we just

Wait for LCD


DDRAM Address
Start LCD

Wait for LCD


Make sure

Wait for LCD

Start LCD

Wait for LCD


Make sure
Did we just

state <= crlf5;


else
state <= idle;
end if;
end if;
when crlf3 => if (ready = '1') then
-ready to accept command
data
<= x"80";
-set: address $00 (1st line)
start
<= '1';
-sequence
rs
<= '0';
state
<= crlf4;
end if;
when crlf4 => if (ready = '0') then
-sequence started
start
<= '0';
-sequence not automatically restarted
state
<= press1;
text_index <= ttextlength'HIGH;
end if;
when press1 => if (ready = '1') then
-ready to accept command
data
<= line3(text_index);
text_index <= text_index - 1;
start
<= '1';
-sequence
rs
<= '1';
state
<= press2;
end if;
when press2 => if (ready = '0') then
-sequence started
start <= '0';
-sequence not automatically restarted
if (text_index = 0) then
-send the last text line 1 data?
state <= press3;
else
state <= press1;
end if;
end if;
when press3 => if (push1_d = '1') then
state <= press3;
else
state <= wait1;
end if;
when crlf5 => if (ready = '1') then
ready to accept command
data
<= x"80";
set: address $00 (1st line)
start
<= '1';
sequence
rs
<= '0';
state
<= crlf6;
end if;
when crlf6 => if (ready = '0') then
sequence started
start
<= '0';
sequence not automatically restarted

Wait for LCD


DDRAM Address
Start LCD

Wait for LCD


Make sure

Wait for LCD

Start LCD

Wait for LCD


Make sure
Did we just

-- Wait for LCD


-- DDRAM Address
-- Start LCD

-- Wait for LCD


-- Make sure

state
<= press4;
text_index <= ttextlength'HIGH;
end if;
when press4 => if (ready = '1') then
-- Wait for LCD
ready to accept command
data
<= line4(text_index);
text_index <= text_index - 1;
start
<= '1';
-- Start LCD
sequence
rs
<= '1';
state
<= press5;
end if;
when press5 => if (ready = '0') then
-- Wait for LCD
sequence started
start <= '0';
-- Make sure
sequence not automatically restarted
if (text_index = 0) then
-- Did we just
send the last text line 1 data?
state <= press6;
else
state <= press4;
end if;
end if;
when press6 => if (push2_d = '1') then
state <= press6;
else
state <= wait1;
end if;
when others
end case;
end if;
end if;
end process;
rst <= not
P1_LIO_A09
P1_LIO_A13
P1_LIO_A15

=> state <= wait1;

PUSH_RESET;
<= clk_out;
<= clk_1ms;
<= clk_02ms;

PIEZO <= (clk_1ms and push1_d) or (clk_02ms and push2_d);


end LCD_CONTROLLER;

You might also like