shilongo83
Newbie level 6
- Joined
- Apr 27, 2009
- Messages
- 12
- Helped
- 3
- Reputation
- 6
- Reaction score
- 2
- Trophy points
- 1,283
- Activity points
- 1,378
--{******************************************************************************}
--{ 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 std_logic;
PUSH : in std_logic_vector(2 downto 1);
LCD_DB : out std_logic_vector (7 downto 0);
LCD_E : out std_logic;
LCD_RS : 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; -- Input clock cycle time (in ns)
CLK_TIMING_OUT_NS: natural -- Input clock cycle time (in ns)
);
port(
CLK_IN : in std_logic; -- Input clock
CLK_OUT: out std_logic -- Output clock
);
end component;
component LCD_CONTROLLER is
port(
RST : in std_logic; -- Reset
CLK : in std_logic; -- Clock (>= 250 ns cycle time)
START : in std_logic; -- Start flag
RS : in std_logic; -- Register select
DATA : in std_logic_vector (7 downto 0); -- Data
E_PORT : out std_logic; -- Enable signal port
RS_PORT : out std_logic; -- Register select port
DATA_PORT : out std_logic_vector (7 downto 0); -- Data port
READY : out std_logic -- Ready flag
);
end component;
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 ttextlength is range 16 downto 0;
type tline is array(ttextlength) of std_logic_vector (7 downto 0);
type tinitlength is range 8 downto 0;
type tinitdata is array(tinitlength) of std_logic_vector (7 downto 0);
constant init_data : tinitdata := (x"38", x"38", x"38", x"38", x"06", x"0E", x"01", x"80", x"00");
constant line1 : tline := (x"20", x"20", x"20", x"20", x"20", x"4C", x"49", x"53",
x"4D", x"41", x"52", x"20", x"20", x"20", x"20", x"20", x"00");
constant line2 : tline := (x"45", x"6E", x"67", x"69", x"6E", x"65", x"65", x"72",
x"69", x"6E", x"67", x"20", x"42", x"2E", x"56", x"2E", x"00");
constant line3 : tline := (x"42", x"75", x"74", x"74", x"6F", x"6E", x"20", x"31",
x"20", x"70", x"72", x"65", x"73", x"73", x"65", x"64", x"00");
constant line4 : tline := (x"42", x"75", x"74", x"74", x"6F", x"6E", x"20", x"32",
x"20", x"70", x"72", x"65", x"73", x"73", x"65", x"64", x"00");
signal state : tstate_main; -- Current state main state amchine
signal text_index : ttextlength; -- Index counter
signal init_index : tinitlength; -- Index counter
signal clk : std_logic; -- Buffered master clock
signal rst : std_logic; -- Reset signal
signal start : std_logic; -- Start flag for writing to LCD
signal ready : std_logic; -- Ready flag (ready for writing to LCD)
signal rs : std_logic; -- RS data for LCD
signal data : std_logic_vector (7 downto 0); -- Data to write to LCD
signal clk_out : std_logic; -- LCD clock
signal clk_1ms : std_logic; -- Timing signal (piezo)
signal clk_02ms: std_logic; -- Timing signal (piezo)
signal push1_p : std_logic_vector (3 downto 0); -- Debouncing PUSH1 button
signal push1_d : std_logic; -- Debounced PUSH1 button
signal push2_p : std_logic_vector (3 downto 0); -- Debouncing PUSH2 button
signal push2_d : std_logic; -- Debounced PUSH2 button
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
)
;
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 -- Wait for LCD ready to accept command
data <= line1(text_index);
text_index <= text_index - 1;
start <= '1'; -- Start LCD sequence
rs <= '1';
state <= text2;
end if;
when text2 => 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 <= crlf1;
else
state <= text1;
end if;
end if;
when crlf1 => if (ready = '1') then -- Wait for LCD ready to accept command
data <= x"C0"; -- DDRAM Address set: address $40 (2nd line)
start <= '1'; -- Start LCD sequence
rs <= '0';
state <= crlf2;
end if;
when crlf2 => if (ready = '0') then -- Wait for LCD sequence started
start <= '0'; -- Make sure sequence not automatically restarted
state <= text3;
text_index <= ttextlength'HIGH;
end if;
when text3 => if (ready = '1') then -- Wait for LCD ready to accept command
data <= line2(text_index);
text_index <= text_index - 1;
start <= '1'; -- Start LCD sequence
rs <= '1';
state <= text4;
end if;
when text4 => 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 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
state <= crlf5;
else
state <= idle;
end if;
end if;
when crlf3 => if (ready = '1') then -- Wait for LCD ready to accept command
data <= x"80"; -- DDRAM Address set: address $00 (1st line)
start <= '1'; -- Start LCD sequence
rs <= '0';
state <= crlf4;
end if;
when crlf4 => if (ready = '0') then -- Wait for LCD sequence started
start <= '0'; -- Make sure sequence not automatically restarted
state <= press1;
text_index <= ttextlength'HIGH;
end if;
when press1 => if (ready = '1') then -- Wait for LCD ready to accept command
data <= line3(text_index);
text_index <= text_index - 1;
start <= '1'; -- Start LCD sequence
rs <= '1';
state <= press2;
end if;
when press2 => 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 <= 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 -- Wait for LCD ready to accept command
data <= x"80"; -- DDRAM Address set: address $00 (1st line)
start <= '1'; -- Start LCD sequence
rs <= '0';
state <= crlf6;
end if;
when crlf6 => if (ready = '0') then -- Wait for LCD sequence started
start <= '0'; -- Make sure sequence not automatically restarted
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 => state <= wait1;
end case;
end if;
end if;
end process;
rst <= not PUSH_RESET;
P1_LIO_A09 <= clk_out;
P1_LIO_A13 <= clk_1ms;
P1_LIO_A15 <= clk_02ms;
PIEZO <= (clk_1ms and push1_d) or (clk_02ms and push2_d);
end LCD_CONTROLLER;
--{******************************************************************************}
--{ FileName............: Lcd_controller.vhd
--{ Project.............: FPGA
--{------------------------------------------------------------------------------}
--{
--{ Component for controlling a Seiko KS0066 based character LCD (write only)
--{
--{ The LCD has the following connections:
--{ DATAx_PORT Databus bits 0..7
--{ E_PORT Enable
--{ RS_PORT Register select
--{
--{ Timing issues (writing):
--{ E Cycle time : min 500 ns
--{ Pulse width : min 230 ns (high level)
--{ Rise/fall time: max 20 ns
--{ RS Setup time : min 40 ns before rising edge E
--{ Hold time : min 10 ns after falling edge E
--{ DBx Setup time : min 80 ns before falling edge E
--{ data is clocked in at falling edge of E
--{ Hold time : min 10 ns after falling edge E
--{ After power up a 15 ms delay is required
--{
--{ A LCD command takes some time to complete, depending on the type of command.
--{ Typically commands are executed in 40 us. Others can take up to 1.7 ms
--{------------------------------------------------------------------------------}
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
--{------------------------------------------------------------------------------}
--{ Params : <RST> Reset
--{ <CLK> Input clock (must be clock with cycle time close to 250 ns)
--{ <START> Start sequence when '1'
--{ Only validated when <READY>
--{ Note that the caller must remove the signal after
--{ <READY> becomes false, otherwise the sequence will
--{ be repeated once it is done
--{ <E> Enable signal
--{ <RW> R/W signal
--{ <RS> Register selection
--{ Latched when sequence starts
--{ <DATA> Data
--{ Latched when sequence starts
--{ <E_PORT> Enable signal port
--{ <RS_PORT> RS port
--{ <DATAx_PORT> Data bit ports
--{ <READY> Ready status (ready to start a new sequecne)
--{ Descript: LCD component (based on KS0066 chipset), write only
--{------------------------------------------------------------------------------}
entity LCD_CONTROLLER is
port(
RST : in std_logic; -- Reset
CLK : in std_logic; -- Clock (>= 250 ns cycle time)
START : in std_logic; -- Start flag
RS : in std_logic; -- Register select
DATA : in std_logic_vector (7 downto 0); -- Data
E_PORT : out std_logic; -- Enable signal port
RS_PORT : out std_logic; -- Register select port
DATA_PORT : out std_logic_vector (7 downto 0); -- Data port
READY : out std_logic -- Ready flag
);
end LCD_CONTROLLER;
--{------------------------------------------------------------------------------}
--{ Architecture
--{------------------------------------------------------------------------------}
architecture LCD_CONTROLLER of LCD_CONTROLLER is
constant STARTDELAY : natural := 60000; -- Startup delay 15 ms (based on 250 ns clock)
constant COMPLETEDELAY: natural := 7200; -- Command completion delay 1.8 ms (based on 250 ns clock)
type state_LCD is (wait1, wait2, idle, set_rs, set_e_h, set_e_l, execw);
signal state_now : state_lcd; -- Current state
signal state_next: state_lcd; -- Next state
signal e_next : std_logic; -- Next E to write (to be registered)
signal e_reg : std_logic; -- Registered E (to be written)
signal rs_next : std_logic; -- Next RS to write (to be registered)
signal rs_reg : std_logic; -- Registered RS (to be written)
signal data_next : std_logic_vector(7 downto 0); -- Next data to write (to be registered)
signal data_reg : std_logic_vector(7 downto 0); -- Registered data (to be written)
signal ready_next: std_logic; -- Next READY to write (to be registered)
signal ready_reg : std_logic; -- Registered READY (to be written)
signal delay_reg : integer range 0 to STARTDELAY; -- Delay counter (for start next state)
signal delay_next: integer range 0 to STARTDELAY; -- Delay counter (for start next state)
begin
--{------------------------------------------------------------------------------}
--{ Params : <CLK> Clock
--{ <RST> Reset
--{ Descript: State machine: State register
--{ The state register is updated
--{ Using synchronuous reset
--{------------------------------------------------------------------------------}
process (CLK, RST)
begin
if (rising_edge(CLK)) then
if (RST = '1') then
delay_reg <= 0;
else
if (delay_reg = 0) then
state_now <= state_next;
delay_reg <= delay_next;
else
delay_reg <= delay_reg - 1;
end if;
end if;
end if;
end process;
--{------------------------------------------------------------------------------}
--{ Params : <CLK> Clock
--{ Descript: State machine: Output buffer
--{ The output registers are updated
--{------------------------------------------------------------------------------}
process (CLK)
begin
if (rising_edge(CLK)) then
ready_reg <= ready_next; -- Register READY output
data_reg <= data_next; -- Register data output
rs_reg <= rs_next; -- Register RS output
e_reg <= e_next; -- Register E output
end if;
end process;
--{------------------------------------------------------------------------------}
--{ Params : <START> Start flag
--{ <RST> Reset
--{ <state_now> Current state
--{ Descript: State machine: Next state logic
--{ Notes : <delay_next> is the delay after the -next- state has been executed
--{ and must be reset
--{------------------------------------------------------------------------------}
process (START, RST, state_now)
begin
if (RST = '1') then
ready_next <= '0';
e_next <= '0';
rs_next <= '0';
data_next <= x"00";
delay_next <= 0;
state_next <= wait1;
else
case state_now is
when wait1 => ready_next <= '0';
e_next <= '0';
rs_next <= rs_reg;
data_next <= data_reg;
delay_next <= STARTDELAY; -- Delay active after -next- state executes!
state_next <= wait2;
when wait2 => ready_next <= ready_reg;
e_next <= e_reg;
rs_next <= rs_reg;
data_next <= data_reg;
delay_next <= 0;
state_next <= idle; -- STARTDELAY activated here
when idle => ready_next <= '1'; -- Idle == ready == set ready flag
e_next <= e_reg;
rs_next <= rs_reg;
data_next <= data_reg;
delay_next <= delay_reg;
if (START = '1') then
state_next <= set_rs;
else
state_next <= state_now;
end if;
when set_rs => ready_next <= '0'; -- Sequence will start == reset ready flag
e_next <= e_reg;
rs_next <= RS;
data_next <= data_reg;
delay_next <= delay_reg;
state_next <= set_e_h;
when set_e_h => ready_next <= ready_reg;
e_next <= '1';
rs_next <= rs_reg;
data_next <= DATA;
delay_next <= delay_reg;
state_next <= set_e_l;
when set_e_l => ready_next <= ready_reg;
e_next <= '0';
rs_next <= rs_reg;
data_next <= data_reg;
delay_next <= COMPLETEDELAY; -- Completion of command delay
state_next <= execw;
when execw => ready_next <= ready_reg;
e_next <= e_reg;
rs_next <= rs_reg;
data_next <= data_reg;
delay_next <= 0;
state_next <= idle; -- COMPLETEDELAY activated here
when others => ready_next <= ready_reg;
e_next <= e_reg;
rs_next <= rs_reg;
data_next <= data_reg;
delay_next <= delay_reg;
state_next <= wait1;
end case;
end if;
end process;
--{------------------------------------------------------------------------------}
--{ Descript: Output
--{ The actual outputs are set
--{------------------------------------------------------------------------------}
READY <= ready_reg;
E_PORT <= e_reg;
RS_PORT <= rs_reg;
DATA_PORT <= data_reg;
end LCD_CONTROLLER;
--{******************************************************************************}
--{ FileName............: Clock_div.vhd
--{ Project.............: FPGA
--{------------------------------------------------------------------------------}
--{
--{ Component for dividing a clock
--{------------------------------------------------------------------------------}
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--{------------------------------------------------------------------------------}
--{ Params : <CLK_TIMING_IN_NS> Speed (in ns) of input clock
--{ <CLK_TIMING_OUT_NS> Speed (in ns) of required output clock
--{ <CLK_IN> Input clock
--{ <CLK_OUT> Output clock
--{ Descript: Clock divider component
--{------------------------------------------------------------------------------}
entity CLOCK_DIV is
generic(
CLK_TIMING_IN_NS : natural; -- Input clock cycle time (in ns)
CLK_TIMING_OUT_NS: natural -- Input clock cycle time (in ns)
-- Should be multiple of CLK_TIMING_IN_NS otherwise actual timing is slightly less
);
port(
CLK_IN : in std_logic; -- Input clock
CLK_OUT: out std_logic -- Output clock
);
end CLOCK_DIV;
--{------------------------------------------------------------------------------}
--{ Architecture
--{------------------------------------------------------------------------------}
architecture CLOCK_DIV of CLOCK_DIV is
constant COUNTER_LOAD: natural := (CLK_TIMING_OUT_NS / CLK_TIMING_IN_NS / 2) - 1; -- Required counts of the input clock to run at the required output speed
signal counter: integer range 0 to COUNTER_LOAD; -- Counter (clock division)
signal toggle : std_logic := '0'; -- Toggle bit
begin
--{------------------------------------------------------------------------------}
--{ Params : <CLK_IN> Clock
--{ Descript: Countdown and reload counter and toggle when counted down
--{------------------------------------------------------------------------------}
process (CLK_IN)
begin
if (rising_edge(CLK_IN)) then
if (counter = 0) then
counter <= COUNTER_LOAD;
toggle <= not toggle;
CLK_OUT <= toggle;
else
counter <= counter - 1;
end if;
end if;
end process;
end CLOCK_DIV;
how to program a lcd inverter with sch?
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?