URL
https://opencores.org/ocsvn/hd44780_driver/hd44780_driver/trunk
Subversion Repositories hd44780_driver
Compare Revisions
- This comparison shows the changes necessary to convert path
/hd44780_driver/trunk
- from Rev 6 to Rev 5
- ↔ Reverse comparison
Rev 6 → Rev 5
/trunk/lcd_driver_hd44780.qpf
0,0 → 1,30
# -------------------------------------------------------------------------- # |
# |
# Copyright (C) 1991-2011 Altera Corporation |
# Your use of Altera Corporation's design tools, logic functions |
# and other software and tools, and its AMPP partner logic |
# functions, and any output files from any of the foregoing |
# (including device programming or simulation files), and any |
# associated documentation or information are expressly subject |
# to the terms and conditions of the Altera Program License |
# Subscription Agreement, Altera MegaCore Function License |
# Agreement, or other applicable license agreement, including, |
# without limitation, that your use is for the sole purpose of |
# programming logic devices manufactured by Altera and sold by |
# Altera or its authorized distributors. Please refer to the |
# applicable agreement for further details. |
# |
# -------------------------------------------------------------------------- # |
# |
# Quartus II 32-bit |
# Version 11.1 Build 216 11/23/2011 Service Pack 1 SJ Web Edition |
# Date created = 09:17:30 September 29, 2012 |
# |
# -------------------------------------------------------------------------- # |
|
QUARTUS_VERSION = "11.1" |
DATE = "09:17:30 September 29, 2012" |
|
# Revisions |
|
PROJECT_REVISION = "lcd_driver_hd44780" |
/trunk/lcd_driver_hd44780_module.vhd
0,0 → 1,500
+-- blink_on:
+-- true to let the cursor blink, false for no blink (just a underscore)
+-- use_bf: true if Busy Flag reading is to be used, false for no BF reading
+--
+-- Note: it's not possible to write command codes to the display.
+--
+-- Changes to v1.0: LCD_E is renamed to LCD_EN
+-- LCD_DB is renamed to LCD_DATA
+-- busy is now registered
+-- removed hardware simulation architecture
+--
+-- Changes to v1.1: added timing generics for better steering of the E pulse cycle
+-- implemented cursor on/off/blink with generic parameters
+--
+-- Changes to v1.2: added Busy Flag reading mode, selectable at instantiation time
+-- LCD_EN changes back to LCD_E
+-- LCD_DATA changed back to LCD_DB
+--
+-- To do: use 4-bit mode or 8-bit mode at instantiation time
+--
+
+-- The libraries to use.
+library ieee;
+use ieee.std_logic_1164.all;
+
+-- The entity of the LCD Driver Module.
+entity lcd_driver_hd44780_module is
+ generic (freq : integer := 50000000;
+ areset_pol : std_logic := '1';
+ time_init1 : time := 40 ms;
+ time_init2 : time := 4100 us;
+ time_init3 : time := 100 us;
+ time_tas : time := 60 ns;
+ time_cycle_e : time := 1000 ns;
+ time_pweh : time := 500 ns;
+ time_no_bf : time := 2 ms;
+ cursor_on : boolean := false;
+ blink_on : boolean := false;
+ use_bf : boolean := true
+ );
+ port (clk : in std_logic;
+ areset : in std_logic;
+ -- User site
+ init : in std_logic;
+ data : in std_logic_vector(7 downto 0);
+ wr : in std_logic;
+ cls : in std_logic;
+ home : in std_logic;
+ goto10 : in std_logic;
+ goto20 : in std_logic;
+ goto30 : in std_logic;
+ busy : out std_logic;
+ -- LCD side
+ LCD_E : out std_logic;
+ LCD_RS : out std_logic;
+ LCD_RW : out std_logic;
+ LCD_DB : inout std_logic_vector(7 downto 0)
+ );
+end entity lcd_driver_hd44780_module;
+
+-- This architecture drives the LCD.
+architecture hardware_driver of lcd_driver_hd44780_module is
+
+-- Delays... Please note that if the frequency is (too) low,
+-- some of the delays will 0. The code will take care of that.
+-- Converting time to integer is problematic. Please note the use of
+-- the simulator time step in the calculations.
+-- The simulator timestep
+constant simulator_timestep : time := 1 ns;
+-- Number of simulator timesteps per second.
+constant sim_steps_per_sec : real := real(1 sec/simulator_timestep);
+
+constant delay_init1 : integer := integer( real(freq) * real(time_init1/simulator_timestep) / sim_steps_per_sec);
+constant delay_init2 : integer := integer( real(freq) * real(time_init2/simulator_timestep) / sim_steps_per_sec);
+constant delay_init3 : integer := integer( real(freq) * real(time_init3/simulator_timestep) / sim_steps_per_sec);
+constant delay_tas : integer := integer( real(freq) * real(time_tas/simulator_timestep) / sim_steps_per_sec);
+constant delay_cycle_e : integer := integer( real(freq) * real(time_cycle_e/simulator_timestep) / sim_steps_per_sec);
+constant delay_pweh : integer := integer( real(freq) * real(time_pweh/simulator_timestep) / sim_steps_per_sec);
+constant delay_no_bf : integer := integer( real(freq) * real(time_no_bf/simulator_timestep) / sim_steps_per_sec);
+
+-- The next statements do work in Quartus but not in (32 bit) ModelSim...
+--constant delay_init1 : integer := integer(real(freq)*real(time'pos(time_init1)) / real(time'pos(1 sec)));
+--constant delay_init2 : integer := integer(real(freq)*real(time'pos(time_init2)) / real(time'pos(1 sec)));
+--constant delay_init3 : integer := integer(real(freq)*real(time'pos(time_init3)) / real(time'pos(1 sec)));
+--constant delay_tas : integer := integer(real(freq)*real(time'pos(time_tas)) / real(time'pos(1 sec)));
+--constant delay_cycle_e : integer := integer(real(freq)*real(time'pos(time_cycle_e)) / real(time'pos(1 sec)));
+--constant delay_pweh : integer := integer(real(freq)*real(time'pos(time_pweh)) / real(time'pos(1 sec)));
+--constant delay_no_bf : integer := integer(real(freq)*real(time'pos(time_no_bf)) / real(time'pos(1 sec)));
+
+-- Time the E signal must be low following E high
+constant delay_pwel : integer := delay_cycle_e-delay_pweh;
+
+-- Counter for the delays. Timer would be a better choice.
+-- Range should be to the longest delay.
+signal delay_counter : integer range 0 to delay_init1;
+
+-- Should we use Busy Flag reading?
+signal use_bf_int : std_logic;
+
+-- The states of the state machine.
+type state_type is (reset, command_init, command_init_1, command_init_2, command_init_3,
+ command_init_4, command_init_5, command_init_6, command_init_7, command_init_8,
+ command_init_9, command_init_10, command_init_11, command_init12,
+ wait_for_command,
+ command_cls, command_home,
+ command_goto10, command_goto20, command_goto30, command_wr,
+ pulse_e, pulse_e_1, pulse_e_2, pulse_e_3, pulse_e_4,
+ pulse_busy_flag, pulse_busy_flag_1, pulse_busy_flag_2, pulse_busy_flag_3,
+ pulse_busy_flag_4, pulse_busy_flag_5);
+
+
+-- The current state and one for the return state (to facilitate return to the caller).
+signal current_state, return_state : state_type;
+begin
+
+ -- The state machine ;-)
+ nsl_state: process (clk, areset) is
+ -- Function to translate a boolean to std_logic
+ function bool_to_stdlogic(l: boolean) return std_logic is
+ begin
+ if l then
+ return('1');
+ else
+ return('0');
+ end if;
+ end function bool_to_stdlogic;
+ begin
+ if (areset = '1' and areset_pol = '1') or (areset = '0' and areset_pol = '0') then
+ current_state <= reset;
+ delay_counter <= 0;
+ busy <= '1';
+ LCD_DB <= (others => 'Z');
+ LCD_E <= '0';
+ LCD_RS <= '0';
+ LCD_RW <= '0';
+ use_bf_int <= '0';
+ elsif rising_edge(clk) then
+ -- Default is busy
+ busy <= '1';
+ -- Default values of the LCD side
+ LCD_E <= '0';
+ LCD_RW <= '0';
+ case current_state is
+ when reset|command_init =>
+ -- The logic is reset. Start initialization routine.
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ use_bf_int <= '0';
+ delay_counter <= delay_init1;
+ current_state <= command_init_1;
+ when command_init_1 =>
+ -- Wait until Vcc > 4.5 V...
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ use_bf_int <= '0';
+ -- If done write 0x30 to the LCD
+ if delay_counter = 0 or delay_counter = 1 then
+ LCD_DB <= "00110000"; -- 0x30
+ current_state <= pulse_e;
+ return_state <= command_init_2;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when command_init_2 =>
+ -- Next, set up wait for 4.1 ms
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ use_bf_int <= '0';
+ delay_counter <= delay_init2;
+ current_state <= command_init_3;
+ when command_init_3 =>
+ -- Wait...
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ use_bf_int <= '0';
+ -- If done write 0x30 to the LCD
+ if delay_counter = 0 or delay_counter = 1 then
+ LCD_DB <= "00110000"; -- 0x30
+ current_state <= pulse_e;
+ return_state <= command_init_4;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when command_init_4 =>
+ -- Next, set up wait for 100 us
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ use_bf_int <= '0';
+ delay_counter <= delay_init3;
+ current_state <= command_init_5;
+ when command_init_5 =>
+ -- Wait...
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ use_bf_int <= '0';
+ -- If done write 0x30 to the LCD
+ if delay_counter = 0 or delay_counter = 1 then
+ LCD_DB <= "00110000"; -- 0x30
+ current_state <= pulse_e;
+ return_state <= command_init_6;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when command_init_6 =>
+ -- Power up is now done, so let's enter some reasonable values...
+ LCD_DB <= "00110000";
+ LCD_RS <= '0';
+ use_bf_int <= bool_to_stdlogic(use_bf);
+ current_state <= pulse_e;
+ return_state <= command_init_7;
+ when command_init_7 =>
+ -- 8-bit bus, 2(?) lines, 5x7 characters
+ LCD_DB <= "00111100"; -- 0x3C
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= command_init_8;
+ when command_init_8 =>
+ -- Display off
+ LCD_DB <= "00001000"; -- 0x08
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= command_init_9;
+ when command_init_9 =>
+ -- Display clear
+ LCD_DB <= "00000001"; -- 0x01
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= command_init_10;
+ when command_init_10 =>
+ -- Display on, cursor and blink...
+ LCD_DB <= "000011" & bool_to_stdlogic(cursor_on) & bool_to_stdlogic(blink_on); -- 0x0C + ...
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= command_init_11;
+ when command_init_11 =>
+ -- Mode set, increment cursor address, cursor shift
+ LCD_DB <= "00000110"; -- 0x06
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ -- The command dispatcher! This state waits for one of
+ -- the command inputs to be logic '1' and 'starts' the
+ -- accompanying routine. Note the priority encoding!
+ when wait_for_command =>
+ LCD_DB <= (others => 'Z');
+ LCD_RS <= '0';
+ busy <= '0';
+ if init = '1' then
+ busy <= '1';
+ current_state <= command_init;
+ elsif cls = '1' then
+ busy <= '1';
+ current_state <= command_cls;
+ elsif home = '1' then
+ busy <= '1';
+ current_state <= command_home;
+ elsif goto10 = '1' then
+ busy <= '1';
+ current_state <= command_goto10;
+ elsif goto20 = '1' then
+ busy <= '1';
+ current_state <= command_goto20;
+ elsif goto30 = '1' then
+ busy <= '1';
+ current_state <= command_goto30;
+ elsif wr = '1' then
+ -- Read in data! Do NOT forget that here!
+ LCD_DB <= data;
+ busy <= '1';
+ current_state <= command_wr;
+ end if;
+
+ when command_cls =>
+ -- Display clear
+ LCD_DB <= "00000001";
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ when command_home =>
+ -- Cursor home
+ LCD_DB <= "00000010";
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ when command_goto10 =>
+ -- Cursor to beginning of line 2nd line...
+ LCD_DB <= "11000000"; --0x80+0x40;
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ when command_goto20 =>
+ -- Cursor to beginning of line 3rd line...
+ LCD_DB <= "10010000"; --0x80+0x10;
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ when command_goto30 =>
+ -- Cursor to beginning of line 4th line...
+ LCD_DB <= "11010000"; --0x80+0x50;
+ LCD_RS <= '0';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ when command_wr =>
+ -- Start character write cycle
+ -- Do NOT set data here!
+ LCD_RS <= '1';
+ current_state <= pulse_e;
+ return_state <= wait_for_command;
+
+ -- --
+ -- Provide E strobing for data transfer.
+ -- Writes data byte to the LCD.
+ -- Please note, DATA and RS are set by the caller!
+ when pulse_e =>
+ -- wait 60 ns before E -> 1 (tAS)
+ delay_counter <= delay_tas;
+ current_state <= pulse_e_1;
+ when pulse_e_1 =>
+ if delay_counter = 0 or delay_counter = 1 then
+ -- timer set: E = 1 for 500 ns (PWeh)
+ delay_counter <= delay_pweh;
+ current_state <= pulse_e_2;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when pulse_e_2 =>
+ LCD_E <= '1';
+ if delay_counter = 0 or delay_counter = 1 then
+ -- timer set: E = 0 for 500 ns (tCycleE-PWeh)
+ delay_counter <= delay_pwel;
+ current_state <= pulse_e_3;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when pulse_e_3 =>
+ LCD_E <= '0';
+ -- Command completion, check for use busy flag
+ if delay_counter = 0 or delay_counter = 1 then
+ -- If no busy flag used, wait for a amount of time.
+ if use_bf_int = '0' then
+ delay_counter <= delay_no_bf;
+ current_state <= pulse_e_4;
+ else -- BF used
+ current_state <= pulse_busy_flag;
+ end if;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when pulse_e_4 =>
+ -- Wait for the delay to finsh and then return to the caller.
+ if delay_counter = 0 or delay_counter = 1 then
+ current_state <= return_state;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+
+ -- Let's read the busy flag, see if the module is busy...
+ when pulse_busy_flag =>
+ LCD_DB <= (others => 'Z');
+ LCD_RW <= '1';
+ LCD_RS <= '0';
+ -- wait 60 ns before E -> 1 (tAS)
+ delay_counter <= delay_tas;
+ current_state <= pulse_busy_flag_1;
+ when pulse_busy_flag_1 =>
+ LCD_RW <= '1';
+ if delay_counter = 0 or delay_counter = 1 then
+ -- timer set: E = 1 for 500 ns (tPWeh)
+ delay_counter <= delay_pweh;
+ current_state <= pulse_busy_flag_2;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when pulse_busy_flag_2 =>
+ LCD_E <= '1';
+ LCD_RW <= '1';
+ if delay_counter = 0 or delay_counter = 1 then
+ -- timer set: E = 0 for 500 ns (tPWel)
+ delay_counter <= delay_pwel;
+ current_state <= pulse_busy_flag_3;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when pulse_busy_flag_3 =>
+ LCD_E <= '0';
+ LCD_RW <= '1';
+ if LCD_DB(7) = '0' then
+ -- operation ended
+ current_state <= pulse_busy_flag_4;
+ else
+ -- operation in progress
+ current_state <= pulse_busy_flag_5;
+ end if;
+ when pulse_busy_flag_4 =>
+ if delay_counter = 0 or delay_counter = 1 then
+ -- Operation ended, return caller
+ current_state <= return_state;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+ when pulse_busy_flag_5 =>
+ if delay_counter = 0 or delay_counter = 1 then
+ -- Operation in progress, read BF again
+ current_state <= pulse_busy_flag;
+ else
+ delay_counter <= delay_counter-1;
+ end if;
+
+ when others => null;
+ end case;
+ end if;
+
+ end process;
+
+end architecture hardware_driver;
-- Filename: lcd_driver_hd44780_module.vhd |
-- Filetype: VHDL Source Code |
-- Date: 26 oct 2012 |
-- Update: - |
-- Description: VHDL Description for driving an HD44780 based LCD driver |
-- Author: J. op den Brouw |
-- State: Demo |
-- Error: - |
-- Version: 1.2alpha |
-- Copyright: (c)2012, De Haagse Hogeschool |
|
-- This file contains a VHDL description for driving an HD44780 based LCD |
-- driver, see for a standard information of such a display: |
-- https://decibel.ni.com/content/servlet/JiveServlet/download/2741-3-3217/hd44780.pdf |
-- |
-- Currently, this driver uses the 8-bit databus mode. This is not a big problem |
-- for most FPGA's because of the numerous pins. |
-- |
-- Please note that there are a lot of almost-the-same displays available, so |
-- it's not guaranteed to work with all displays available. Also, timing may differ. |
-- |
-- This code is tested on a Terasic DE0-board with an optional |
-- LCD display. See the weblinks |
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=56&No=364 |
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=78&No=396 |
-- for more info. The display used has only two lines. |
-- |
-- This VHDL description can both be simulated and synthesized. |
-- |
-- This driver has a User Side and a LCD Side. The user is to interface at the User Side |
-- and has a number of "routines" at her disposal. The User Side implements the following |
-- inputs/routines in order of priority: |
-- |
-- Command inputs: |
-- init: a logic 1 initializes the display |
-- cls: a logic 1 clears the display (and goes to home) |
-- home: a logic 1 sets the cursor to row 0, column 0 |
-- goto10: a logic 1 sets the cursor to row 1, column 0 |
-- goto20: a logic 1 sets the cursor to row 2, column 0 |
-- goto30: a logic 1 sets the cursor to row 3, column 0 |
-- wr: a logic 1 writes a character to the display |
-- |
-- Data inputs: |
-- |
-- data: an 8-bit data to be written to the display |
-- |
-- The user has one observable output: |
-- |
-- busy: a logic 1 indicates that the driver is currently |
-- busy driving the display, a logic 0 indicates that |
-- the driver waits for the next command. |
-- |
-- The user can supply the next generics, which are processed at |
-- instantiation of the module: |
-- |
-- freq: the clock frequency at which the hardware has to run. |
-- this frequency is mandatory because of internal delays |
-- calculated, defaults to 50 MHz. |
-- areset_pol: |
-- the polarity of the reset signal, defaults to High (1) |
-- time_init1: |
-- the time to wait after Vcc > 4.5 V |
-- time_init2: |
-- the time to wait after first "contact" |
-- time_init3: |
-- the time to wait after the second contact |
-- time_tas: |
-- the RW and RS signal setup time with respect to the positive |
-- edge of the E pulse |
-- time_cycle_e: |
-- the complete cycle time |
-- time_pweh: |
-- the E pulse width high time |
-- time_no_bf: |
-- time to wait before command completion if no Busy Flag reading is done, |
-- some designs connect RW to logic 0, so reading from the LCD is not |
-- possible, saves a pin. |
-- cursor_on: |
/trunk/example_driver.vhd
0,0 → 1,277
-- Filename: example_driver.vhd |
-- Filetype: VHDL Source Code |
-- Date: 26 oct 2012 |
-- Update: - |
-- Description: VHDL Description of example driver |
-- Author: J. op den Brouw |
-- State: Demo |
-- Error: - |
-- Version: 1.1alpha |
-- Copyright: (c)2012, De Haagse Hogeschool |
|
-- This VHDL code is a example description on how to use the |
-- HD44780 LCD display driver module. It writes 4x16 characters |
-- to the display, presuming that the display has four lines. |
-- |
-- This code is tested on a Terasic DE0-board with an optional |
-- LCD display. See the weblinks |
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=56&No=364 |
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=78&No=396 |
-- for more info. The display used has only two lines. |
|
-- After a line has written completely, the cursor is moved to |
-- the beginning of the next line. After the last line is written, |
-- this code goes into hold mode. |
-- |
|
-- Libraries et al. |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
-- The entity of a Terasic DE0-board. |
entity example_driver is |
port (CLOCK_50 : in std_logic; |
BUTTON : in std_logic_vector(2 downto 0); |
SW : in std_logic_vector(9 downto 0); |
LEDG : out std_logic_vector(9 downto 0); |
HEX3_D : out std_logic_vector(6 downto 0); |
HEX2_D : out std_logic_vector(6 downto 0); |
HEX1_D : out std_logic_vector(6 downto 0); |
HEX0_D : out std_logic_vector(6 downto 0); |
HEX0_DP : out std_logic; |
HEX1_DP : out std_logic; |
HEX2_DP : out std_logic; |
HEX3_DP : out std_logic; |
-- LCD of the DE0 board |
LCD_EN : out std_logic; |
LCD_RS : out std_logic; |
LCD_RW : out std_logic; |
LCD_DATA : inout std_logic_vector(7 downto 0); |
LCD_BLON : out std_logic |
); |
|
end entity example_driver; |
|
-- The architecture! |
architecture hardware of example_driver is |
-- Component declaration of the LCD module |
component lcd_driver_hd44780_module is |
generic (freq : integer := 50000000; |
areset_pol : std_logic := '1'; |
time_init1 : time := 40 ms; |
time_init2 : time := 4100 us; |
time_init3 : time := 100 us; |
time_tas : time := 60 ns; |
time_cycle_e : time := 1000 ns; |
time_pweh : time := 500 ns; |
time_no_bf : time := 2 ms; |
cursor_on : boolean := false; |
blink_on : boolean := false; |
use_bf : boolean := true |
); |
port (clk : in std_logic; |
areset : in std_logic; |
-- User site |
init : in std_logic; |
data : in std_logic_vector(7 downto 0); |
wr : in std_logic; |
cls : in std_logic; |
home : in std_logic; |
goto10 : in std_logic; |
goto20 : in std_logic; |
goto30 : in std_logic; |
busy : out std_logic; |
-- LCD side |
LCD_E : out std_logic; |
LCD_RS : out std_logic; |
LCD_RW : out std_logic; |
LCD_DB : inout std_logic_vector(7 downto 0) |
); |
end component lcd_driver_hd44780_module; |
|
-- The system's frequency |
constant sys_freq : integer := 50000000; |
|
signal areset : std_logic; |
signal clk : std_logic; |
signal init : std_logic; |
signal data : std_logic_vector(7 downto 0); |
signal wr : std_logic; |
signal cls : std_logic; |
signal home : std_logic; |
signal goto10 : std_logic; |
signal goto20 : std_logic; |
signal goto30 : std_logic; |
signal busy : std_logic; |
|
type state_type is (reset, write_char, write_char_wait, update, update_linecount, |
update_linecount_wait, write_char_1, write_char_1_wait, |
write_char_2, write_char_2_wait, write_char_3, write_char_4, hold, |
hold2); |
signal state : state_type; |
|
-- A string of 16 characters |
subtype string16_type is string(1 to 16); |
-- An array of 4 strings of 16 characters. |
type message4x16_type is array (1 to 4) of string16_type; |
|
-- The four-line message |
constant message : message4x16_type := |
( 1 => "1Elektrotechniek", |
2 => "2 LCD HD44780 ", |
3 => "3Driver in VHDL!", |
4 => "4J. op den Brouw"); |
|
-- Counts the characters on a line. |
signal character_counter : integer range 1 to 16; |
-- Counts the lines. |
signal line_counter : integer range 1 to 4; |
|
begin |
|
-- Push buttons are active low. |
areset <= not BUTTON(0); |
|
-- The clock |
clk <= CLOCK_50; |
|
-- Use LCD module. |
lcdm : lcd_driver_hd44780_module |
generic map (freq => sys_freq, areset_pol => '1', time_cycle_e => 2000 ns, time_pweh => 500 ns, |
cursor_on => false, blink_on => false, use_bf => false) |
port map (clk => clk, areset => areset, init => init, data => data, wr => wr, cls => cls, |
home => home, goto10 => goto10, goto20 => goto20, goto30 => goto30, busy => busy, |
LCD_E => LCD_EN, LCD_RS => LCD_RS, LCD_RW => LCD_RW, LCD_DB => LCD_DATA); |
|
-- The client side |
drive: process (clk, areset) is |
variable aline : string16_type; |
begin |
if areset = '1' then |
wr <= '0'; |
init <= '0'; |
cls <= '0'; |
home <= '0'; |
goto10 <= '0'; |
goto20 <= '0'; |
goto30 <= '0'; |
LEDG(0) <= '0'; |
data <= "00000000"; |
character_counter <= 1; |
state <= reset; |
elsif rising_edge(clk) then |
wr <= '0'; |
init <= '0'; |
cls <= '0'; |
home <= '0'; |
goto10 <= '0'; |
goto20 <= '0'; |
goto30 <= '0'; |
LEDG(0) <= '0'; |
data <= "00000000"; |
case state is |
|
when reset => |
-- Wait for the LCD module ready |
if busy = '0' then |
state <= write_char; |
end if; |
-- Setup message counter, start at 1. |
character_counter <= 1; |
line_counter <= 1; |
|
when write_char => |
LEDG(0) <= '1'; |
-- Set up WRITE! |
-- Use the data from the string |
aline := message(line_counter); |
data <= std_logic_vector( to_unsigned( character'pos(aline(character_counter)),8)); |
wr <= '1'; |
state <= write_char_wait; |
|
when write_char_wait => |
-- This state is needed so that the LCD driver |
-- can process the write command. Note that data |
-- and wr are registered outputs and get their |
-- respective values while in *this* state. If you don't |
-- want this behaviour, please make your outputs |
-- non-registered. |
state <= update; |
|
when update => |
LEDG(0) <= '1'; |
-- Wait for the write complete |
if busy = '0' then |
-- If end of string, goto hold mode... |
if line_counter = 4 and character_counter = 16 then |
state <= hold; |
-- If end of line... |
elsif character_counter = 16 then |
case line_counter is |
when 1 => goto10 <= '1'; |
when 2 => goto20 <= '1'; |
when 3 => goto30 <= '1'; |
-- Never reached, but nice anyway... |
when 4 => home <= '1'; |
when others => null; |
end case; |
-- Set new values of the counters |
line_counter <= line_counter+1; |
character_counter <= 1; |
-- Goto the update state |
state <= update_linecount; |
else |
-- Not the end of a lines, update the character counter. |
character_counter <= character_counter+1; |
state <= write_char; |
end if; |
end if; |
|
when update_linecount => |
-- This state is needed so that the LCD driver |
-- can process the gotoXX command. Note that the gotoXX |
-- signals are registered outputs and get their |
-- respective values while in *this* state. If you don't |
-- want this behaviour, please make your outputs |
-- non-registered. |
state <= update_linecount_wait; |
|
when update_linecount_wait => |
-- Wait for the LCD module ready |
if busy = '0' then |
state <= write_char; |
end if; |
|
-- The "hohouwer" |
when hold => |
--state <= hold; |
state <= hold2; |
home <= '1'; |
when hold2 => |
state <= reset; |
|
when others => |
null; |
|
end case; |
end if; |
end process; |
|
-- The unused outputs... |
HEX3_D <= (others => '1'); |
HEX2_D <= (others => '1'); |
HEX1_D <= (others => '1'); |
HEX0_D <= (others => '1'); |
|
HEX3_DP <= '1'; |
HEX2_DP <= '1'; |
HEX1_DP <= '1'; |
HEX0_DP <= '1'; |
|
LEDG(9 downto 1) <= (others => '0'); |
|
-- Sadly, the LCD doesn't have a backlight... |
LCD_BLON <= '0'; |
|
end architecture hardware; |
/trunk/lcd_driver_hd44780.qsf
0,0 → 1,319
# -------------------------------------------------------------------------- # |
# |
# Copyright (C) 1991-2011 Altera Corporation |
# Your use of Altera Corporation's design tools, logic functions |
# and other software and tools, and its AMPP partner logic |
# functions, and any output files from any of the foregoing |
# (including device programming or simulation files), and any |
# associated documentation or information are expressly subject |
# to the terms and conditions of the Altera Program License |
# Subscription Agreement, Altera MegaCore Function License |
# Agreement, or other applicable license agreement, including, |
# without limitation, that your use is for the sole purpose of |
# programming logic devices manufactured by Altera and sold by |
# Altera or its authorized distributors. Please refer to the |
# applicable agreement for further details. |
# |
# -------------------------------------------------------------------------- # |
# |
# Quartus II 32-bit |
# Version 11.1 Build 216 11/23/2011 Service Pack 1 SJ Web Edition |
# Date created = 09:17:30 September 29, 2012 |
# |
# -------------------------------------------------------------------------- # |
# |
# Notes: |
# |
# 1) The default values for assignments are stored in the file: |
# lcd_driver_hd44780_assignment_defaults.qdf |
# If this file doesn't exist, see file: |
# assignment_defaults.qdf |
# |
# 2) Altera recommends that you do not modify this file. This |
# file is updated automatically by the Quartus II software |
# and any changes you make may be lost or overwritten. |
# |
# -------------------------------------------------------------------------- # |
|
|
set_global_assignment -name FAMILY "Cyclone III" |
set_global_assignment -name DEVICE EP3C16F484C6 |
set_global_assignment -name TOP_LEVEL_ENTITY example_driver |
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "11.1 SP1" |
set_global_assignment -name PROJECT_CREATION_TIME_DATE "09:17:30 SEPTEMBER 29, 2012" |
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" |
set_location_assignment PIN_D13 -to HEX0_DP |
set_location_assignment PIN_B15 -to HEX1_DP |
set_location_assignment PIN_A18 -to HEX2_DP |
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 |
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 |
set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA |
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484 |
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 6 |
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF |
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF |
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "AS INPUT TRI-STATED" |
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise |
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall |
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise |
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall |
set_global_assignment -name SMART_RECOMPILE ON |
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 |
set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V |
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" |
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation |
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008 |
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF |
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" |
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" |
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V" |
set_global_assignment -name EDA_TEST_BENCH_ENABLE_STATUS COMMAND_MACRO_MODE -section_id eda_simulation |
set_global_assignment -name EDA_SIMULATION_RUN_SCRIPT tb_example_driver.do -section_id eda_simulation |
set_location_assignment PIN_G21 -to CLOCK_50 |
set_location_assignment PIN_B12 -to CLOCK_50_2 |
set_location_assignment PIN_G8 -to DRAM_CAS_N |
set_location_assignment PIN_G7 -to DRAM_CS_N |
set_location_assignment PIN_E5 -to DRAM_CLK |
set_location_assignment PIN_E6 -to DRAM_CKE |
set_location_assignment PIN_B5 -to DRAM_BA_0 |
set_location_assignment PIN_A4 -to DRAM_BA_1 |
set_location_assignment PIN_F10 -to DRAM_DQ[15] |
set_location_assignment PIN_E10 -to DRAM_DQ[14] |
set_location_assignment PIN_A10 -to DRAM_DQ[13] |
set_location_assignment PIN_B10 -to DRAM_DQ[12] |
set_location_assignment PIN_C10 -to DRAM_DQ[11] |
set_location_assignment PIN_A9 -to DRAM_DQ[10] |
set_location_assignment PIN_B9 -to DRAM_DQ[9] |
set_location_assignment PIN_A8 -to DRAM_DQ[8] |
set_location_assignment PIN_F8 -to DRAM_DQ[7] |
set_location_assignment PIN_H9 -to DRAM_DQ[6] |
set_location_assignment PIN_G9 -to DRAM_DQ[5] |
set_location_assignment PIN_F9 -to DRAM_DQ[4] |
set_location_assignment PIN_E9 -to DRAM_DQ[3] |
set_location_assignment PIN_H10 -to DRAM_DQ[2] |
set_location_assignment PIN_G10 -to DRAM_DQ[1] |
set_location_assignment PIN_D10 -to DRAM_DQ[0] |
set_location_assignment PIN_E7 -to DRAM_LDQM |
set_location_assignment PIN_B8 -to DRAM_UDQM |
set_location_assignment PIN_F7 -to DRAM_RAS_N |
set_location_assignment PIN_D6 -to DRAM_WE_N |
set_location_assignment PIN_C8 -to DRAM_ADDR[12] |
set_location_assignment PIN_A7 -to DRAM_ADDR[11] |
set_location_assignment PIN_B4 -to DRAM_ADDR[10] |
set_location_assignment PIN_B7 -to DRAM_ADDR[9] |
set_location_assignment PIN_C7 -to DRAM_ADDR[8] |
set_location_assignment PIN_A6 -to DRAM_ADDR[7] |
set_location_assignment PIN_B6 -to DRAM_ADDR[6] |
set_location_assignment PIN_C6 -to DRAM_ADDR[5] |
set_location_assignment PIN_A5 -to DRAM_ADDR[4] |
set_location_assignment PIN_C3 -to DRAM_ADDR[3] |
set_location_assignment PIN_B3 -to DRAM_ADDR[2] |
set_location_assignment PIN_A3 -to DRAM_ADDR[1] |
set_location_assignment PIN_C4 -to DRAM_ADDR[0] |
set_location_assignment PIN_R2 -to FL_ADDR[21] |
set_location_assignment PIN_P3 -to FL_ADDR[20] |
set_location_assignment PIN_P1 -to FL_ADDR[19] |
set_location_assignment PIN_M6 -to FL_ADDR[18] |
set_location_assignment PIN_M5 -to FL_ADDR[17] |
set_location_assignment PIN_AA2 -to FL_ADDR[16] |
set_location_assignment PIN_L6 -to FL_ADDR[15] |
set_location_assignment PIN_L7 -to FL_ADDR[14] |
set_location_assignment PIN_M1 -to FL_ADDR[13] |
set_location_assignment PIN_M2 -to FL_ADDR[12] |
set_location_assignment PIN_M3 -to FL_ADDR[11] |
set_location_assignment PIN_N1 -to FL_ADDR[10] |
set_location_assignment PIN_N2 -to FL_ADDR[9] |
set_location_assignment PIN_P2 -to FL_ADDR[8] |
set_location_assignment PIN_M4 -to FL_ADDR[7] |
set_location_assignment PIN_M8 -to FL_ADDR[6] |
set_location_assignment PIN_N6 -to FL_ADDR[5] |
set_location_assignment PIN_N5 -to FL_ADDR[4] |
set_location_assignment PIN_N7 -to FL_ADDR[3] |
set_location_assignment PIN_P6 -to FL_ADDR[2] |
set_location_assignment PIN_P5 -to FL_ADDR[1] |
set_location_assignment PIN_P7 -to FL_ADDR[0] |
set_location_assignment PIN_AA1 -to FL_BYTE_N |
set_location_assignment PIN_N8 -to FL_CE_N |
set_location_assignment PIN_R7 -to FL_DQ[0] |
set_location_assignment PIN_P8 -to FL_DQ[1] |
set_location_assignment PIN_R8 -to FL_DQ[2] |
set_location_assignment PIN_U1 -to FL_DQ[3] |
set_location_assignment PIN_V2 -to FL_DQ[4] |
set_location_assignment PIN_V3 -to FL_DQ[5] |
set_location_assignment PIN_W1 -to FL_DQ[6] |
set_location_assignment PIN_Y1 -to FL_DQ[7] |
set_location_assignment PIN_T5 -to FL_DQ[8] |
set_location_assignment PIN_T7 -to FL_DQ[9] |
set_location_assignment PIN_T4 -to FL_DQ[10] |
set_location_assignment PIN_U2 -to FL_DQ[11] |
set_location_assignment PIN_V1 -to FL_DQ[12] |
set_location_assignment PIN_V4 -to FL_DQ[13] |
set_location_assignment PIN_W2 -to FL_DQ[14] |
set_location_assignment PIN_R6 -to FL_OE_N |
set_location_assignment PIN_R1 -to FL_RST_N |
set_location_assignment PIN_M7 -to FL_RY |
set_location_assignment PIN_P4 -to FL_WE_N |
set_location_assignment PIN_T3 -to FL_WP_N |
set_location_assignment PIN_Y2 -to FL_DQ15_AM1 |
set_location_assignment PIN_J1 -to LEDG[0] |
set_location_assignment PIN_J2 -to LEDG[1] |
set_location_assignment PIN_J3 -to LEDG[2] |
set_location_assignment PIN_H1 -to LEDG[3] |
set_location_assignment PIN_F2 -to LEDG[4] |
set_location_assignment PIN_E1 -to LEDG[5] |
set_location_assignment PIN_C1 -to LEDG[6] |
set_location_assignment PIN_C2 -to LEDG[7] |
set_location_assignment PIN_B2 -to LEDG[8] |
set_location_assignment PIN_B1 -to LEDG[9] |
set_location_assignment PIN_F21 -to LCD_BLON |
set_location_assignment PIN_F22 -to LCD_RS |
set_location_assignment PIN_E22 -to LCD_RW |
set_location_assignment PIN_E21 -to LCD_EN |
set_location_assignment PIN_P22 -to PS2_KBCLK |
set_location_assignment PIN_P21 -to PS2_KBDAT |
set_location_assignment PIN_R21 -to PS2_MSCLK |
set_location_assignment PIN_R22 -to PS2_MSDAT |
set_location_assignment PIN_H2 -to BUTTON[0] |
set_location_assignment PIN_G3 -to BUTTON[1] |
set_location_assignment PIN_F1 -to BUTTON[2] |
set_location_assignment PIN_Y21 -to SD_CLK |
set_location_assignment PIN_Y22 -to SD_CMD |
set_location_assignment PIN_AA22 -to SD_DAT0 |
set_location_assignment PIN_W21 -to SD_DAT3 |
set_location_assignment PIN_W20 -to SD_WP_N |
set_location_assignment PIN_E11 -to HEX0_D[0] |
set_location_assignment PIN_F11 -to HEX0_D[1] |
set_location_assignment PIN_H12 -to HEX0_D[2] |
set_location_assignment PIN_H13 -to HEX0_D[3] |
set_location_assignment PIN_G12 -to HEX0_D[4] |
set_location_assignment PIN_F12 -to HEX0_D[5] |
set_location_assignment PIN_F13 -to HEX0_D[6] |
set_location_assignment PIN_A13 -to HEX1_D[0] |
set_location_assignment PIN_B13 -to HEX1_D[1] |
set_location_assignment PIN_C13 -to HEX1_D[2] |
set_location_assignment PIN_A14 -to HEX1_D[3] |
set_location_assignment PIN_B14 -to HEX1_D[4] |
set_location_assignment PIN_E14 -to HEX1_D[5] |
set_location_assignment PIN_A15 -to HEX1_D[6] |
set_location_assignment PIN_D15 -to HEX2_D[0] |
set_location_assignment PIN_A16 -to HEX2_D[1] |
set_location_assignment PIN_B16 -to HEX2_D[2] |
set_location_assignment PIN_E15 -to HEX2_D[3] |
set_location_assignment PIN_A17 -to HEX2_D[4] |
set_location_assignment PIN_B17 -to HEX2_D[5] |
set_location_assignment PIN_F14 -to HEX2_D[6] |
set_location_assignment PIN_B18 -to HEX3_D[0] |
set_location_assignment PIN_F15 -to HEX3_D[1] |
set_location_assignment PIN_A19 -to HEX3_D[2] |
set_location_assignment PIN_B19 -to HEX3_D[3] |
set_location_assignment PIN_C19 -to HEX3_D[4] |
set_location_assignment PIN_D19 -to HEX3_D[5] |
set_location_assignment PIN_G15 -to HEX3_D[6] |
set_location_assignment PIN_G16 -to HEX3_DP |
set_location_assignment PIN_J6 -to SW[0] |
set_location_assignment PIN_H5 -to SW[1] |
set_location_assignment PIN_H6 -to SW[2] |
set_location_assignment PIN_G4 -to SW[3] |
set_location_assignment PIN_G5 -to SW[4] |
set_location_assignment PIN_J7 -to SW[5] |
set_location_assignment PIN_H7 -to SW[6] |
set_location_assignment PIN_E3 -to SW[7] |
set_location_assignment PIN_E4 -to SW[8] |
set_location_assignment PIN_D2 -to SW[9] |
set_location_assignment PIN_L22 -to VGA_VS |
set_location_assignment PIN_L21 -to VGA_HS |
set_location_assignment PIN_K22 -to VGA_B[0] |
set_location_assignment PIN_K21 -to VGA_B[1] |
set_location_assignment PIN_J22 -to VGA_B[2] |
set_location_assignment PIN_K18 -to VGA_B[3] |
set_location_assignment PIN_H22 -to VGA_G[0] |
set_location_assignment PIN_J17 -to VGA_G[1] |
set_location_assignment PIN_K17 -to VGA_G[2] |
set_location_assignment PIN_J21 -to VGA_G[3] |
set_location_assignment PIN_H19 -to VGA_R[0] |
set_location_assignment PIN_H17 -to VGA_R[1] |
set_location_assignment PIN_H20 -to VGA_R[2] |
set_location_assignment PIN_H21 -to VGA_R[3] |
set_location_assignment PIN_U22 -to UART_RXD |
set_location_assignment PIN_U21 -to UART_TXD |
set_location_assignment PIN_V21 -to UART_CTS |
set_location_assignment PIN_V22 -to UART_RTS |
set_location_assignment PIN_AB16 -to GPIO0_D[0] |
set_location_assignment PIN_AA16 -to GPIO0_D[1] |
set_location_assignment PIN_AA15 -to GPIO0_D[2] |
set_location_assignment PIN_AB15 -to GPIO0_D[3] |
set_location_assignment PIN_AA14 -to GPIO0_D[4] |
set_location_assignment PIN_AB14 -to GPIO0_D[5] |
set_location_assignment PIN_AB13 -to GPIO0_D[6] |
set_location_assignment PIN_AA13 -to GPIO0_D[7] |
set_location_assignment PIN_AB10 -to GPIO0_D[8] |
set_location_assignment PIN_AA10 -to GPIO0_D[9] |
set_location_assignment PIN_AB8 -to GPIO0_D[10] |
set_location_assignment PIN_AA8 -to GPIO0_D[11] |
set_location_assignment PIN_AB5 -to GPIO0_D[12] |
set_location_assignment PIN_AA5 -to GPIO0_D[13] |
set_location_assignment PIN_AB4 -to GPIO0_D[14] |
set_location_assignment PIN_AA4 -to GPIO0_D[15] |
set_location_assignment PIN_V14 -to GPIO0_D[16] |
set_location_assignment PIN_U14 -to GPIO0_D[17] |
set_location_assignment PIN_Y13 -to GPIO0_D[18] |
set_location_assignment PIN_W13 -to GPIO0_D[19] |
set_location_assignment PIN_U13 -to GPIO0_D[20] |
set_location_assignment PIN_V12 -to GPIO0_D[21] |
set_location_assignment PIN_R10 -to GPIO0_D[22] |
set_location_assignment PIN_V11 -to GPIO0_D[23] |
set_location_assignment PIN_Y10 -to GPIO0_D[24] |
set_location_assignment PIN_W10 -to GPIO0_D[25] |
set_location_assignment PIN_T8 -to GPIO0_D[26] |
set_location_assignment PIN_V8 -to GPIO0_D[27] |
set_location_assignment PIN_W7 -to GPIO0_D[28] |
set_location_assignment PIN_W6 -to GPIO0_D[29] |
set_location_assignment PIN_V5 -to GPIO0_D[30] |
set_location_assignment PIN_U7 -to GPIO0_D[31] |
set_location_assignment PIN_AB12 -to GPIO0_CLKIN[0] |
set_location_assignment PIN_AA12 -to GPIO0_CLKIN[1] |
set_location_assignment PIN_AB3 -to GPIO0_CLKOUT[0] |
set_location_assignment PIN_AA3 -to GPIO0_CLKOUT[1] |
set_location_assignment PIN_D22 -to LCD_DATA[0] |
set_location_assignment PIN_D21 -to LCD_DATA[1] |
set_location_assignment PIN_C22 -to LCD_DATA[2] |
set_location_assignment PIN_C21 -to LCD_DATA[3] |
set_location_assignment PIN_B22 -to LCD_DATA[4] |
set_location_assignment PIN_B21 -to LCD_DATA[5] |
set_location_assignment PIN_D20 -to LCD_DATA[6] |
set_location_assignment PIN_C20 -to LCD_DATA[7] |
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON |
set_global_assignment -name OPTIMIZE_POWER_DURING_SYNTHESIS OFF |
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" |
set_global_assignment -name FITTER_EFFORT "STANDARD FIT" |
set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF |
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF |
set_global_assignment -name TIMEQUEST_REPORT_SCRIPT_INCLUDE_DEFAULT_ANALYSIS OFF |
set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON |
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF |
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING OFF |
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA OFF |
set_global_assignment -name PHYSICAL_SYNTHESIS_MAP_LOGIC_TO_MEMORY_FOR_AREA OFF |
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL |
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE BALANCED |
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON |
|
|
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top |
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top |
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top |
set_instance_assignment -name SLEW_RATE 1 -to LCD_EN |
set_instance_assignment -name SLEW_RATE 1 -to LCD_RS |
set_instance_assignment -name SLEW_RATE 1 -to LCD_RW |
set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to LCD_EN |
set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to LCD_RS |
set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to LCD_RW |
set_global_assignment -name VHDL_FILE lcd_driver_hd44780_module.vhd |
set_global_assignment -name VHDL_FILE tb_lcd_driver_hd44780_module.vhd |
set_global_assignment -name COMMAND_MACRO_FILE tb_lcd_driver_hd44780_module.do |
set_global_assignment -name VHDL_FILE example_driver.vhd |
set_global_assignment -name VHDL_FILE tb_example_driver.vhd |
set_global_assignment -name COMMAND_MACRO_FILE tb_example_driver.do |
set_global_assignment -name SDC_FILE lcd_driver_hd44780.sdc |
set_global_assignment -name TEXT_FILE readme.txt |
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top |
/trunk/lcd_driver_hd44780.sdc
0,0 → 1,115
## Generated SDC file "lcd_driver_hd44780.sdc" |
|
## Copyright (C) 1991-2011 Altera Corporation |
## Your use of Altera Corporation's design tools, logic functions |
## and other software and tools, and its AMPP partner logic |
## functions, and any output files from any of the foregoing |
## (including device programming or simulation files), and any |
## associated documentation or information are expressly subject |
## to the terms and conditions of the Altera Program License |
## Subscription Agreement, Altera MegaCore Function License |
## Agreement, or other applicable license agreement, including, |
## without limitation, that your use is for the sole purpose of |
## programming logic devices manufactured by Altera and sold by |
## Altera or its authorized distributors. Please refer to the |
## applicable agreement for further details. |
|
|
## VENDOR "Altera" |
## PROGRAM "Quartus II" |
## VERSION "Version 11.1 Build 216 11/23/2011 Service Pack 1 SJ Web Edition" |
|
## DATE "Thu Oct 11 15:50:30 2012" |
|
## |
## DEVICE "EP3C16F484C6" |
## |
|
|
#************************************************************** |
# Time Information |
#************************************************************** |
|
set_time_format -unit ns -decimal_places 3 |
|
|
|
#************************************************************** |
# Create Clock |
#************************************************************** |
|
create_clock -name {CLOCK_50} -period 20.000 -waveform { 0.000 10.000 } [get_ports {CLOCK_50}] |
|
|
#************************************************************** |
# Create Generated Clock |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Clock Latency |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Clock Uncertainty |
#************************************************************** |
|
#set_clock_uncertainty -rise_from [get_keepers {prescaler:pres|clkint}] -rise_to [get_keepers {prescaler:pres|clkint}] 0.020 |
#set_clock_uncertainty -rise_from [get_keepers {prescaler:pres|clkint}] -fall_to [get_keepers {prescaler:pres|clkint}] 0.020 |
#set_clock_uncertainty -fall_from [get_keepers {prescaler:pres|clkint}] -rise_to [get_keepers {prescaler:pres|clkint}] 0.020 |
#set_clock_uncertainty -fall_from [get_keepers {prescaler:pres|clkint}] -fall_to [get_keepers {prescaler:pres|clkint}] 0.020 |
|
set_clock_uncertainty -rise_from [get_clocks {CLOCK_50}] -rise_to [get_clocks {CLOCK_50}] 0.020 |
set_clock_uncertainty -rise_from [get_clocks {CLOCK_50}] -fall_to [get_clocks {CLOCK_50}] 0.020 |
set_clock_uncertainty -fall_from [get_clocks {CLOCK_50}] -rise_to [get_clocks {CLOCK_50}] 0.020 |
set_clock_uncertainty -fall_from [get_clocks {CLOCK_50}] -fall_to [get_clocks {CLOCK_50}] 0.020 |
|
#************************************************************** |
# Set Input Delay |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Output Delay |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Clock Groups |
#************************************************************** |
|
|
|
#************************************************************** |
# Set False Path |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Multicycle Path |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Maximum Delay |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Minimum Delay |
#************************************************************** |
|
|
|
#************************************************************** |
# Set Input Transition |
#************************************************************** |
|
/trunk/photo.jpg
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
trunk/photo.jpg
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: trunk/tb_lcd_driver_hd44780_module.vhd
===================================================================
--- trunk/tb_lcd_driver_hd44780_module.vhd (nonexistent)
+++ trunk/tb_lcd_driver_hd44780_module.vhd (revision 5)
@@ -0,0 +1,247 @@
+-- Filename: tb_lcd_driver_hd44780_module.do
+-- Filetype: VHDL Testbench
+-- Date: 26 oct 2012
+-- Update: -
+-- Description: VHDL Testbench for simulation
+-- Author: J. op den Brouw
+-- State: Demo
+-- Error: -
+-- Version: 1.1alpha
+-- Copyright: (c)2012, De Haagse Hogeschool
+
+-- This file contains a very simple VHDL testbench for a HD44780 LCD
+-- display, see more specs at
+--
+-- This VHDL code implements a simple testbench for testing
+-- the LCD Module Driver. More scripting should be done here.
+
+-- The libraries et al.
+library ieee;
+use ieee.std_logic_1164.all;
+
+-- Empty entity
+entity tb_lcd_driver_hd44780_module is
+end entity tb_lcd_driver_hd44780_module;
+
+-- The testbench
+architecture sim of tb_lcd_driver_hd44780_module is
+-- The LCD driver
+component lcd_driver_hd44780_module is
+ generic (freq : integer := 50000000;
+ areset_pol : std_logic := '1';
+ time_init1 : time := 40 ms;
+ time_init2 : time := 4100 us;
+ time_init3 : time := 100 us;
+ time_tas : time := 60 ns;
+ time_cycle_e : time := 1000 ns;
+ time_pweh : time := 500 ns;
+ time_no_bf : time := 2 ms;
+ cursor_on : boolean := false;
+ blink_on : boolean := false;
+ use_bf : boolean := true
+ );
+ port (clk : in std_logic;
+ areset : in std_logic;
+ -- User site
+ init : in std_logic;
+ data : in std_logic_vector(7 downto 0);
+ wr : in std_logic;
+ cls : in std_logic;
+ home : in std_logic;
+ goto10 : in std_logic;
+ goto20 : in std_logic;
+ goto30 : in std_logic;
+ busy : out std_logic;
+ -- LCD side
+ LCD_E : out std_logic;
+ LCD_RS : out std_logic;
+ LCD_RW : out std_logic;
+ LCD_DB : inout std_logic_vector(7 downto 0)
+ );
+end component lcd_driver_hd44780_module;
+
+-- Glue signals
+signal clk : std_logic;
+signal areset : std_logic;
+-- User site
+signal init : std_logic;
+signal data : std_logic_vector(7 downto 0);
+signal wr : std_logic;
+signal cls : std_logic;
+signal home : std_logic;
+signal goto10 : std_logic;
+signal goto20 : std_logic;
+signal goto30 : std_logic;
+signal busy : std_logic;
+-- LCD side
+signal LCD_DB : std_logic_vector(7 downto 0);
+signal LCD_E : std_logic;
+signal LCD_RW : std_logic;
+signal LCD_RS : std_logic;
+
+--constant freq_in : integer := 10000; -- 10 kHz
+constant freq_in : integer := 50000000; -- 50 MHz
+constant clock_period : time := (1.0/real(freq_in)) * (1 sec);
+
+-- Internal tracer
+signal trace : integer;
+
+-- Now let's begin...
+begin
+
+ -- Instantiation of the LCD Driver, some generics are used
+ lcdm : lcd_driver_hd44780_module
+ generic map (freq => freq_in, areset_pol => '1', time_cycle_e => 2000 ns, time_pweh => 500 ns,
+ cursor_on => true, blink_on => true, use_bf => false)
+ port map (clk => clk, areset => areset, init => init, data => data, wr => wr, cls => cls,
+ home => home, goto10 => goto10, goto20 => goto20, goto30 => goto30, busy => busy,
+ LCD_DB => LCD_DB, LCD_E => LCD_E, LCD_RW => LCD_RW, LCD_RS => LCD_RS);
+
+ -- The clock signal generation process
+ clockgen: process is
+ begin
+ -- give time for reset
+ clk <= '0';
+ areset <= '1';
+ wait for 15 ns;
+ areset <= '0';
+ wait for 5 ns;
+ -- forever: generate clock cycle for 20 ns and 50% d.c.
+ loop
+ clk <= '1';
+ wait for clock_period/2;
+ clk <= '0';
+ wait for clock_period/2;
+ end loop;
+ end process;
+
+ -- Simulating the user side of the driver
+ user_side: process is
+ begin
+ -- All at zero
+ init <= '0';
+ cls <= '0';
+ home <= '0';
+ goto10 <= '0';
+ goto20 <= '0';
+ goto30 <= '0';
+ wr <= '0';
+ data <= (others => '0');
+ wait until clk = '1';
+
+ -- wait for initialization to complete
+ wait until busy = '0';
+
+ -- Write data to LCD
+ wait until clk = '1';
+ data <= "01000011";
+ wr <= '1';
+ wait until clk = '1';
+ wr <= '0';
+ wait until busy = '0';
+ wait until clk = '1';
+ -- Write data to LCD
+ data <= "01000011";
+ wr <= '1';
+ wait until clk = '1';
+ wr <= '0';
+ wait until busy = '0';
+ wait until clk = '1';
+
+ -- Clear the screen
+ wait until clk = '1';
+ cls <= '1';
+ wait until clk = '1';
+ cls <= '0';
+ wait until busy = '0';
+
+ -- Home the screen
+ wait until clk = '1';
+ home <= '1';
+ wait until clk = '1';
+ home <= '0';
+ wait until busy = '0';
+
+ -- Goto line
+ wait until clk = '1';
+ goto10 <= '1';
+ wait until clk = '1';
+ goto10 <= '0';
+ wait until busy = '0';
+ wait until clk = '1';
+ goto20 <= '1';
+ wait until clk = '1';
+ goto20 <= '0';
+ wait until busy = '0';
+ wait until clk = '1';
+ goto30 <= '1';
+ wait until clk = '1';
+ goto30 <= '0';
+ wait until busy = '0';
+
+ -- Write data to LCD
+ wait until clk = '1';
+ wr <= '1';
+ wait until clk = '1';
+ wr <= '0';
+ wait until busy = '0';
+ wait until clk = '1';
+
+ -- Initialize the LCD
+ wait until clk = '1';
+ init <= '1';
+ wait until clk = '1';
+ init <= '0';
+ wait until busy = '0';
+ wait until clk = '1';
+
+ wait;
+ end process;
+
+ -- Simple simulation description of the LCD itself...
+ -- (probably too simple)
+ lcd_module_sim: process is
+ begin
+ trace <= 0;
+ LCD_DB <= (others => 'Z');
+ -- Wait for reset clear
+ wait until areset = '0';
+ trace <= 1;
+ -- Three writes to the LCD, no busy flag testing possible
+ wait until LCD_E = '1';
+ wait until LCD_E = '1';
+ wait until LCD_E = '1';
+ trace <= 2;
+
+ loop
+ -- command/data written to
+ trace <= 3;
+ wait until LCD_E = '1';
+ trace <= 4;
+ wait until LCD_E = '0';
+
+ -- busy flag reading
+ trace <= 5;
+ wait until LCD_E = '1';
+ trace <= 6;
+ if LCD_RW = '1' then
+ trace <= 61;
+ -- Signal LCD is busy
+ LCD_DB <= "1ZZZZZZZ";
+ -- Internal delay of the LCD for some commands
+ wait for 40 us;
+ -- Signal LCD is ready
+ LCD_DB <= "0ZZZZZZZ";
+ end if;
+ wait until LCD_E = '0';
+ trace <= 7;
+ if LCD_RW = '1' then
+ trace <= 1;
+ LCD_DB <= "ZZZZZZZZ";
+ end if;
+
+ end loop;
+ wait;
+ end process;
+
+end architecture;
\ No newline at end of file
Index: trunk/tb_lcd_driver_hd44780_module.do
===================================================================
--- trunk/tb_lcd_driver_hd44780_module.do (nonexistent)
+++ trunk/tb_lcd_driver_hd44780_module.do (revision 5)
@@ -0,0 +1,96 @@
+# Filename: tb_lcd_driver_hd44780_module.do
+# Filetype: Modelsim Script File
+# Date: 66 oct 2012
+# Update: -
+# Description: Script File For Automatic Simulation
+# Author: J. op den Brouw
+# State: Demo
+# Error: -
+# Version: 1.1alpha
+# Copyright: (c)2012, De Haagse Hogeschool
+
+# This ModelSim command file houses all commands for tracing
+# the LCD Module Driver.
+
+# Set transcript on
+transcript on
+
+# Recreate the work directory and map to work
+if {[file exists rtl_work]} {
+ vdel -lib rtl_work -all
+}
+vlib rtl_work
+vmap work rtl_work
+
+# Find out if we're started through Quartus or by hand
+# (or by using an exec in the Tcl window in Quartus).
+# Quartus has the annoying property that it will start
+# Modelsim from a directory called "simulation/modelsim".
+# The design and the testbench are located in the project
+# root, so we've to compensate for that.
+if [ string match "*simulation/modelsim" [pwd] ] {
+ set prefix "../../"
+ puts "Running Modelsim from Quartus..."
+} else {
+ set prefix ""
+ puts "Running Modelsim..."
+}
+
+# Compile the LCD VHDL description and testbench,
+# please note that the design and its testbench is located
+# in the project root, but the simulator start in directory
+# /simulation/modelsim, so we have to compensate
+# for that.
+vcom -2008 -work work ${prefix}lcd_driver_hd44780_module.vhd
+vcom -2008 -work work ${prefix}tb_lcd_driver_hd44780_module.vhd
+
+# Start the simulator with 1 ns time resolution
+vsim -t 1ns -L rtl_work -L work -voptargs="+acc" tb_lcd_driver_hd44780_module
+
+# Log all signals in the design, good if the number
+# of signals is small.
+add log -r *
+
+# Add all toplevel signals
+# Add a number of signals of the simulated design
+#add list *
+
+# Add all toplevel signals
+# Add a number of signals of the simulated design
+add wave -divider "SYSTEM"
+add wave clk
+add wave areset
+add wave -divider "Inputs"
+add wave init
+add wave cls
+add wave home
+add wave goto10
+add wave goto20
+add wave goto30
+add wave wr
+add wave data
+add wave -divider "Internals"
+add wave lcdm/current_state
+add wave lcdm/return_state
+add wave lcdm/delay_counter
+add wave lcdm/use_bf_int
+add wave trace
+add wave -divider "Outputs"
+add wave busy
+add wave LCD_E
+add wave LCD_RW
+add wave LCD_RS
+add wave LCD_DB
+
+# Open Structure, Signals (waveform) and List window
+view structure
+#view list
+view signals
+view wave
+
+# Run simulation for ...
+# Note: 60 ms is sufficient using Busy Flag reading.
+run 160 ms
+
+# Fill up the waveform in the window
+wave zoom full
Index: trunk/readme.txt
===================================================================
--- trunk/readme.txt (nonexistent)
+++ trunk/readme.txt (revision 5)
@@ -0,0 +1,104 @@
+Information to the Project HD44780 Driver
+-----------------------------------------
+This project contains VHDL descriptions for driving a standard HD44780
+LCD Driver with a minimum of inputs. Please read on.
+
+Information
+-----------
+Author: J.E.J. op den Brouw
+Company: De Haagse Hogeschool
+Rationale: This driver is written to facilitate my students
+Software: Quartus II v11.1 / ModelSim v10.0.c / Windows 7
+Hardware: Terasic DE0 board with optional display (Cyclone III)
+Status: Alpha, tested by my students.
+
+Files
+-----
+lcd_driver_hd44780_module.vhd - The Driver
+tb_lcd_driver_hd44780_module.vhd - Simple testbench
+tb_lcd_driver_hd44780_module.do - ModelSim command file
+example_driver.vhd - Example on how to use the driver
+tb_example_driver.vhd - Simple testbench
+tb_example_driver.do - ModelSim command file
+lcd_driver_hd44780.sdc - Synopsys Constraints File (clock info only)
+readme.txt - This file
+
+Overall Description
+----------------------------------------------------------------------------------------
+Currently, this driver uses the 8-bit databus mode. This is not a big problem
+for most FPGA's because of the numerous pins.
+Please note that there are a lot of almost-the-same displays available, so
+it's not guaranteed to work with all displays available. Also, timing may differ.
+
+This code is tested on a Terasic DE0-board with an optional LCD display.
+See the weblinks:
+http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=56&No=364
+http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=78&No=396
+for more info. The display used has only two lines.
+
+The VHDL descriptions can both be simulated and synthesized.
+
+This driver has a User Side and a LCD Side. The user is to interface at the User Side
+and has a number of "routines" at her disposal. The User Side implements the following
+inputs/routines in order of priority:
+
+Command inputs:
+ init: a logic 1 initializes the display
+ cls: a logic 1 clears the display (and goes to home)
+ home: a logic 1 sets the cursor to row 0, column 0
+ goto10: a logic 1 sets the cursor to row 1, column 0
+ goto20: a logic 1 sets the cursor to row 2, column 0
+ goto30: a logic 1 sets the cursor to row 3, column 0
+ wr: a logic 1 writes a character to the display
+
+Data inputs:
+
+ data: an 8-bit data to be written to the display
+
+The user has one observable output:
+
+ busy: a logic 1 indicates that the driver is currently
+ busy driving the display, a logic 0 indicates that
+ the driver waits for the next command.
+
+The user can supply the next generics, which are processed at
+instantiation of the module:
+
+ freq: the clock frequency at which the hardware has to run.
+ this frequency is mandatory because of internal delays
+ calculated, defaults to 50 MHz.
+ areset_pol:
+ the polarity of the reset signal, defaults to High (1)
+ time_init1:
+ the time to wait after Vcc > 4.5 V
+ time_init2:
+ the time to wait after first "contact"
+ time_init3:
+ the time to wait after the second contact
+ time_tas:
+ the RW and RS signal setup time with respect to the positive
+ edge of the E pulse
+ time_cycle_e:
+ the complete cycle time
+ time_pweh:
+ the E pulse width high time
+ time_no_bf:
+ time to wait before command completion if no Busy Flag reading is done,
+ some designs connect RW to logic 0, so reading from the LCD is not
+ possible, saves a pin.
+ cursor_on:
+ true to set the cursor on at the display, false for no cursor
+ blink_on:
+ true to let the cursor blink, false for no blink (just a underscore)
+ use_bf: true if Busy Flag reading is to be used, false for no BF reading
+
+Note: it's not possible to write command codes to the display.
+
+A note about timing:
+ Some of the timing parameters are very small, e.g. the RW and RS setup time with
+ respect to rising edge of E. If the clock frequency is too low, the delay calculated
+ will be zero, which result in at least a delay with the period time of the clock.
+
+A note about implementing:
+ If the driver doesn't work or you get clobbered strings, please use non-BF
+ reading at first. Next, increase the Cycle E time and PWeh time.
Index: trunk/tb_example_driver.vhd
===================================================================
--- trunk/tb_example_driver.vhd (nonexistent)
+++ trunk/tb_example_driver.vhd (revision 5)
@@ -0,0 +1,150 @@
+-- Filename: tb_example_driver.vhd
+-- Filetype: VHDL Testbench
+-- Date: 26 oct 2012
+-- Update: -
+-- Description: VHDL testbench for example driver
+-- Author: J. op den Brouw
+-- State: Demo
+-- Error: -
+-- Version: 1.0alpha
+-- Copyright: (c)2012, De Haagse Hogeschool
+
+-- This file contains a very simple VHDL testbench for a User Side
+-- driver for the LCD driver.
+--
+
+-- Libraries et al.
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+-- The entity of a testbench for the example driver
+entity tb_example_driver is
+end entity tb_example_driver;
+
+-- The architecture!
+architecture sim of tb_example_driver is
+-- Component declaration of the example driver
+component example_driver is
+ port (CLOCK_50 : in std_logic;
+ BUTTON : in std_logic_vector(2 downto 0);
+ SW : in std_logic_vector(9 downto 0);
+ LEDG : out std_logic_vector(9 downto 0);
+ HEX3_D : out std_logic_vector(6 downto 0);
+ HEX2_D : out std_logic_vector(6 downto 0);
+ HEX1_D : out std_logic_vector(6 downto 0);
+ HEX0_D : out std_logic_vector(6 downto 0);
+ HEX0_DP : out std_logic;
+ HEX1_DP : out std_logic;
+ HEX2_DP : out std_logic;
+ HEX3_DP : out std_logic;
+ -- LCD of the DE0 board
+ LCD_EN : out std_logic;
+ LCD_RS : out std_logic;
+ LCD_RW : out std_logic;
+ LCD_DATA : inout std_logic_vector(7 downto 0);
+ LCD_BLON : out std_logic
+ );
+end component example_driver;
+
+signal CLOCK_50 : std_logic;
+signal BUTTON : std_logic_vector(2 downto 0);
+signal SW : std_logic_vector(9 downto 0);
+signal LEDG : std_logic_vector(9 downto 0);
+signal HEX3_D : std_logic_vector(6 downto 0);
+signal HEX2_D : std_logic_vector(6 downto 0);
+signal HEX1_D : std_logic_vector(6 downto 0);
+signal HEX0_D : std_logic_vector(6 downto 0);
+signal HEX0_DP : std_logic;
+signal HEX1_DP : std_logic;
+signal HEX2_DP : std_logic;
+signal HEX3_DP : std_logic;
+-- LCD of the DE0 board
+signal LCD_EN : std_logic;
+signal LCD_RS : std_logic;
+signal LCD_RW : std_logic;
+signal LCD_DATA : std_logic_vector(7 downto 0);
+signal LCD_BLON : std_logic;
+
+--constant freq_in : integer := 10000; -- 10 kHz
+constant freq_in : integer := 50000000; -- 50 MHz
+constant clock_period : time := (1.0/real(freq_in)) * (1 sec);
+
+-- Internal tracer
+signal trace : integer;
+
+begin
+
+ -- The driver's driver...
+ de0: example_driver
+ port map (CLOCK_50 => CLOCK_50, BUTTON => BUTTON, SW => SW, LEDG => LEDG,
+ HEX3_D => HEX3_D, HEX2_D => HEX2_D, HEX1_D => HEX1_D, HEX0_D => HEX0_D,
+ HEX0_DP => HEX0_DP, HEX1_DP => HEX1_DP, HEX2_DP => HEX2_DP, HEX3_DP => HEX3_DP,
+ LCD_EN => LCD_EN, LCD_RS => LCD_RS, LCD_RW => LCD_RW, LCD_DATA => LCD_DATA,
+ LCD_BLON => LCD_BLON);
+
+ -- The clock signal generation process
+ clockgen: process is
+ begin
+ -- give time for reset, buttons active low!
+ CLOCK_50 <= '0';
+ BUTTON <= "110";
+ wait for 15 ns;
+ BUTTON <= "111";
+ wait for 5 ns;
+ -- forever: generate clock cycle for 20 ns and 50% d.c.
+ loop
+ CLOCK_50 <= '1';
+ wait for clock_period/2;
+ CLOCK_50 <= '0';
+ wait for clock_period/2;
+ end loop;
+ end process;
+
+ -- Simple simulation description of the LCD itself...
+ -- (probably too simple)
+ lcd_module_sim: process is
+ begin
+ trace <= 0;
+ LCD_DATA <= (others => 'Z');
+ -- Wait for reset clear
+ wait until BUTTON(0) = '0';
+ trace <= 1;
+ -- Three writes to the LCD, no busy flag testing possible
+ wait until LCD_EN = '1';
+ wait until LCD_EN = '1';
+ wait until LCD_EN = '1';
+ trace <= 2;
+
+ loop
+ -- command/data written to
+ trace <= 3;
+ wait until LCD_EN = '1';
+ trace <= 4;
+ wait until LCD_EN = '0';
+
+ -- busy flag reading
+ trace <= 5;
+ wait until LCD_EN = '1';
+ trace <= 6;
+ if LCD_RW = '1' then
+ trace <= 61;
+ -- Signal LCD is busy
+ LCD_DATA <= "1ZZZZZZZ";
+ -- Internal delay of the LCD for some commands
+ wait for 40 us;
+ -- Signal LCD is ready
+ LCD_DATA <= "0ZZZZZZZ";
+ end if;
+ wait until LCD_EN = '0';
+ trace <= 7;
+ if LCD_RW = '1' then
+ trace <= 1;
+ LCD_DATA <= "ZZZZZZZZ";
+ end if;
+
+ end loop;
+ wait;
+ end process;
+
+end architecture sim;
\ No newline at end of file
Index: trunk/tb_example_driver.do
===================================================================
--- trunk/tb_example_driver.do (nonexistent)
+++ trunk/tb_example_driver.do (revision 5)
@@ -0,0 +1,93 @@
+# Filename: tb_example_driver.do
+# Filetype: Modelsim Script File
+# Date: 26 oct 2012
+# Update: -
+# Description: Script File For Automatic Simulation
+# Author: J. op den Brouw
+# State: Demo
+# Error: -
+# Version: 1.1aplha
+# Copyright: (c)2012, De Haagse Hogeschool
+
+# This ModelSim command file houses all commands for tracing
+# the client side module driver alias the test hardware.
+
+# Set transcript on
+transcript on
+
+# Recreate the work directory and map to work
+if {[file exists rtl_work]} {
+ vdel -lib rtl_work -all
+}
+vlib rtl_work
+vmap work rtl_work
+
+# Find out if we're started through Quartus or by hand
+# (or by using an exec in the Tcl window in Quartus).
+# Quartus has the annoying property that it will start
+# Modelsim from a directory called "simulation/modelsim".
+# The design and the testbench are located in the project
+# root, so we've to compensate for that.
+if [ string match "*simulation/modelsim" [pwd] ] {
+ set prefix "../../"
+ puts "Running Modelsim from Quartus..."
+} else {
+ set prefix ""
+ puts "Running Modelsim..."
+}
+
+# Compile the LCD VHDL description and testbench,
+# please note that the design and its testbench are located
+# in the project root, but the simulator start in directory
+# /simulation/modelsim, so we have to compensate
+# for that.
+vcom -2008 -work work ${prefix}lcd_driver_hd44780_module.vhd
+vcom -2008 -work work ${prefix}example_driver.vhd
+vcom -2008 -work work ${prefix}tb_example_driver.vhd
+
+# Start the simulator with 1 ns time resolution
+vsim -t 1ns -L rtl_work -L work -voptargs="+acc" tb_example_driver
+
+# Log all signals in the design, good if the number
+# of signals is small.
+add log -r *
+
+# Add all toplevel signals
+# Add a number of signals of the simulated design
+add wave -divider "SYSTEM"
+add wave CLOCK_50
+add wave -divider "Inputs"
+add wave BUTTON
+add wave -divider "Internals"
+add wave de0/areset
+add wave de0/clk
+add wave de0/state
+add wave de0/busy
+add wave de0/wr
+add wave de0/goto10
+add wave de0/goto20
+add wave de0/goto30
+add wave de0/home
+add wave de0/cls
+add wave de0/line_counter
+add wave de0/character_counter
+add wave -divider "Outputs"
+add wave LCD_EN
+add wave LCD_RW
+add wave LCD_RS
+add wave LCD_DATA
+add wave LEDG(0)
+
+# Open Structure, Signals (waveform) and List window
+view structure
+#view list
+view signals
+view wave
+
+# Run simulation for ...
+# Note 60 ms is sufficient if using Busy Flag reading, 270 ms
+# for non-BF reading
+run 270 ms
+
+# Fill up the waveform in the window
+wave zoom full