Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VHDL sources for LCD controller continuously displaying the contents of small memory (or block of registers)

4 views
Skip to first unread message

wzab

unread,
Apr 17, 2009, 6:20:41 PM4/17/09
to
Archive-name: stack-fsm
Submitted-by: wz...@ise.pw.edu.pl

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.6.3).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh08043
# Made on 2009-04-18 00:15 CEST by <wzab@wzab>.
# Source directory was `/tmp/LCD'.
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 10425 -rw-r--r-- lcd.vhd
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir ;;
esac
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'

else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and'
${echo} 'installing GNU `touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir}
then : ; else ${echo} 'lock directory '${lock_dir}' exists'
exit 1
fi
if mkdir ${lock_dir}
then ${echo} 'x - created lock directory `'${lock_dir}\''.'
else ${echo} 'x - failed to create lock directory `'${lock_dir}\''.'
exit 1
fi
# ============= lcd.vhd ==============
if test -f 'lcd.vhd' && test "$first_param" != -c; then
${echo} 'x -SKIPPING lcd.vhd (file already exists)'
else
${echo} 'x - extracting lcd.vhd (text)'
sed 's/^X//' << 'SHAR_EOF' > 'lcd.vhd' &&
-------------------------------------------------------------------------------
-- Title : LCD controller for Spartan 3E Starter Kit
-- Project :
-------------------------------------------------------------------------------
-- File : lcd.vhd
-- Author : Wojciech M. Zabolotny <wz...@ise.pw.edu.pl>
-- Company :
-- Created : 2007-12-31
-- Last update: 2009-04-18
-- Platform :
-- Standard : VHDL
-------------------------------------------------------------------------------
-- Description:
-- This is implementation of a simple LCD controller working with the
-- LCD display based on HD44780 or compatible chip
-- The controller performs the initialization of the display,
-- And then continuously updates the display with the data read
-- from the external "display memory", connected via busses
-- lcd_dta and lcd_addr
-- The address lcd_addr is set 41us before accessing the data,
-- so you can use even very slow implementation of the "display memory"
-- Please note, that you HAVE to set the T_CLK constant correctly
-- to assure the proper timing!
--
--
-- The design is a sample implementation of state machine
-- with "state stack", which allows you to implement often used
-- sequences of states as "subroutines"
-------------------------------------------------------------------------------
-- Copyright (c) 2007
-- This is public domain code!!!
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2007-12-31 1.0 wzab Created
-------------------------------------------------------------------------------
X
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
X
entity lcd_test is
X
X port (
X lcd : out std_logic_vector(7 downto 4); -- LCD data lines
X lcd_rs : out std_logic; -- LCD controller RS line
X lcd_rw : out std_logic; -- LCD controller RW line
X lcd_e : out std_logic; -- LCD controller E line
X lcd_dta : in std_logic_vector(7 downto 0); -- display memory
data output
X lcd_addr : out integer range 0 to 31; -- display memory address lines
X sys_clk : in std_logic; -- system clock
X sys_nrst : in std_logic); -- system reset, active LOW
X
end lcd_test;
X
architecture beh of lcd_test is
X
X constant T_CLK : integer := 20; -- Clock period in ns
X type T_LCD_STATE is (L_START, L_WRITE, L_DELAY, L_INIT0,
X L_INIT1, L_INIT2, L_INIT3, L_INIT4, L_INIT5,
L_INIT6, L_INIT7,
X L_INIT8, L_INIT9, L_INIT10, L_INIT11, L_INIT12,
L_INIT13, L_INIT14, L_INIT15,
X L_INIT16, L_INIT17, L_INIT18, L_INIT19,
L_INIT20, L_INIT21, L_INIT22,
X L_WRITED, L_WRITED_1, L_WRITED_2, L_WRITED_3,
L_WRITED_4,
X L_WRITE4, L_WRITE4_1, L_WRITE4_2, L_WRITE4_3,
X L_WRITE8, L_WRITE8_1, L_WRITE8_2, L_ROW,
L_ROW_2, L_ROW_3, L_ROW_4, L_ROW_5);
X constant STACK_DEPTH : integer := 7;
X type T_STACK is array (STACK_DEPTH-1 downto 0) of T_LCD_STATE;
X signal stack : T_STACK;
X signal stack_ptr : integer range 0 to STACK_DEPTH := 0;
X signal stack_err : boolean := false;
X signal lcd_state : T_LCD_STATE := L_START;
X signal lcd_cmd : std_logic_vector(7 downto 0);
X signal cnt_del : integer := 0;
X signal sys_rst : std_logic;
X
X signal lcd_cnt_row : integer range 0 to 1;
X signal lcd_cnt_col : integer range 0 to 15;
X
X signal main_clk, main_rst, main_rst0 : std_logic := '0';
X
X
begin -- beh
X
X sys_rst <= not sys_nrst;
X main_clk <= sys_clk;
X
X lcd_addr <= 16*lcd_cnt_row+lcd_cnt_col;
X
X process (main_clk, sys_rst)
X begin -- process
X if sys_rst = '1' then -- asynchronous reset (active low)
X main_rst <= '0';
X main_rst0 <= '0';
X elsif main_clk'event and main_clk = '1' then -- rising clock edge
X main_rst0 <= '1';
X main_rst <= main_rst0;
X end if;
X end process;
X
X process (main_clk, sys_rst)
X
X procedure STK_PUSH (
X constant next_state : in T_LCD_STATE) is
X begin -- STK_PUSH
X if stack_ptr < STACK_DEPTH then
X stack(stack_ptr) <= next_state;
X stack_ptr <= stack_ptr + 1;
X else
X stack_err <= true;
X end if;
X end STK_PUSH;
X
X procedure STK_RET is
X begin -- stk_pop
X if stack_ptr > 0 then
X lcd_state <= stack(stack_ptr - 1);
X stack_ptr <= stack_ptr - 1;
X else
X stack_err <= true;
X end if;
X end STK_RET;
X
X procedure STK_CALL (
X constant called_state, ret_state : in T_LCD_STATE) is
X begin -- STK_CALL
X STK_PUSH(ret_state);
X lcd_state <= called_state;
X end STK_CALL;
X
X procedure STK_JMP (
X constant called_state : in T_LCD_STATE) is
X begin -- STK_CALL
X lcd_state <= called_state;
X end STK_JMP;
X
X procedure STK_DEL (
X constant delay : in integer;
X constant ret_state : in T_LCD_STATE) is
X begin -- stk_pop
X cnt_del <= (delay+T_CLK-1) / T_CLK;
X STK_CALL(L_DELAY, ret_state);
X end STK_DEL;
X
X procedure STK_WRITE4 (
X constant value4 : in integer range 0 to 15;
X constant ret_state : in T_LCD_STATE) is
X begin -- STK_WRITE4
X lcd_rs <= '0';
X lcd_cmd(7 downto 4) <= std_logic_vector(to_unsigned(value4, 4));
X STK_CALL(L_WRITE4, ret_state);
X end STK_WRITE4;
X
X procedure STK_WRITE8 (
X constant value8 : in integer range 0 to 255;
X constant ret_state : in T_LCD_STATE) is
X begin -- STK_WRITE8
X lcd_rs <= '0';
X lcd_cmd(7 downto 0) <= std_logic_vector(to_unsigned(value8, 8));
X STK_CALL(L_WRITE8, ret_state);
X end STK_WRITE8;
X
X procedure STK_WRITED (
X constant value8 : in integer range 0 to 255;
X constant ret_state : in T_LCD_STATE) is
X begin -- STK_WRITED
X lcd_rs <= '1';
X lcd_cmd(7 downto 0) <= std_logic_vector(to_unsigned(value8, 8));
X STK_CALL(L_WRITED, ret_state);
X end STK_WRITED;
X
X procedure STK_ROW (
X constant row : in integer range 0 to 1;
X constant ret_state : in T_LCD_STATE) is
X begin -- STK_WRITED
X lcd_cnt_row <= row;
X lcd_cnt_col <= 0;
X STK_CALL(L_ROW, ret_state);
X end STK_ROW;
X
X procedure INIT is
X begin -- INIT
X lcd_rw <= '0';
X lcd_e <= '0';
X lcd <= (others => '0');
X lcd_state <= L_START;
X stack_err <= false;
X stack_ptr <= 0;
X cnt_del <= 0;
X end INIT;
X
X begin -- process
X if sys_rst = '1' then -- asynchronous reset (active low)
X INIT;
X elsif main_clk'event and main_clk = '1' then -- rising clock edge
X if main_rst = '0' then
X INIT;
X else
X case lcd_state is
X when L_START =>
X STK_DEL(16_000_000, L_INIT0);
X -- Subroutine DELAY
X when L_INIT0 =>
X STK_WRITE4(16#3#, L_INIT1);
X when L_INIT1 =>
X STK_DEL(4_200_000, L_INIT2);
X when L_INIT2 =>
X STK_WRITE4(16#3#, L_INIT3);
X when L_INIT3 =>
X STK_DEL(110_000, L_INIT4);
X when L_INIT4 =>
X STK_WRITE4(16#3#, L_INIT5);
X when L_INIT5 =>
X STK_DEL(41_000, L_INIT6);
X when L_INIT6 =>
X STK_WRITE4(16#2#, L_INIT7);
X when L_INIT7 =>
X STK_DEL(41_000, L_INIT8);
X when L_INIT8 =>
X STK_WRITE8(16#28#, L_INIT9);
X when L_INIT9 =>
X STK_DEL(41_000, L_INIT10);
X when L_INIT10 =>
X STK_WRITE8(16#06#, L_INIT11);
X when L_INIT11 =>
X STK_DEL(41_000, L_INIT12);
X when L_INIT12 =>
X STK_WRITE8(16#0C#, L_INIT13);
X when L_INIT13 =>
X STK_DEL(41_000, L_INIT14);
X when L_INIT14 =>
X STK_WRITE8(16#01#, L_INIT15);
X when L_INIT15 =>
X STK_DEL(1_750_000, L_INIT16);
X -- Here we start the normal operation of the display
X -- First set the cursor to the first row, first column
X when L_INIT16 =>
X STK_ROW(0, L_INIT17);
X when L_INIT17 =>
X STK_ROW(1, L_INIT16);
X -- We stay forever in the two above states
X -- Subroutine delay
X when L_DELAY =>
X if cnt_del = 0 then
X STK_RET;
X else
X cnt_del <= cnt_del-1;
X end if;
X -- Subroutine ROW
X when L_ROW =>
X STK_WRITE8(16#80#+lcd_cnt_row*16#40#, L_ROW_2);
X when L_ROW_2 =>
X STK_DEL(41_000, L_ROW_3);
X when L_ROW_3 =>
X STK_WRITED(to_integer(unsigned(lcd_dta)), L_ROW_4);
X when L_ROW_4 =>
X if lcd_cnt_col = 15 then
X STK_DEL(41_000, L_ROW_5);
X else
X lcd_cnt_col <= lcd_cnt_col+1;
X STK_DEL(41_000, L_ROW_3); -- after delay go to
L_ROW_3
X end if;
X when L_ROW_5 =>
X STK_RET;
X -- Subroutine WRITE4
X when L_WRITE4 =>
X lcd_rw <= '0';
X lcd(7 downto 4) <= lcd_cmd(7 downto 4);
X STK_DEL(60, L_WRITE4_1);
X when L_WRITE4_1 =>
X lcd_e <= '1';
X STK_DEL(250, L_WRITE4_2);
X when L_WRITE4_2 =>
X lcd_e <= '0';
X STK_DEL(20, L_WRITE4_3);
X when L_WRITE4_3 =>
X STK_RET;
X -- Subroutine WRITE8
X when L_WRITE8 =>
X STK_CALL(L_WRITE4, L_WRITE8_1);
X when L_WRITE8_1 =>
X STK_DEL(1_000, L_WRITE8_2);
X when L_WRITE8_2 =>
X lcd_cmd(7 downto 4) <= lcd_cmd(3 downto 0);
X STK_JMP(L_WRITE4);
X -- Subroutine WRITED
X when L_WRITED =>
X STK_CALL(L_WRITE4, L_WRITED_1);
X when L_WRITED_1 =>
X STK_DEL(1_000, L_WRITED_2);
X when L_WRITED_2 =>
X lcd_cmd(7 downto 4) <= lcd_cmd(3 downto 0);
X STK_CALL(L_WRITE4, L_WRITED_3);
X when L_WRITED_3 =>
X STK_DEL(41_000, L_WRITED_4);
X when L_WRITED_4 =>
X --lcd_rs <= '0';
X STK_RET;
X when others =>
X STK_JMP(L_INIT0);
X end case;
X end if;
X end if;
X end process;
X
end beh;
SHAR_EOF
(set 20 09 04 18 00 05 22 'lcd.vhd'; eval "$shar_touch") &&
chmod 0644 'lcd.vhd'
if test $? -ne 0
then ${echo} 'restore of lcd.vhd failed'
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'lcd.vhd: MD5 check failed'
) << SHAR_EOF
d032ae3443d35335556f278079b83bdd lcd.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'lcd.vhd'` -ne 10425 && \
${echo} 'restoration warning: size of lcd.vhd is not 10425'
fi
fi
if rm -fr ${lock_dir}
then ${echo} 'x - removed lock directory `'${lock_dir}\''.'
else ${echo} 'x - failed to remove lock directory `'${lock_dir}\''.'
exit 1
fi
exit 0

wzab

unread,
Apr 17, 2009, 6:28:25 PM4/17/09
to
0 new messages