Skip to content

Instantly share code, notes, and snippets.

@jjcarrier
Created December 28, 2011 18:40
Show Gist options
  • Save jjcarrier/1529101 to your computer and use it in GitHub Desktop.
Save jjcarrier/1529101 to your computer and use it in GitHub Desktop.
A simple character LCD controller core written in Verilog
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Carrier Frequency, Inc.
// Engineer: Jon Carrier
//
// Create Date: 21:33:11 06/17/2011
// Design Name:
// Module Name: FPGA_2_LCD
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies: The clock should be set to 24MHz. Slower clocks should also work.
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments: This module performs the full initialization procedure.
// Once init is done, the module takes in DATA and processes
// it according to OPER. When idle, the module indicates RDY.
// ENB, indicates that DATA and OPER are valid and the module
// should start to read the lines.
// Note: the calling module must keep DATA valid until RDY re-asserts
//
//////////////////////////////////////////////////////////////////////////////////
module FPGA_2_LCD(
CLK, LCD_RS, LCD_RW, LCD_E, LCD_DB, RDY, DATA, OPER, ENB, RST
);
input CLK; // For this code to work without modification, CLK should equal 24MHz
input DATA; // The Data to send to the LCD Module
input OPER; // The Type of operation to perform (data or instruction)
input ENB; // Tells the module that the data is valid and start reading DATA and OPER
input RST;
output RDY; // Indicates that the module is Idle and ready to take more data
output LCD_RS, LCD_RW, LCD_E;
output [7:0] LCD_DB;
wire [7:0] DATA;
wire [1:0] OPER;
wire ENB;
reg RDY;
reg [7:0] LCD_DB=0;
reg LCD_RW=0; // always write to (and never read from) the LCD
reg LCD_RS=0; // HI means Data, LOW means Instruction/Command
reg LCD_E=0;
/*----------------------SOME NOTES-------------------
when RS and R/W change STATE...wait for at least 40ns ( ~1clock cycle )
after that period of time bring E high and invert E every 250ns (can be larger) ( ~6 clock cycles)
while E is HI, set DATA
when E goes LOW, maintain DATA for atleast 10ns
CLOCK=24MHz ==> 41.667ns
-------------------------END OF NOTES-------------------*/
//===============================================================================================
//------------------------------Define the Timing Parameters-------------------------------------
//===============================================================================================
parameter [19:0] t_40ns = 1; //40ns == ~1clk
parameter [19:0] t_250ns = 6; //250ns == ~6clks
parameter [19:0] t_42us = 1008; //42us == ~1008clks
parameter [19:0] t_100us = 2400; //100us == ~2400clks
parameter [19:0] t_1640us = 39360; //1.64ms == ~39360clks
parameter [19:0] t_4100us = 98400; //4.1ms == ~98400clks
parameter [19:0] t_15000us = 360000; //15ms == ~360000clks
//===============================================================================================
//------------------------------Define the BASIC Command Set-------------------------------------
//===============================================================================================
parameter [7:0] SETUP = 8'b00111000; //Execution time = 42us, sets to 8-bit interface, 2-line display, 5x7 dots
parameter [7:0] DISP_ON = 8'b00001100; //Execution time = 42us, Turn ON Display
parameter [7:0] ALL_ON = 8'b00001111; //Execution time = 42us, Turn ON All Display
parameter [7:0] ALL_OFF = 8'b00001000; //Execution time = 42us, Turn OFF All Display
parameter [7:0] CLEAR = 8'b00000001; //Execution time = 1.64ms, Clear Display
parameter [7:0] ENTRY_N = 8'b00000110; //Execution time = 42us, Normal Entry, Cursor increments, Display is not shifted
parameter [7:0] HOME = 8'b00000010; //Execution time = 1.64ms, Return Home
parameter [7:0] C_SHIFT_L = 8'b00010000; //Execution time = 42us, Cursor Shift
parameter [7:0] C_SHIFT_R = 8'b00010100; //Execution time = 42us, Cursor Shift
parameter [7:0] D_SHIFT_L = 8'b00011000; //Execution time = 42us, Display Shift
parameter [7:0] D_SHIFT_R = 8'b00011100; //Execution time = 42us, Display Shift
//===============================================================================================
//-----------------------------Create the counting mechanisms------------------------------------
//===============================================================================================
reg [19:0] cnt_timer=0; //39360 clks, used to delay the STATEmachine during a command execution (SEE above command set)
reg flag_250ns=0,flag_42us=0,flag_100us=0,flag_1640us=0,flag_4100us=0,flag_15000us=0;
reg flag_rst=1; //Start with flag RST set. so that the counting has not started
always @(posedge CLK) begin
if(flag_rst) begin
flag_250ns <= 1'b0; //Unlatch the flag
flag_42us <= 1'b0; //Unlatch the flag
flag_100us <= 1'b0; //Unlatch the flag
flag_1640us <= 1'b0; //Unlatch the flag
flag_4100us <= 1'b0; //Unlatch the flag
flag_15000us <= 1'b0; //Unlatch the flag
cnt_timer <= 20'b0;
end
else begin
if(cnt_timer>=t_250ns) begin
flag_250ns <= 1'b1;
end
else begin
flag_250ns <= flag_250ns;
end
//----------------------------
if(cnt_timer>=t_42us) begin
flag_42us <= 1'b1;
end
else begin
flag_42us <= flag_42us;
end
//----------------------------
if(cnt_timer>=t_100us) begin
flag_100us <= 1'b1;
end
else begin
flag_100us <= flag_100us;
end
//----------------------------
if(cnt_timer>=t_1640us) begin
flag_1640us <= 1'b1;
end
else begin
flag_1640us <= flag_1640us;
end
//----------------------------
if(cnt_timer>=t_4100us) begin
flag_4100us <= 1'b1;
end
else begin
flag_4100us <= flag_4100us;
end
//----------------------------
if(cnt_timer>=t_15000us) begin
flag_15000us <= 1'b1;
end
else begin
flag_15000us <= flag_15000us;
end
//----------------------------
cnt_timer <= cnt_timer + 1;
end
end
//##########################################################################################
//-----------------------------Create the STATE MACHINE------------------------------------
//##########################################################################################
reg [3:0] STATE=0;
reg [1:0] SUBSTATE=0;
always @(posedge CLK) begin
case(STATE)
//---------------------------------------------------------------------------------------
0: begin //---------------Initiate Command Sequence (RS=LOW)-----------------------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
LCD_E <= 1'b0; //We are in the initial setup, keep low until 250ns has past
LCD_DB <= 8'b00000000;
RDY <= 1'b0; //Indicate that the module is busy
SUBSTATE <= 0;
if(!flag_15000us) begin //WAIT 15ms...worst case scenario
STATE <= STATE; //Remain in current STATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
flag_rst <= 1'b1; //Stop counting
end
end
//---------------------------------------------------------------------------------------
1: begin //-----------SET FUNCTION #1, 8-bit interface, 2-line display, 5x7 dots---------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= SETUP; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_4100us) begin //WAIT at least 4.1ms (required for Initialization)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
2: begin //-----------SET FUNCTION #2, 8-bit interface, 2-line display, 5x7 dots---------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= SETUP; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_100us) begin //WAIT at least 100us (required for Initialization)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
3: begin //-----------SET FUNCTION #3, 8-bit interface, 2-line display, 5x7 dots---------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= SETUP; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_100us) begin //WAIT at least 100us (required for Initialization)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
4: begin //-----------SET FUNCTION #4, 8-bit interface, 2-line display, 5x7 dots---------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= SETUP; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_100us) begin //WAIT at least 100us (required for Initialization)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
5: begin //-----------------DISPLAY, Display OFF, Cursor OFF, Blinking OFF------------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= ALL_OFF; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_42us) begin //WAIT at least 42us (required for operation to process)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
6: begin //-------------------DISPLAY CLEAR, clear the display screen--------------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= CLEAR; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_1640us) begin //WAIT at least 1640us (required for operation to process)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
7: begin //---------Normal ENTRY, Cursor increments, Display is not shifted--------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= ENTRY_N; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_42us) begin //WAIT at least 42us (required for operation to process)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
8: begin //-----------------DISPLAY, Display ON, Cursor ON, Blinking ON------------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= DISP_ON;//ALL_ON; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_42us) begin //WAIT at least 42us (required for operation to process)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
9: begin //-------------------DISPLAY CLEAR, clear the display screen--------------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= CLEAR; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_1640us) begin //WAIT at least 1640us (required for operation to process)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= 15; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
10: begin//----------------------------- WRITE DATA -------------------------------------
LCD_RS <= 1'b1; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= DATA; //WRITE THE CHARACTER
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= 15;//STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
11: begin//----------------------- WRITE INSTRUCTION ------------------------------------
LCD_RS <= 1'b0; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
RDY <= 1'b0; //Indicate that the module is busy
if(SUBSTATE==0)begin
LCD_E <= 1'b0; //Disable Bus
LCD_DB <= LCD_DB; //Maintain Previous Data on the Bus
STATE <= STATE;
SUBSTATE <= 1;
end
if(SUBSTATE==1)begin
LCD_E <= 1'b1; //Enable Bus
LCD_DB <= DATA; //Data Valid
if(!flag_250ns) begin //WAIT at least 250ns (required for LCD_E)
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
SUBSTATE <= SUBSTATE+1; //Go to next SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
if(SUBSTATE==2)begin
LCD_E <= 1'b0; //Disable Bus, Triggers LCD to read BUS
LCD_DB <= LCD_DB; //Keep Data Valid
if(!flag_42us) begin //WAIT at least 49us (required for operation to process)
STATE <= STATE; //Maintain current STATE
SUBSTATE <= SUBSTATE; //Maintain current SUBSTATE
flag_rst <= 1'b0; //Start or Continue counting
end
else begin
STATE <= 15;//STATE+1; //Go to next STATE
SUBSTATE <= 0; //Reset SUBSTATE
flag_rst <= 1'b1; //Stop counting
end
end
end
//---------------------------------------------------------------------------------------
default: begin//----------This is the IDLE STATE, DO NOTHING UNTIL OPER is set-----------
LCD_RS <= LCD_RS; //Indicate an instruction is to be sent soon
LCD_RW <= 1'b0; //Indicate a write operation
LCD_DB <= LCD_DB; //Maintain Data Bus
LCD_E <= 1'b0; //Disable Bus
RDY <= 1'b1; //Indicate that the system is ready to taking in data
if(ENB==1 && RST==0)begin
case(OPER)
0:STATE<=STATE; //IDLE
1:STATE<=10; //WRITE CHARACTER
2:STATE<=11; //WRITE INSTRUCTION (assumes 49us or less time to process instr)
3:STATE<=0; //RESET
endcase
end
else if(RST==1)begin
STATE<=0;
end
end
endcase
end
endmodule
@gil-a
Copy link

gil-a commented Dec 28, 2018

Hi, Is the code written for writing to lcd in 8-wire or 4-wire ?
(i'm guessing 8...)

@jjcarrier
Copy link
Author

Hi, Is the code written for writing to lcd in 8-wire or 4-wire ?
(i'm guessing 8...)

The module is currently set up for an 8bit databus only (this is mentioned many times in the code comments), no provisions were made for using a 4bit data bus. Though an 8bit interface always starts off in 4bit mode and has to be specifically instructed to switch to 8bit mode. This module is highly driven by the data sheet for the ST7066 lcd controller which has a thorough description for configuration of the controller to operate in 8bit and 4bit modes. I recommend you review this document to get the insight needed for adapting the module to use 4bit mode

@vikash73908
Copy link

Does this code works for Nexys 4 DDR FPGA board ??

@jjcarrier
Copy link
Author

Does this code works for Nexys 4 DDR FPGA board ??

If this dev board has the required number of I/O pins available, then yes it should work. You may need to adapt parameters to accommodate clock frequency or other minor details, but there are no proprietary entities in this implementation and should work on any fabric.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment