OpenCores
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
    /
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/hd44780_driver/trunk/trunk/example_driver.vhd File deleted \ No newline at end of file
/hd44780_driver/trunk/trunk/lcd_driver_hd44780.qsf File deleted \ No newline at end of file
/hd44780_driver/trunk/trunk/photo.jpg Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
hd44780_driver/trunk/trunk/photo.jpg Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: hd44780_driver/trunk/trunk/tb_lcd_driver_hd44780_module.vhd =================================================================== --- hd44780_driver/trunk/trunk/tb_lcd_driver_hd44780_module.vhd (revision 5) +++ hd44780_driver/trunk/trunk/tb_lcd_driver_hd44780_module.vhd (nonexistent) @@ -1,247 +0,0 @@ --- 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: hd44780_driver/trunk/trunk/tb_lcd_driver_hd44780_module.do =================================================================== --- hd44780_driver/trunk/trunk/tb_lcd_driver_hd44780_module.do (revision 5) +++ hd44780_driver/trunk/trunk/tb_lcd_driver_hd44780_module.do (nonexistent) @@ -1,96 +0,0 @@ -# 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: hd44780_driver/trunk/trunk/readme.txt =================================================================== --- hd44780_driver/trunk/trunk/readme.txt (revision 5) +++ hd44780_driver/trunk/trunk/readme.txt (nonexistent) @@ -1,104 +0,0 @@ -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: hd44780_driver/trunk/trunk/tb_example_driver.vhd =================================================================== --- hd44780_driver/trunk/trunk/tb_example_driver.vhd (revision 5) +++ hd44780_driver/trunk/trunk/tb_example_driver.vhd (nonexistent) @@ -1,150 +0,0 @@ --- 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: hd44780_driver/trunk/trunk/tb_example_driver.do =================================================================== --- hd44780_driver/trunk/trunk/tb_example_driver.do (revision 5) +++ hd44780_driver/trunk/trunk/tb_example_driver.do (nonexistent) @@ -1,93 +0,0 @@ -# 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 Index: hd44780_driver/trunk/trunk/lcd_driver_hd44780_module.vhd =================================================================== --- hd44780_driver/trunk/trunk/lcd_driver_hd44780_module.vhd (revision 5) +++ hd44780_driver/trunk/trunk/lcd_driver_hd44780_module.vhd (nonexistent) @@ -1,500 +0,0 @@ --- 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: --- 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. --- --- 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; Index: hd44780_driver/trunk/trunk/lcd_driver_hd44780.qpf =================================================================== --- hd44780_driver/trunk/trunk/lcd_driver_hd44780.qpf (revision 5) +++ hd44780_driver/trunk/trunk/lcd_driver_hd44780.qpf (nonexistent) @@ -1,30 +0,0 @@ -# -------------------------------------------------------------------------- # -# -# 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"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.