// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: LCD_RGB
//
// Author: Step
//
// Description: Drive TFT_RGB_LCD_1.8 to display
//
// Web: www.stepfpga.com
//
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date: |Changes Made:
// V1.1 |2016/10/30 |Initial ver
// --------------------------------------------------------------------
module LCD_RGB #
(
parameter LCD_W = 8'd240, //
parameter LCD_H = 8'd240 //
)
(
input clk, // system clock
input rst_n, //system reset, active low
input display_en,
output reg display_done,
output reg ram_lcd_clk_en,
output reg [7:0] ram_lcd_addr,
input [7:0] ram_lcd_data,
output reg lcd_csn,
output reg lcd_res,
output lcd_blk,
output reg lcd_dcn,
output reg lcd_sck, // SPI clock
output reg lcd_sda // Master out slave in
);
localparam INIT_DEPTH = 16'd59; // the number of init command and data
localparam RED = 16'hf800;
localparam GREEN = 16'h07e0;
localparam BLUE = 16'h001f;
localparam BLACK = 16'h0000;
localparam WHITE = 16'hffff;
localparam YELLOW = 16'hffe0;
localparam IDLE = 3'd0;
localparam MAIN = 3'd1;
localparam INIT = 3'd2;
localparam SCAN = 3'd3;
localparam WRITE = 3'd4;
localparam DELAY = 3'd5;
localparam LOW = 1'b0;
localparam HIGH = 1'b1;
assign lcd_blk = HIGH; // backlight active high level
wire [15:0] color_t = WHITE;
wire [15:0] color_b = BLACK;
reg [7:0] x_cnt;
reg [7:0] y_cnt;
reg [7:0] ram_data_r;
reg [7:0] ram_data_r1;
reg [8:0] data_reg; //
reg [8:0] reg_setxy [10:0];
reg [8:0] reg_init [58:0];
reg [2:0] cnt_main;
reg [2:0] cnt_init;
reg [2:0] cnt_scan;
reg [4:0] cnt_write;
reg [23:0] cnt_delay;
reg [23:0] num_delay;
reg [6:0] cnt;
reg high_word;
reg [2:0] state;
reg [2:0] state_back;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
display_done <= 1'b0;
x_cnt <= 8'd0;
y_cnt <= 8'd0;
ram_lcd_clk_en <= 1'b0;
ram_lcd_addr <= 8'd0;
cnt_main <= 3'd0;
cnt_init <= 3'd0;
cnt_scan <= 3'd0;
cnt_write <= 5'd0;
cnt_delay <= 16'd0;
num_delay <= 16'd10;
cnt <= 7'd0;
high_word <= 1'b1;
state <= IDLE;
state_back <= IDLE;
end else begin
case(state)
IDLE:begin
display_done <= 1'b0;
x_cnt <= 8'd0;
y_cnt <= 8'd0;
ram_lcd_clk_en <= 1'b0;
ram_lcd_addr <= 8'd0;
cnt_main <= 3'd0;
cnt_init <= 3'd0;
cnt_scan <= 3'd0;
cnt_write <= 5'd0;
cnt_delay <= 16'd0;
num_delay <= 16'd10;
cnt <= 7'd0;
high_word <= 1'b1;
state <= MAIN;
state_back <= MAIN;
lcd_csn <= 1'b1;
lcd_sck <= LOW;
end
MAIN:begin
case(cnt_main)
3'd0: begin state <= INIT; cnt_main <= cnt_main + 1'b1; end
3'd1: begin display_done <= 1'b0; cnt_main <= cnt_main + 1'b1; end
3'd2: begin
if(display_en) cnt_main <= cnt_main + 1'b1;
else cnt_main <= cnt_main;
end
3'd3: begin state <= SCAN; cnt_main <= cnt_main + 1'b1; end
3'd4: begin display_done <= 1'b1; cnt_main <= 1'b1; end
default: state <= IDLE;
endcase
end
INIT:begin
case(cnt_init)
3'd0: begin lcd_res <= 1'b0; cnt_init <= cnt_init + 1'b1; end
3'd1: begin num_delay <= 24'd1_200_000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end
3'd2: begin lcd_res <= 1'b1; cnt_init <= cnt_init + 1'b1; end
3'd3: begin num_delay <= 24'd1_200_000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end
3'd4: begin
if(cnt>=INIT_DEPTH) begin
cnt <= 7'd0;
cnt_init <= cnt_init + 1'b1;
end else begin
data_reg <= reg_init[cnt];
if(cnt==7'd0) num_delay <= 24'd1_600_000; // long time delay is necessary
cnt <= cnt + 16'd1;
state <= WRITE;
state_back <= INIT;
end
end
3'd5: begin cnt_init <= 1'b0; state <= MAIN; end
default: state <= IDLE;
endcase
end
SCAN:begin
case(cnt_scan)
3'd0: begin
if(cnt >= 11) begin
cnt <= 7'd0;
cnt_scan <= cnt_scan + 1'b1;
end else begin
data_reg <= reg_setxy[cnt];
cnt <= cnt + 7'd1;
state <= WRITE;
state_back <= SCAN;
end
end
3'd1: begin ram_lcd_clk_en <= HIGH; ram_lcd_addr <= y_cnt; cnt_scan <= cnt_scan + 1'b1; end
3'd2: begin cnt_scan <= cnt_scan + 1'b1; end
3'd3: begin ram_lcd_clk_en <= LOW; ram_data_r1 <= ram_data_r; ram_data_r <= ram_lcd_data; cnt_scan <= cnt_scan + 1'b1; end
3'd4: begin
if(x_cnt>=LCD_W) begin
x_cnt <= 8'd0;
if(y_cnt>=LCD_H) begin y_cnt <= 8'd0; cnt_scan <= cnt_scan + 1'b1; end
else begin y_cnt <= y_cnt + 1'b1; cnt_scan <= 3'd1; end
end else begin
if(high_word)
data_reg <= {1'b1,y_cnt&&(y_cnt-1'b1)&&(((x_cnt>=ram_data_r)&&(x_cnt<=ram_data_r1))||((x_cnt<=ram_data_r)&&(x_cnt>=ram_data_r1)))? color_t[15:8]:color_b[15:8]};
else begin
data_reg <= {1'b1,y_cnt&&(y_cnt-1'b1)&&(((x_cnt>=ram_data_r)&&(x_cnt<=ram_data_r1))||((x_cnt<=ram_data_r)&&(x_cnt>=ram_data_r1)))? color_t[7:0]:color_b[7:0]};
x_cnt <= x_cnt + 1'b1;
end
/* //dot
if(high_word)
data_reg <= {1'b1,(x_cnt==ram_lcd_data)? color_t[15:8]:color_b[15:8]};
else begin
data_reg <= {1'b1,(x_cnt==ram_lcd_data)? color_t[7:0]:color_b[7:0]};
x_cnt <= x_cnt + 1'b1;
end
*/
high_word <= ~high_word;
state <= WRITE;
state_back <= SCAN;
end
end
3'd5: begin cnt_scan <= 1'b0; state <= MAIN; end
default: state <= IDLE;
endcase
end
WRITE:begin
if(cnt_write >= 5'd18) cnt_write <= 1'b0;
else cnt_write <= cnt_write + 1'b1;
case(cnt_write)
//lock data_reg
5'd0: begin lcd_dcn <= data_reg[8]; lcd_csn <= 1'b0; end
5'd1: begin lcd_sck <= LOW; lcd_sda <= data_reg[7]; end
5'd2: begin lcd_sck <= HIGH; end
5'd3: begin lcd_sck <= LOW; lcd_sda <= data_reg[6]; end
5'd4: begin lcd_sck <= HIGH; end
5'd5: begin lcd_sck <= LOW; lcd_sda <= data_reg[5]; end
5'd6: begin lcd_sck <= HIGH; end
5'd7: begin lcd_sck <= LOW; lcd_sda <= data_reg[4]; end
5'd8: begin lcd_sck <= HIGH; end
5'd9: begin lcd_sck <= LOW; lcd_sda <= data_reg[3]; end
5'd10: begin lcd_sck <= HIGH; end
5'd11: begin lcd_sck <= LOW; lcd_sda <= data_reg[2]; end
5'd12: begin lcd_sck <= HIGH; end
5'd13: begin lcd_sck <= LOW; lcd_sda <= data_reg[1]; end
5'd14: begin lcd_sck <= HIGH; end
5'd15: begin lcd_sck <= LOW; lcd_sda <= data_reg[0]; end
5'd16: begin lcd_sck <= HIGH; end
5'd17: begin lcd_sck <= LOW; end
5'd18: begin lcd_csn <= 1'b1; state <= DELAY; end
default: state <= IDLE;
endcase
end
DELAY:begin
if(cnt_delay >= num_delay) begin
cnt_delay <= 16'd0;
num_delay <= 16'd10;
state <= state_back;
end else cnt_delay <= cnt_delay + 1'b1;
end
default:state <= IDLE;
endcase
end
end
// data for setxy
always @(*) begin
reg_setxy[0] = {1'b0,8'h2a};
reg_setxy[1] = {1'b1,8'h00};
reg_setxy[2] = {1'b1,8'h50};
reg_setxy[3] = {1'b1,8'h01};
reg_setxy[4] = {1'b1,8'h3f};
reg_setxy[5] = {1'b0,8'h2b};
reg_setxy[6] = {1'b1,8'h00};
reg_setxy[7] = {1'b1,8'h00};
reg_setxy[8] = {1'b1,8'h00};
reg_setxy[9] = {1'b1,LCD_H-8'h01};
reg_setxy[10] = {1'b0,8'h2c};
end
// data for init
always @(*) begin
reg_init[0] = {1'b0,8'h11};
reg_init[1] = {1'b0,8'h36};
reg_init[2] = {1'b1,8'ha0};
reg_init[3] = {1'b0,8'h3A};
reg_init[4] = {1'b1,8'h05};
reg_init[5] = {1'b0,8'hB2};
reg_init[6] = {1'b1,8'h0C};
reg_init[7] = {1'b1,8'h0C};
reg_init[8] = {1'b1,8'h00};
reg_init[9] = {1'b1,8'h33};
reg_init[10] = {1'b1,8'h33};
reg_init[11] = {1'b0,8'hB7};
reg_init[12] = {1'b1,8'h35};
reg_init[13] = {1'b0,8'hBB};
reg_init[14] = {1'b1,8'h19};
reg_init[15] = {1'b0,8'hC0};
reg_init[16] = {1'b1,8'h2C};
reg_init[17] = {1'b0,8'hC2};
reg_init[18] = {1'b1,8'h01};
reg_init[19] = {1'b0,8'hC3};
reg_init[20] = {1'b1,8'h12};
reg_init[21] = {1'b0,8'hC4};
reg_init[22] = {1'b1,8'h20};
reg_init[23] = {1'b0,8'hC6};
reg_init[24] = {1'b1,8'h0F};
reg_init[25] = {1'b0,8'hD0};
reg_init[26] = {1'b1,8'hA4};
reg_init[27] = {1'b1,8'hA1};
reg_init[28] = {1'b0,8'hE0};
reg_init[29] = {1'b1,8'hD0};
reg_init[30] = {1'b1,8'h04};
reg_init[31] = {1'b1,8'h0D};
reg_init[32] = {1'b1,8'h11};
reg_init[32] = {1'b1,8'h13};
reg_init[33] = {1'b1,8'h2B};
reg_init[34] = {1'b1,8'h3F};
reg_init[35] = {1'b1,8'h54};
reg_init[36] = {1'b1,8'h4C};
reg_init[37] = {1'b1,8'h18};
reg_init[38] = {1'b1,8'h0D};
reg_init[39] = {1'b1,8'h0B};
reg_init[40] = {1'b1,8'h1F};
reg_init[41] = {1'b1,8'h23};
reg_init[42] = {1'b0,8'hE1};
reg_init[43] = {1'b1,8'hD0};
reg_init[44] = {1'b1,8'h04};
reg_init[45] = {1'b1,8'h0C};
reg_init[46] = {1'b1,8'h11};
reg_init[47] = {1'b1,8'h13};
reg_init[48] = {1'b1,8'h2C};
reg_init[49] = {1'b1,8'h3F};
reg_init[50] = {1'b1,8'h44};
reg_init[51] = {1'b1,8'h51};
reg_init[52] = {1'b1,8'h2F};
reg_init[53] = {1'b1,8'h1F};
reg_init[54] = {1'b1,8'h1F};
reg_init[55] = {1'b1,8'h20};
reg_init[56] = {1'b1,8'h23};
reg_init[57] = {1'b0,8'h21};
reg_init[58] = {1'b0,8'h29};
end
endmodule