Академический Документы
Профессиональный Документы
Культура Документы
--------
The design displays the word VHDL splitted on two lines on the LCD
+----------------+
|VH
|
| DL
|
+----------------+
-cs
-----.
--
The 2 x 16 character LCD on the board has an internal Sitronix ST7066U graphi
controller that is functionally equivalent with the following devices:
* Samsung S6A0069X or KS0066U
* Hitachi HD44780
* SMOS SED1278
To minimize pin icount the FPGA controls the LCD via the 4-bit data interface
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity lcd
port(
clk
:
rst
:
SF_D :
LCD_E :
LCD_RS :
LCD_RW :
SF_CE0 :
end lcd;
is
in std_logic;
in std_logic;
out std_logic_vector(11 downto 8);
out std_logic;
out std_logic;
out std_logic;
out std_logic);
istate, next_istate
dstate, next_dstate
idone, next_idone
icount, next_icount
dcount, next_dcount
nibble
:
:
:
:
signal
signal
signal
signal
signal
_RS
signal
signal
begin
-- concurrent assignments
SF_CE0 <= '1'; --disable intel strataflash memory.
--FPGA has full read/write access to LCD.
LCD_RW <= '0'; --write LCD (LCD accepts data).
--putting LCD_RW=0 also prevent the LCD screen from presenting
--undesired data.
SF_D <= nibble;
LCD_E <= enable;
LCD_RS <= regsel;
--- muxing init state machines and data state machine
-mux: process (idone, dnibble, inibble, denable, ienable, dregsel, iregsel)
begin
if (idone = '1') then
nibble <= dnibble;
enable <= denable;
regsel <= dregsel;
else
nibble <= inibble;
enable <= ienable;
regsel <= iregsel;
end if;
end process mux;
--- initialization state machine
--- the purpose of the state machine is to initialize the display.
-- After power-on, the display must be initialized to
-- 1. establish the required communication protocol, and
-- 2. configure the diplay operation
--- 1. Configuration of the Fout-bit Interface Protocol
-- The initialization sequence establishes that the FPGA application wishes to
use the
-- four-bit data interface to the LCD as follows:
-- * Wait 15 ms or longer, although the display is generally ready when the
FPGA
-finishes configuration. The 15 ms interval is 750,000 clock cycles at 5
0 MHz.
-- * Write SF_D<11:8> = 0x3, pulse LCD_E High for 12 clock cycles.
-- * Wait 4.1 ms or longer, which is 205,000 clock cycles at 50 MHz.
-- * Write SF_D<11:8> = 0x3, pulse LCD_E High for 12 clock cycles.
-- * Wait 100 ?s or longer, which is 5,000 clock cycles at 50 MHz.
-- * Write SF_D<11:8> = 0x3, pulse LCD_E High for 12 clock cycles.
-- * Wait 40 ?s or longer, which is 2,000 clock cycles at 50 MHz.
-- * Write SF_D<11:8> = 0x2, pulse LCD_E High for 12 clock cycles.
next_icount <= 0;
end if;
when iwait_three => -- wait here for 40 us
next_icount <= icount + 1;
if (icount = 2000) then
next_istate <= iwrite_four;
next_icount <= 0;
next_inibble <= "0010"; -- 0x2
end if;
when iwrite_four =>
next_inibble <= inibble;
next_ienable <= ienable;
next_icount <= icount + 1;
if (icount = 1) then
next_ienable <= '1';
end if;
if (icount = 10) then
next_ienable <= '0';
end if;
if(icount = 11) then
next_istate <= iwait_four;
next_icount <= 0;
end if;
when iwait_four => -- wait here for 40 us
next_icount <= icount + 1;
if (icount = 2000) then
next_istate <= function_set; -- issue function set command 0x28
next_icount <= 0;
next_inibble <= "0010"; -- 0x2 (upper nibble of 0x28)
end if;
when function_set => -- function set command 0x28
next_inibble <= inibble;
next_ienable <= ienable;
next_icount <= icount + 1;
if (icount = 1) then
next_ienable <= '1';
end if;
if (icount = 10) then
next_ienable <= '0';
end if;
if(icount = 11) then -- done with the upper nibble data
next_inibble <= (others => '0');
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
10 + 1 + 50 - 2 = 58
0x8 (lower nibble of 0x28)
-- the timing between the falling edge of the lower nibble's enable
-- and the rising edge of the upper nibble's rising edge
-- of two adjacent operations is 40us (2000 clock cycles)
if (icount = 2068) then -- 69 + 1 + 2000 - 2 =
next_istate <= entry_mode;
next_icount <= 0;
next_inibble <= "0000"; -- 0x0 (lower nibble of 0x06)
end if;
when entry_mode => -- entry mode set command 0x06
next_inibble <= inibble;
next_ienable <= ienable;
next_icount <= icount + 1;
if (icount = 1) then
next_ienable <= '1';
end if;
if (icount = 10) then
next_ienable <= '0';
end if;
if(icount = 11) then -- done with the upper nibble data
next_inibble <= (others => '0');
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (icount = 58) then
-next_inibble <= "0110"; -end if;
if (icount = 60) then
next_ienable <= '1';
end if;
if (icount = 69) then
next_ienable <= '0';
end if;
if(icount = 70) then -- done
next_inibble <= (others =>
end if;
10 + 1 + 50 - 2 = 58
0x6 (lower nibble of 0x06)
-- the timing between the falling edge of the lower nibble's enable
-- and the rising edge of the upper nibble's rising edge
10 + 1 + 50 - 2 = 58
0xC (lower nibble of 0x0C)
the timing between the falling edge of the lower nibble's enable
and the rising edge of the upper nibble's rising edge
of two adjacent operations is 40us (2000 clock cycles)
(icount = 2068) then -- 69 + 1 + 2000 - 2 =
next_istate <= clear_display;
next_icount <= 0;
next_inibble <= "0000"; -- 0x0 (lower nibble of 0x01)
end if;
when clear_display
next_inibble <=
next_ienable <=
next_icount <=
=>
inibble;
ienable;
icount + 1;
if (icount = 1) then
10 + 1 + 50 - 2 = 58
0x1 (lower nibble of 0x01)
--- After the command is complete allow 1.64 ms (82,000 clock cycles)
-- before issuing another command
if (icount = 82071) then -- 70 + 1 + 82000 = 82071
next_istate <= init_done;
next_idone <= '1'; -- flag to signal that initialization is done
next_icount <= 0;
end if;
when init_done =>
-- by default idone will be hold at '1'
-- and the state machine will remain in
-- init_done for good
when others => -- nothing to do
end case;
end process init_sm;
--- display state machine
--- Once the LCD has been properly initialized finally the display sm kicks in
and
-- it makes possible to display characters on the screen.
-- The character code to be displayed on the screen are first stored in the Di
splay
-- Data RAM (DDRAM).
-- There are 32 character locations on the display. The upper line of characte
rs
-- is stored between addresses 0x00 and 0x0F of the DDRAM. The second line of
-- characters is stored between addresses 0x40 and 0x4F of the DDRAM.
-- The character code stored in a DDRAM location "references" a specific chara
cter
-- bitmap stored in the predefined Character Generator ROM (CGROM) character s
et.
-- The CGROM contains the font bitmap for each of the predefined characters th
at
-- the LCD screen can display.
-- The sequence of commands to display characters to the screen is as follows:
-- 1. Set DDRAM Address command
-Set the initial DDRAM address by initializing an internal address counte
r.
-The DDRAM address counter either remains constant or auto-increments or
-auto-decrements by one location, as defined by the I/D set bit of the
-Entry Mode Set command.
-- 2. Write Data to DDRAM command
-Write data into DDRAM if the command follows a previous Set DDRAM Addres
s.
-- 3. Return Cursor Home command
-Return the cursor to the home position, the top-left corner. DDRAM conte
nts are
-unaffected.
--- NOTE: the sm follows religiously (and without much brain involvement) the S
partan 3E
-Starter Kit Board User Guide (pg.41-52). As can be easily noticed the
actions
-taken in most of the states have only few differences, so by "adding"
a
-little more flexibility in the way the state machine is coded/designe
d it is
-possible to reduce the number of states (and the line of code) consid
erably
-display_sm: process(dstate, dcount, dregsel, dnibble, denable, idone)
begin
next_dstate
next_dcount
next_dregsel
next_dnibble
next_denable
<=
<=
<=
<=
<=
dstate;
dcount;
dregsel;
dnibble;
denable;
case dstate is
when didle =>
if (idone = '1') then
next_dstate <= set_address_one; -- set address 0x80
next_dcount <= 0;
next_dnibble <= "1000"; -- 0x8 (upper nibble of 0x80)
end if;
when set_address_one =>
next_dcount
<= dcount + 1;
if (dcount = 1) then
next_denable <= '1';
end if;
if (dcount = 10) then
next_denable <= '0';
end if;
if(dcount = 11) then -- done with the upper nibble data
next_dnibble <= (others => '0');
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (dcount = 58) then
-next_dnibble <= "0000"; -end if;
if (dcount = 60) then
next_denable <= '1';
end if;
if (dcount = 69) then
next_denable <= '0';
end if;
if(dcount = 70) then -- done
next_dnibble <= (others =>
end if;
10 + 1 + 50 - 2 = 58
0x0 (lower nibble of 0x80)
-- the timing between the falling edge of the lower nibble's enable
-- and the rising edge of the upper nibble's rising edge
-- of two adjacent operations is 40us (2000 clock cycles)
if (dcount = 2068) then -- 69 + 1 + 2000 - 2 =
next_dstate <= write_data_V;
next_dcount <= 0;
next_dnibble <= "0101"; -- 0x5 (upper nibble of 0x56)
next_dregsel <= '1';
end if;
when write_data_V => -- V = 0x56
next_dcount
<= dcount + 1;
if (dcount = 1) then
next_denable <= '1';
end if;
if (dcount = 10) then
next_denable <= '0';
end if;
if(dcount = 11) then -- done with the upper nibble data
next_dnibble <= (others => '0');
next_dregsel <= '0';
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (dcount = 58) then
-- 10 + 1 + 50 - 2 = 58
next_dnibble <= "0110"; -- 0x6 (lower nibble of 0x56)
<= dcount + 1;
if (dcount = 1) then
next_denable <= '1';
end if;
if (dcount = 10) then
next_denable <= '0';
end if;
if(dcount = 11) then -- done with the upper nibble data
next_dnibble <= (others => '0');
next_dregsel <= '0';
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (dcount = 58) then
-next_dnibble <= "1000"; -next_dregsel <= '1';
end if;
if (dcount = 60) then
next_denable <= '1';
end if;
if (dcount = 69) then
next_denable <= '0';
end if;
if(dcount = 70) then -- done
next_dnibble <= (others =>
next_dregsel <= '0';
end if;
10 + 1 + 50 - 2 = 58
0x8 (lower nibble of 0x56)
-- the timing between the falling edge of the lower nibble's enable
<= dcount + 1;
if (dcount = 1) then
next_denable <= '1';
end if;
if (dcount = 10) then
next_denable <= '0';
end if;
if(dcount = 11) then -- done with the upper nibble data
next_dnibble <= (others => '0');
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (dcount = 58) then
-next_dnibble <= "0010"; -end if;
if (dcount = 60) then
next_denable <= '1';
end if;
if (dcount = 69) then
next_denable <= '0';
end if;
if(dcount = 70) then -- done
next_dnibble <= (others =>
end if;
10 + 1 + 50 - 2 = 58
0x2 (lower nibble of 0xC2)
-- the timing between the falling edge of the lower nibble's enable
-- and the rising edge of the upper nibble's rising edge
-- of two adjacent operations is 40us (2000 clock cycles)
if (dcount = 2068) then -- 69 + 1 + 2000 - 2 =
next_dstate <= write_data_D;
next_dcount <= 0;
next_dnibble <= "0100"; -- 0x4 (upper nibble of 0x44)
next_dregsel <= '1';
end if;
when write_data_D => -- D = 0x44
next_dcount
<= dcount + 1;
if (dcount = 1) then
next_denable <= '1';
end if;
if (dcount = 10) then
next_denable <= '0';
end if;
if(dcount = 11) then -- done with the upper nibble data
next_dnibble <= (others => '0');
next_dregsel <= '0';
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (dcount = 58) then
-next_dnibble <= "0100"; -next_dregsel <= '1';
end if;
if (dcount = 60) then
next_denable <= '1';
end if;
if (dcount = 69) then
next_denable <= '0';
end if;
if(dcount = 70) then -- done
next_dnibble <= (others =>
next_dregsel <= '0';
end if;
10 + 1 + 50 - 2 = 58
0x4 (lower nibble of 0x44)
-- the timing between the falling edge of the lower nibble's enable
-- and the rising edge of the upper nibble's rising edge
-- of two adjacent operations is 40us (2000 clock cycles)
if (dcount = 2068) then -- 69 + 1 + 2000 - 2 =
next_dstate <= write_data_L; -- 0x4C
next_dcount <= 0;
next_dnibble <= "0100"; --0x4 (upper nibble of 0x4C)
end if;
when write_data_L => -- L = 0x4C
next_dcount
<= dcount + 1;
if (dcount = 1) then
next_denable <= '1';
end if;
if (dcount = 10) then
next_denable <= '0';
end if;
if(dcount = 11) then -- done with the upper nibble data
next_dnibble <= (others => '0');
next_dregsel <= '0';
end if;
-- the timing between the falling edge of the upper nibble's enable
-- and the rising edge of the lower nibble's rising edge of an
-- operation is 1us (50 clock cycles)
if (dcount = 58) then
-- 10 + 1 + 50 - 2 = 58
next_dnibble <= "1100"; -- 0xC (lower nibble of 0x4C)
return_home =>
by default the state machine will remain in the
return_home state for good
NOTE: this is not a real return_home command
as specfied in the Spartan 3E starter kit
user guide. Since in this specific case
we know that once we reach this state we
are not sending anything new to the display
we can simply stall the sm in this state
dcount
dnibble
inibble
ienable
denable
iregsel
dregsel
end if;
end process
<=
<=
<=
<=
<=
<=
<=
next_dcount;
next_dnibble;
next_inibble;
next_ienable;
next_denable;
next_iregsel;
next_dregsel;
registers;
end rtl;
######VERILOG CODE ::
localparam DISPLAY=1'b1;
localparam MAX=26'h3FFFFFF;
localparam N=5'h1A;
reg state=INIT;
reg[3:0] init_cntr=4'h0;
reg nibble_cntr=1'b0;
reg[N-1:0] clk_cntr=0;
assign
assign
assign
assign
assign
assign
lcd_rw=0;
leds[7:4]=lcd_data;
leds[0]=lcd_e;
leds[1]=lcd_rs;
leds[2]=lcd_rw;
leds[3]=lcd_busy;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
4: begin
if(clk_cntr==0)
lcd_data<=4'h2;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
5: begin
if(clk_cntr==0)
lcd_data<=4'h8;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
6: begin
if(clk_cntr==0)
lcd_data<=4'h0;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
7: begin
if(clk_cntr==0)
lcd_data<=4'h6;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
8: begin
if(clk_cntr==0)
lcd_data<=4'h0;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
9: begin
if(clk_cntr==0)
lcd_data<=4'hC;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
10: begin
if(clk_cntr==0)
lcd_data<=4'h0;
else if(clk_cntr==MAX)
init_cntr<= init_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
11: begin
if(clk_cntr==0)
lcd_data<=4'h1;
else if(clk_cntr==MAX) begin
state<= state+ 1;
lcd_busy<=0;
end
else
lcd_e<=^clk_cntr[N-1:N-2];
//
clk_cntr<= clk_cntr+ 1;
end
endcase
DISPLAY:
//
if(lcd_busy)
if(disp_strb|lcd_busy)
case(nibble_cntr)
0: begin
if(clk_cntr==0) begin
lcd_busy<=1;
lcd_rs<=1;//disp_data[8];
lcd_data<=4'h4;//disp_data[7:4];
end
else if(clk_cntr==MAX)
nibble_cntr<= nibble_cntr+ 1;
else
lcd_e<=^clk_cntr[N-1:N-2];
clk_cntr<= clk_cntr+ 1;
end
1: begin
if(clk_cntr==0)
lcd_data<=4'h8;//disp_data[3:0];
####PART2
# clock
NET "clk" LOC="C9";
# clk
#NET "clk" PERIOD=20.0ns HIGH 50%;
# lcd
NET "lcd_rs" LOC="L18";
NET "lcd_rw" LOC="L17";
NET "lcd_e" LOC="M18";
NET "lcd_data<0>" LOC="R15";
NET "lcd_data<1>" LOC="R16";
NET "lcd_data<2>" LOC="P17";
NET "lcd_data<3>" LOC="M15";
# leds
NET "leds<0>"
NET "leds<1>"
NET "leds<2>"
NET "leds<3>"
NET "leds<4>"
NET "leds<5>"
NET "leds<6>"
NET "leds<7>"
LOC="F12";
LOC="E12";
LOC="E11";
LOC="F11";
LOC="C11";
LOC="D11";
LOC="E9";
LOC="F9";
###PART3
`timescale 1ns / 1ps
module disp (
input wire clk,
output wire lcd_rs,
output wire lcd_rw,
output wire lcd_e,
output wire[3:0] lcd_data,
output wire[7:0] leds
);
localparam CMD=1'b0;
#
#
#
#
#
#
#
#
led
led
led
led
led
led
led
led
0
1
2
3
4
5
6
7
localparam CHAR=1'b1;
reg disp_strb=0;
reg[8:0] disp_data;
wire lcd_busy;
lcd disp(.clk(clk), .disp_strb(disp_strb), .disp_data(disp_data), .lcd_b
usy(lcd_busy),
.lcd_rs(lcd_rw), .lcd_rw(lcd_rs), .lcd_e(lcd_e), .lcd_da
ta(lcd_data), .leds(leds));
endmodule
---------------------------------------------------------------------------------- Company:
-- Engineer:
--- Create Date:
14:43:01 05/22/2015
-- Design Name:
-- Module Name:
lcd - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--- Dependencies:
--- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
---------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity lcd is
Port ( lcd : out STD_LOGIC_vector ( 7 downto 0);
rs : out STD_LOGIC;
rw : out STD_LOGIC;
enable: out std_logic);
end lcd;
architecture Behavioral of lcd is
begin
lcd ( 7 downto 4 ) <= "0010" after 10 ns ;-------- 4 bit interface----------lcd ( 3 downto 0) <= "1000" after 10 ns ;
enable <= '0' after 10 ns;
rw <= '0' after 10 ns;
rs <= '0' after 10 ns;
lcd ( 7 downto 4 ) <= "0010" after 10 ns ;-------- 4 bit interface----------lcd ( 3 downto 0) <= "1000" after 10 ns ;
enable <= '1' after 10 ns ;
rw <= '0' after 10 ns;
rs <= '0' after 10 ns;
lcd ( 7 downto 4 ) <= "0010" after 10 ns ;-------- 4 bit interface----------lcd ( 3 downto 0) <= "1000" after 10 ns ;
enable <= '0' after 10 ns;
rw <= '0' after 10 ns;
rs <= '0' after 10 ns;
----------reset display--------------
lcd ( 7 downto 4 ) <= "0101" after 10 ns ;--------displaying p----------lcd ( 3 downto 0) <= "0000" after 10 ns ;
enable <= '0' after 10 ns;
rw <= '0' after 10 ns;
rs <= '0' after 10 ns;
lcd ( 7 downto 4 ) <= "0101" after 10 ns ;--------displaying p----------lcd ( 3 downto 0) <= "0000" after 10 ns ;
enable <= '1' after 10 ns;
rw <= '0' after 10 ns;
rs <= '0' after 10 ns;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity clock is port (clk1 : in std_logic;
rw: out std_logic;
--read write control
rs:out std_logic;
----command data control
en:out std_logic;
data:out std_logic_vector(7 downto 0)
); end clock;
architecture Behavioral of clock is
component bin_ascii
Port ( bin : in STD_LOGIC_VECTOR (7 downto 0);
ascii : out STD_LOGIC_VECTOR (7 downto 0);
ascii1 : out STD_LOG
IC_VECTOR (7 downto 0)); end component; signal seconds, minutes, hours : std_l
ogic_vector(7 downto 0); signal sec,min,hour : integer range 0 to 60 :=0; signa
l count : integer :=1; signal clk : std_logic :='0'; signal out0,out1,out2,out3,
out4,out5 : std_logic_vector(7 downto 0); begin seconds <= conv_std_logic_vect
or(sec,8); minutes <= conv_std_logic_vector(min,8); hours <= conv_std_logic_vect
or(hour,8);
--clk generation.For 50 MHz clock this generates 1 Hz clock. proc
ess(clk1) begin if(clk1'event and clk1='1') then count <=count+1; if(count = 250
00000) then clk <= not clk; count <=1; end if; end if; end process; process(cl
k) --period of clk is 1 second. begin if(clk'event and clk='1') then
sec
<= sec+ 1;
if(sec = 59) then
sec<=0;
min <= min + 1;
if(min = 59) then
hour <= hour + 1;
min <= 0;
if(hour = 23) then
hour <= 0;
end if;
end if;
end if; end if; end process; p1: bin_ascii port map( seco
nds(7 downto 0), out0, out1); p2: bin_ascii port map( minutes(7 downto 0), out2,
out3); p3: bin_ascii port map( hours(7 downto 0), out4, out5); process(clk1)
variable x,y : integer := 0 ; begin rw<='0'; if clk1'event and clk1 = '1' then
if x <= 160000 then
x := x + 1;
elsif x > 160000 then
x := 0 ;
if y < 43 then
y := y + 1 ;
else
y := 0;
end if;
end if;
case y is
-- as
cii code of data to be displayed
when 1=>
data<="001
11000"; ---38 2 lines and 5x7 matrix
en<='1';
rs<='
0';
when 2=>
rs<='0';
en<='0';
when
3=>
data<="00001100"; ---0C Display on, cursor off
e
n<='1';
rs<='0';
when 4=>
rs<='0';
en<='0';
when 5=>
data<="00000001"; ---clear display
en<='1';
rs<='0';
when 6=>
rs<
='0';
en<='0';
when 7=>
data<="00000110"; --06 Inc cursor(shift right)
en<='1';
rs<='0';
when 8=>
rs<='0';
en<='0';
when 9=>
data<="10000000"; ---80 Force cursor to 1st line
en<='1';
rs<='0';
when 10=>
rs<='0';
e
n<='0'; -------------------------------------------------------------------when 11=>
data<="00100000";
-- SPACE
en<='1
';
rs<='1';
when 12=>
rs<='1';
en<='0';
when 13=>
data<=out5;
-- hr
e
n<='1';
rs<='1';
when 14=>
rs<='1';
en<='0';
when 15=>
data<=out4;
--hr
en<='1';
rs<='1';
when 16=>
rs<='1';
en<='0';
when 17=>
data<="00111010";
-- :
en<='1';
rs<='1';
when 18=>
rs<
='1';
en<='0';
when 19=>
data<=out3;
- min
en<='1';
rs<='1';
when 20=>
rs<='1';
en<='0';
when 21=>
data<=out2;
-- min
en<='1';
rs<='1';
when 22=>
rs<='1';
en<='0';
when 23=>
data<="
00111010"; -- :
rs<='1';
en<='1';
when 24=>
rs<='1';
en<='0';
when 25=>
dat
a<=out1;
-- sec
rs<='1';
en<='1';
when 26
=>
rs<='1';
en<='0';
when 27=>
data<=out0;
-- sec
rs<='1';
en<='1';
when
28=>
rs<='1';
en<='0';
when 2
9=>
data<="00100000";
-- SPACE
en<='1';
rs<='1';
when 30=>
rs<='1';
en<='0';
when 31=>
data<="00100000";
-- SPACE
en<='1';
rs<='1';
when 32=>
rs<='1';
en<='0';
when 33=>
data<="00100000";
-- SPACE
en<='1';
rs<='1';
when 34=>
rs<='1'
;
en<='0';
when 35=>
data<="00100000";
-SPACE
en<='1';
rs<='1';
when 36=>
rs<='1';
en<='0';
when 37=>
data<="0010
0000";
-- SPACE
en<='1';
rs<='1';
when 3
8=>
rs<='1';
en<='0';
when 39=>
data<="00100000";
-- SPACE
en<='1';
rs<='1';
when 40=>
rs<='1';
en<='0';
when 4
1=>
data<="00100000";
-- SPACE
en<='1';
rs<='1';
when 42=>
rs<='1';
en<='0'; ---
-------------------------------------------------------------when oth
ers=>
data<="01000100";
-- ascii code for " "
rs<
='1';
en<='0';
end case; end if; end process; end Behavioral
; - See more at: https://www.pantechsolutions.net/project-kits/implementationof-digital-clock#sthash.bxVh9VEQ.dpuf
sec : integer ;
Min1Temp : integer;
Min10Temp: integer;
Hr1Temp : integer;
Hr10Temp : integer;
begin
--Digital clock in VHDL
The following Verilog code takes in 257 bits of data and sends the data to the L
CD.
`timescale 1ns / 1ps
module LCD(
clk,
chars,
lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7);
// inputs and outputs
input
clk;
input [256:0] chars;
output
lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7;
wire [256:0]
reg
chars;
lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7;
// internal variables
reg [5:0]
lcd_code;
reg [1:0]
write = 2'b10; // write code has 10 for rs rw
// delays
reg [1:0]
reg [3:0]
reg [23:0]
before_delay = 3;
on_delay = 13;
off_delay = 750_001;
// time before on
// time on
// time off
";
// array of characters
genvar i;
for (i = 64; i > 0; i = i-1)
begin : for_name
assign chars_data[64-i] = chars_hold[i*4-1:i*4-4
];
end
endgenerate
always @ (posedge clk) begin
// store character data
if (Cs == 10 && count == 0) begin
chars_hold <= chars;
end
// set time when enable is off
if (Cs < 3) begin
case (Cs)
0: off_delay <=
1: off_delay <=
2: off_delay <=
endcase
end else begin
if (Cs > 12) begin
off_delay
end else begin
off_delay
end
end
750_001;
250_001;
5_001;
// 15ms delay
// 5ms delay
// 0.1ms delay
<= 2_001;
// 40us delay
<= 250_001;
// 5ms delay
// power-on initial
ization
1:
2:
3:
4:
5:
6:
7:
8:
lcd_code
lcd_code
lcd_code
lcd_code
lcd_code
lcd_code
lcd_code
lcd_code
<=
<=
<=
<=
<=
<=
<=
<=
6'h03;
6'h03;
6'h02;
6'h02;
6'h08;
6'h00;
6'h06;
6'h00;
// function set
// entry mode set
// display on/off c
ontrol
9: lcd_code <= 6'h0C;
10:lcd_code <= 6'h00;
// display clear
11:lcd_code <= 6'h01;
default: lcd_code <= 6'h10;
endcase
end else begin
// set character data to lcd_code
if (Cs == 44) begin
// change addres
ress change
end else if (Cs == 45) begin
lcd_code <= {2'b00, 4'b0000};
end else begin
if (Cs < 44) begin
lcd_code <= {write, chars_data[Cs-12]};
end else begin
lcd_code <= {write, chars_data[Cs-14]};
end
end
end
// hold and loop back
<= 10;
end
endmodule
This Verilog code tests the module and show how it works. The last character on
the LCD can be manipulated by the switches on the Spartan-3E board.
`timescale 1ns / 1ps
module LCDtest(
clk,
I3, I2, I1, I0,
lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7
);
// input and outputs
input clk;
input I3, I2, I1, I0;
output lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7;
wire
wire
// internal variables
wire [256:0] chars;
// LCD module
LCD
lcd(
clk,
chars,
lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7);
";
endmodule
This is the code for the UCF file for the pin assignments of the Spartan-3E.
# clock
NET "clk" LOC = C9 | IOSTANDARD = LVCMOS33 ;
NET "clk" PERIOD = 20.0ns HIGH 50%;
# LCD control inputs
NET "lcd_e"
LOC = M18 | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "lcd_rs"
LOC = L18 | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
NET "lcd_rw"
LOC = L17 | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ;
# The LCD four-bit data interface
NET "lcd_4"
LOC = R15 | IOSTANDARD
NET "lcd_5"
LOC = R16 | IOSTANDARD
NET "lcd_6"
LOC = P17 | IOSTANDARD
NET "lcd_7"
LOC = M15 | IOSTANDARD
=
=
=
=
LVCMOS33
LVCMOS33
LVCMOS33
LVCMOS33
# inputs
NET "I0"
NET "I1"
NET "I2"
NET "I3"
=
=
=
=
LVTTL;
LVTTL;
LVTTL;
LVTTL;
LOC
LOC
LOC
LOC
=
=
=
=
L13
L14
H18
N17
|
|
|
|
IOSTANDARD
IOSTANDARD
IOSTANDARD
IOSTANDARD
|
|
|
|
DRIVE
DRIVE
DRIVE
DRIVE
=
=
=
=
4
4
4
4
|
|
|
|
SLEW
SLEW
SLEW
SLEW
=
=
=
=
SLOW
SLOW
SLOW
SLOW
;
;
;
;