赞
踩
一个像素点由三种颜色控制,每个颜色8bit,共24bit,三个字节,这就是RGB888。同样的还有RGB565等。
1、HSYNC(水平同步信号、行同步信号):产生此信号,说明开始显示新的一行。
2、VSYNC(垂直同步信号、帧同步信号):当产生此信号的话就表示开始显示新的一帧图像。
3、LCD 屏幕中继续存在HBP、 HFP、 VPB 和 VFP 这四个参数的主要目的是为了锁定有效的像素数据。 (白色区域为显示区域)
重要参数:
当 HSYNC 信号发出以后,需要等待 HSPW+HBP 个 CLK 时间才会接收到真正有效的像素数据。当显示完一行数据以后需要等待 HFP 个 CLK 时间才能发出下一个 HSYNC 信号,所以显示一行所需要的时间就是: HSPW + HBP + HOZVAL + HFP。
重要参数:
显示一帧所需要的时间就是 T = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP) 。
**行场同步模式(HV Mode) **
**数据使能同步模式(DE Mode) **
LCD 的 DE 信号作为数据的有效信号。只有同时扫描到帧有效显示区域和行有效显示区域时, DE 信号才有效(高电平)。当选择 DE 同步模式时,此时行场同步信号 VS 和 HS 必须为高电平。
像素时钟就是 RGB-LCD 的时钟信号 ,以 ATK7016 这款屏幕为例,显示一帧图像所需要的时钟数就是: N(CLK) = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)= (3 + 20 + 600 + 12) * (20 + 140 + 1024 + 160) = 635 * 1344 = 853440。显示一帧图像需要 853440 个时钟数,那么显示 60 帧就是: 853440 * 60 = 51206400≈51.2M,所以像素时钟就是 51.2MHz。
名称 | 类型 | 解释 |
---|---|---|
lcd_clk | input | lcd驱动时钟信号 |
sys_rst_n | input | 复位信号 |
[23:0]pixel_data | input | 像素数据 |
[10:0]pixel_xpos | output | 当前点横坐标 |
[10:0]pixel_ypos | output | 当前点纵坐标 |
lcd_bl | output | 背光 |
lcd_de | output | 数据使能 |
lcd_vs | output | 场同步信号 |
lcd_hs | output | 行同步信号 |
lcd_clk | output | LCD时钟 |
lcd_rgb | output | 颜色数据 |
module lcd_drive( input lcd_clk , //lcd驱动时钟信号 input sys_rst_n, input [23:0] pixel_data, //像素数据 output [10:0] pixel_xpos, //当前点横坐标 output [10:0] pixel_ypos, //当前点纵坐标 //rgb接口 output lcd_bl, //背光 output lcd_de, //数据使能 output lcd_vs, //场同步信号 output lcd_hs, //行同步信号 output lcd_clk, //LCD时钟 output [23:0] lcd_rgb //颜色数据 ); //parameter define //reg define reg [10:0] h_disp = 11'd1024; //水平分辨率 reg [10:0] v_disp = 11'd600; //垂直分辨率 reg [10:0] h_cnt; //行计数器计数 reg [10:0] h_total = 11'd1344; //行显示周期 reg [10:0] v_cnt; //帧计数器计数 reg [10:0] v_total = 11'd635; //帧显示周期 reg [10:0] h_sync = 11'd; //行同步信号宽度 reg [10:0] h_back; //行显示后沿 reg [10:0] v_sync; //帧同步信号宽度 reg [10:0] v_back; //帧显示后沿 assign lcd_bl = 1'b1; assign lcd_de = lcd_en; assign lcd_vs = 1'b1; //选择 DE 同步模式时,此时行场同步信号 VS 和 HS 必须为高电平。 assign lcd_hs = 1'b1; assign lcd_clk = lcd_clk; assign lcd_rgb = lcd_en ? pixel_data : 24'd0; //h_cnt 行计数器计数 always @(posedge lcd_clk or negedge sys_rst_n) begin if(!sys_rst_n) h_cnt <= 1'b0; else if(h_cnt == h_total - 1'd1) h_cnt <= 1'b0; else h_cnt <= h_cnt + 1'b1; end //v_hnt 帧计数器计数 always @(posedge lcd_clk or negedge sys_rst_n) begin if(!sys_rst_n) v_cnt <= 1'b0; else begin if(h_cnt == h_total - 1'd1)begin if(v_cnt == v_total - 1'd1) v_cnt <= 1'b0; else v_cnt <= v_cnt + 1'b1; end end end //使能数据输入 assign lcd_en = ((h_cnt >= h_sync + h_back) && (h_cnt < h_cnt + h_back + h_disp) && (v_cnt >= v_sync + v_back) && (v_cnt < v_sync + v_back + v_disp)) ? 1'b1 : 1'b0; //请求像素点颜色数据输入 assign data_req = ((h_cnt >= h_sync + h_back - 1'b1) && (h_cnt < h_cnt + h_back + h_disp) && (v_cnt >= v_sync + v_back - 1'b1) && (v_cnt < v_sync + v_back + v_disp)) ? 1'b1 : 1'b0; //像素点坐标 assign pixel_xpos = data_req ? (h_cnt - h_back - h_sync + 1'b1) : 11'd0; assign pixel_ypos = data_req ? (v_cnt - v_back - v_sync + 1'b1) : 11'd0; endmodule
ROM显示
ROM 是通过例化 IP 核来实现的只读存储器,它使用 FPGA 的片上存储资源,即BRAM。(达芬奇开发板使用的FPGA 芯片的 BRAM 存储容量为 1.8Mbit)
OM 作为只读存储器,在调用 IP 核时需要指定初始化文件,在这里就是写入存储器中的图片数据,各种格式的图片(bmp、 jpg 等)在 Xilinx 开发软件中都是以 COE 文件或者 HEX 文件的形式导入到 ROM中的
COE 文件格式
使用matlab将图片转化成COE文件
clear %清理命令行窗口 clc %清理工作区 % 使用 imread 函数读取图片,并转化为三维矩阵 image_array = imread('logo.bmp'); % 使用 size 函数计算图片矩阵三个维度的大小 % 第一维为图片的高度,第二维为图片的宽度,第三维为图片维度 [height,width,z]=size(image_array); % 100*100*3 red = image_array(:,:,1); % 提取红色分量,数据类型为 uint8 green = image_array(:,:,2); % 提取绿色分量,数据类型为 uint8 blue = image_array(:,:,3); % 提取蓝色分量,数据类型为 uint8 % 使用 reshape 函数将各个分量重组成一个一维矩阵 %为了避免溢出,将 uint8 类型的数据扩大为 uint32 类型 r = uint32(reshape(red' , 1 ,height*width)); g = uint32(reshape(green' , 1 ,height*width)); b = uint32(reshape(blue' , 1 ,height*width)); % 初始化要写入.COE 文件中的 RGB 颜色矩阵 rgb=zeros(1,height*width); % 导入的图片为 24bit 真彩色图片,每个像素占用 24bit,RGB888 % 将 RGB888 转换为 RGB565 % 红色分量右移 3 位取出高 5 位,左移 11 位作为 ROM 中 RGB 数据的第 15bit 到第 11bit % 绿色分量右移 2 位取出高 6 位,左移 5 位作为 ROM 中 RGB 数据的第 10bit 到第 5bit % 蓝色分量右移 3 位取出高 5 位,左移 0 位作为 ROM 中 RGB 数据的第 4bit 到第 0bit for i = 1:height*width rgb(i) = bitshift(bitshift(r(i),-3),11) + bitshift(bitshift(g(i),-2),5) + bitshift(bitshift(b(i),-3),0); end fid = fopen( 'image.coe', 'w+' ); % .mif 文件字符串打印 fprintf( fid, 'MEMORY_INITIALIZATION_RADIX=16;\n'); fprintf( fid, 'MEMORY_INITIALIZATION_VECTOR=\n',height*width); % 写入图片数据 for i = 1:height*width if i == height*width fprintf(fid,'%x;\n',rgb(i)); %最后一个数据后面加分号 else fprintf(fid,'%x,\n',rgb(i)); end end fclose( fid ); % 关闭文件指针
module lcd_display ( input lcd_clk, input sys_rst_n, input [10:0] pixel_xpos, input [10:0] pixel_ypos, output reg [23:0] pixel_data ); //parameter define localparam PIC_X_START = 11'd1; //图片起始点横坐标 localparam PIC_Y_START = 11'd1; //图片起始点纵坐标 localparam PIC_WIDTH = 11'd100; //图片宽度 localparam PIC_HEIGHT = 11'd100; //图片高度 localparam BACK_COLOR = 24'hE0FFFF; //背景色,浅蓝色 //reg define reg [13:0] rom_addr ; //ROM 地址 wire [10:0] x_cnt; //横坐标计数器 wire [10:0] y_cnt; //纵坐标计数器 wire rom_rd_en ; //ROM 读使能信号 wire [23:0] rom_rd_data ;//ROM 数据 assign x_cnt = pixel_xpos - PIC_X_START; //像素点相对于图像区域起始点水平坐标 assign y_cnt = pixel_ypos - PIC_Y_START; //像素点相对于图像区域起始点垂直坐标 assign rom_rd_en = 1'b1; //读使能拉高,即一直读 ROM 数据 //为 LCD 不同显示区域绘制图片、字符和背景色 always @(posedge lcd_pclk or negedge rst_n) begin if (!sys_rst_n) pixel_data <= BACK_COLOR; else if( (pixel_xpos >= PIC_X_START) && (pixel_xpos < PIC_X_START + PIC_WIDTH) && (pixel_ypos >= PIC_Y_START) && (pixel_ypos < PIC_Y_START + PIC_HEIGHT) ) pixel_data <= rom_rd_data ; //显示图片 else pixel_data <= BACK_COLOR; //屏幕背景色 end //根据当前扫描点的横纵坐标为 ROM 地址赋值 always @(posedge lcd_pclk or negedge rst_n) begin if (!sys_rst_n) rom_addr <= 14'd0; else if( (pixel_xpos >= PIC_X_START) && (pixel_xpos < PIC_X_START + PIC_WIDTH) && (pixel_ypos >= PIC_Y_START) && (pixel_ypos < PIC_Y_START + PIC_HEIGHT) ) rom_addr <= rom_addr + 1'b1; else if((pixel_ypos >= PIC_Y_START + PIC_HEIGHT)) rom_addr <= 14'd0; end //ROM:存储图片 blk_mem_gen_0 blk_mem_gen_0 ( .clka (lcd_pclk), // input wire clka .ena (rom_rd_en), // input wire ena .addra (rom_addr), // input wire [13 : 0] addra .douta (rom_rd_data) // output wire [23 : 0] douta ); endmodule
module lcd_display_top ( input sys_clk, //系统时钟 input sys_rst_n, //系统复位 output lcd_de, //LCD 数据使能信号 output lcd_hs, //LCD 行同步信号 output lcd_vs, //LCD 场同步信号 output lcd_bl, //LCD 背光控制信号 output lcd_clk, //LCD 像素时钟 inout [23:0] lcd_rgb //LCD RGB888 颜色数据 ); wire [10:0] pixel_xpos; //当前像素点横坐标 wire [10:0] pixel_ypos; //当前像素点纵坐标 wire [10:0] h_disp ; //LCD 屏水平分辨率 wire [10:0] v_disp ; //LCD 屏垂直分辨率 wire [23:0] pixel_data; //像素数据 wire [23:0] lcd_rgb_o ; //输出的像素数据 wire [23:0] lcd_rgb_i ; //输入的像素数据 //像素数据方向切换 assign lcd_rgb = lcd_de ? lcd_rgb_o : {24{1'bz}}; assign lcd_rgb_i = lcd_rgb; lcd_display u_lcd_display( .lcd_clk (sys_clk), .sys_rst_n (sys_rst_n), .pixel_xpos (pixel_xpos), .pixel_ypos (pixel_ypos), .pixel_data (pixel_data) ); lcd_driver u_lcd_driver( .lcd_clk (sys_clk), .sys_rst_n (sys_rst_n), .pixel_data (pixel_data), .pixel_xpos (pixel_xpos), .pixel_ypos (pixel_ypos), .lcd_de (lcd_de ), .lcd_hs (lcd_hs ), .lcd_vs (lcd_vs ), .lcd_bl (lcd_bl ), .lcd_clk (lcd_clk ), .lcd_rgb (lcd_rgb_o) ); endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。