## 1.54寸240*240分辨率RGB LCD的控制 ### 1 FPGA控制 #### 1.1 按键输入控制及显示输出主程序: //========================================================================== // // Author: Step // Module: isp_154 // Description: // Web: www.stepfapga.com //-------------------------------------------------------------------------- // Info: // V1.0---yyyy/mm/dd---Initial version // //========================================================================== //timescale `timescale 1ns / 1ns //define //include //module module isp_154 ( input clk_12m, input key_l, key_r, key_o, input [7:0] adc_i, output lcd_csn, output lcd_sck, output lcd_sda, output lcd_res, output lcd_dcn ); wire adc_done= 1'b1; wire sample_done, display_done; wire sample_en, display_en; //Arbiter, control sample and display in different time Arbiter u_Arbiter ( .clk_in (clk_12m ), // system clock .rst_n_in (1'b1 ), //system reset, active low .sample_done (sample_done ), .display_done (display_done ), .sample_en (sample_en ), .display_en (display_en ) ); wire adc_done_o; wire [7:0] trig_data; Time_Scale u_Time_Scale ( .clk_in (clk_12m ), // system clock .rst_n_in (1'b1 ), //system reset, active low .key_l (key_l ), // encoder B .key_r (key_r ), // encoder OK .key_o (key_o ), // .trig_data (trig_data ), .adc_done (adc_done ), .adc_done_o (adc_done_o ) ); wire ram_adc_clk_en; wire [7:0] ram_adc_addr; wire [7:0] ram_adc_data; ADC_Sample u_ADC_Sample ( .clk_in (clk_12m ), // system clock .rst_n_in (1'b1 ), //system reset, active low .adc_done (adc_done_o ), .adc_data (adc_i ), .trig_data (trig_data ), .sample_en (sample_en ), .sample_done (sample_done ), .ram_adc_clk_en (ram_adc_clk_en ), .ram_adc_addr (ram_adc_addr ), .ram_adc_data (ram_adc_data ) ); wire [7:0] QA; wire ram_lcd_clk_en; wire [7:0] ram_lcd_addr; wire [7:0] ram_lcd_data; dp_ram u1 ( .ResetA ( 1'b0 ), .WrA ( 1'b1 ), .ClockEnA ( ram_adc_clk_en ), .ClockA ( clk_12m ), .AddressA ( ram_adc_addr ), .DataInA ( ram_adc_data ), .QA ( QA ), .ResetB ( 1'b0 ), .WrB ( 1'b0 ), .ClockEnB ( ram_lcd_clk_en ), .ClockB ( clk_12m ), .AddressB ( ram_lcd_addr ), .DataInB ( 8'b0 ), .QB ( ram_lcd_data ) ); LCD_RGB u_LCD_RGB ( .clk ( clk_12m ), .rst_n ( 1'b1 ), .display_en ( display_en ), .display_done ( display_done ), .ram_lcd_clk_en ( ram_lcd_clk_en ), .ram_lcd_addr ( ram_lcd_addr ), .ram_lcd_data ( ram_lcd_data ), .lcd_csn ( lcd_csn ), .lcd_res ( lcd_res ), .lcd_dcn ( lcd_dcn ), .lcd_sck ( lcd_sck ), .lcd_sda ( lcd_sda ) ); endmodule //isp_154 #### 1.2 RGB LCD的控制 // -------------------------------------------------------------------- // >>>>>>>>>>>>>>>>>>>>>>>>> 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