Created
March 17, 2017 20:04
-
-
Save darrena092/d46cf531d7bce093b1c6a3b58965c32d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module LCDFPGA( | |
clk, //Clock input (50MHz), rising edge. | |
LCD_RS, //Register select. 0 for command bytes. 1 for data bytes. | |
LCD_RW, //Read/Write. 0 to write. 1 to read. | |
LCD_E, //Enable. Active high. | |
LCD_DataBus //Data bus. | |
); | |
//Port declarations | |
input clk; | |
output LCD_RS, LCD_RW, LCD_E; | |
output [7:0] LCD_DataBus; | |
wire clk; | |
reg LCD_RS; | |
wire LCD_RW; //Wire as it will be permanently low. We're only ever writing. | |
reg LCD_E; | |
reg [7:0] LCD_DataBus; | |
//State definitions | |
parameter S_IDLE = 4'h0; | |
parameter S_WRITE = 4'h1; | |
parameter S_WAIT = 4'h2; | |
parameter S_HALT = 4'h3; | |
parameter P_IDLETIME = 16'h073A; //1,850 clocks (37us). | |
parameter P_WAITTIME = 16'h2710; //10,000 clocks (2ms). | |
parameter P_WRITETIME = 16'h003C; //60 clocks (1200ns). | |
//Internal Signals. | |
reg [15:0] counter = 8'b00000000; //Used for counting cycles. | |
reg [3:0] state = S_IDLE; //State register. | |
reg writeStarted = 1'b0; | |
reg [3:0] currentByteIndex = 4'b0; | |
//Data. | |
wire [7:0] testData [0:3]; //Has to be a wire as not synchronous. | |
wire testRS [0:3]; //RS setting for each byte. | |
//Initialisation bytes and an uppercase 'T' in ASCII encoding. | |
//(0x38 - Set to 8 bit mode) | |
//(0x0F - Initialize display (blinking cursor)). | |
//(0x01 - Clear screen) 2ms wait required after this. | |
//(0x54 - Uppercase 'T' ASCII). | |
assign {testData[0], testData[1], testData[2], testData[3]} = {8'h38, 8'h0F, 8'h01, 8'h54}; | |
assign {testRS[0], testRS[1], testRS[2], testRS[3]} = {1'b0, 1'b0, 1'b0, 1'b1}; | |
//Assignments. | |
assign LCD_RW = 1'b0; //Always low as we're always writing. | |
always @(posedge clk) | |
begin | |
//Increment the counter. | |
counter <= counter + 1; | |
//FSM which controls the LCD. | |
case(state) | |
//Stay idle for 10 clocks and keep the enable line low. | |
S_IDLE: begin | |
if(counter >= P_IDLETIME) begin | |
//Time has elapsed, go to next byte. | |
counter <= 0; //Zero the counter for the next step. | |
state <= S_WRITE; | |
end else begin | |
//Make sure that the LCD enable signal is low. | |
LCD_E <= 0; | |
LCD_RS <= 0; | |
LCD_DataBus <= 0; | |
state <= S_IDLE; | |
end | |
end | |
//Write a byte out to the display. | |
S_WRITE: begin | |
if(writeStarted == 0) begin | |
//We haven't started writing yet. Start now. | |
//Check we still have data to write. | |
if(currentByteIndex >= 4) begin | |
//Halt. | |
state <= S_HALT; | |
end else begin | |
LCD_E <= 1; //Enable the LCD. | |
LCD_DataBus <= testData[currentByteIndex]; | |
LCD_RS <= testRS[currentByteIndex]; | |
writeStarted <= 1; | |
state <= S_WRITE; | |
end | |
end else begin | |
//We've already written. Wait. | |
if(counter >= P_WRITETIME) begin | |
//Cycle is finished. | |
//Start by incrementing the current byte. | |
currentByteIndex <= currentByteIndex + 1; | |
writeStarted <= 0; //Reset write started. | |
//We need to wait longer when doing 0x01 (screen refresh). | |
if(LCD_DataBus == 8'h01) begin | |
counter <= 0; //Zero the counter for the next step. | |
state <= S_WAIT; | |
end else begin | |
counter <= 0; //Zero the counter for the next step. | |
state <= S_IDLE; | |
end | |
end else begin | |
//Just wait. | |
state <= S_WRITE; | |
end | |
end | |
end | |
//A state specifically for long waits where required. | |
S_WAIT: begin | |
if(counter >= P_WAITTIME) begin | |
//Wait is over. Go back to write. | |
state <= S_WRITE; | |
end else begin | |
//Still waiting... | |
//Make sure that the LCD enable signal is low. | |
LCD_E <= 0; | |
LCD_RS <= 0; | |
state <= S_WAIT; | |
end | |
end | |
//Halt after completion. | |
S_HALT: begin | |
LCD_DataBus <= 0; | |
LCD_RS <= 0; | |
LCD_E <= 0; | |
state <= S_HALT; | |
end | |
endcase | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment