FPGA自学教程 12 总结自己在使用HDMI显示图片(UART+RAM)遇到的坑

双非硕士 研一下学期视觉转FPGA

长路漫漫,但希望前途光明

HDMI显示的原理网上都有很多,这里就不进行介绍了

 显示效果如下:

大坑一:

我是使用串口发送的8位数据来存到RAM中的,因为自己想偷懒,所以想使用RGB332来转RGB888,思路就是将串口接收到的每一位数据补成RGB888,代码如下:

assign RGB888[23:0] = {rx_data[7:5],5'b00000,rx_data[4:2],5'b00000,rx_data[1:0],6'b000000};

RAM中的写地址就使用rx_data的结束标志来递增,代码如下:

always@(posedge sys_clk or negedge sys_rst_n)
    if(!sys_rst_n)
       ram_wraddra <= 14'd0;
    else if(rx_end_flag == 1'b1 && ram_wraddra == 10000)
       ram_wraddra <= 14'd0;
    else if(rx_end_flag == 1'b1)
       ram_wraddra <= ram_wraddra + 1'b1;

 !!!那么,我遇到的坑是什么嘞,就是我在传图片数据的时候,传的图片还是RGB888的数据,那么HDMI显示的图片数据就变成原来的三倍了,所以显示出来都是乱七八糟的颜色,后面被朋友点了一下,才知道是这个原因,我粘贴一下使用MATLAB实现将图片转为RGB332的txt格式代码:

clc;
clear all;
RGB = imread('dog.bmp');
[ROW,COL,D]=size(RGB);
R = RGB(:,:,1);
G = RGB(:,:,2);
B = RGB(:,:,3);
imgdata = zeros(1,ROW*COL);
%RGB332转换
for r=1:ROW
    for c=1:COL
        imgdata((r-1)*COL+c)=bitand(R(r,c),224)+bitshift(bitand(G(r,c),224),-3)+bitshift(bitand(B(r,c),192),-6);
    end
end
fidc=fopen('data_dog.txt','w+');
for i =1:ROW*COL
    fprintf(fidc,'%02x ',imgdata(i)); %注意02x后面有一个空格
end
fclose(fidc);

粘贴一下我写的图像生成模块代码,里面包含了接收串口的数据+写ram和读ram:

`timescale 1ns / 1ps


module  vga_pic
(
    input   wire             sys_clk     ,   //输入系统时钟,频率25MHZ
    input   wire             vga_clk     ,   //输入工作时钟,频率40MHz
    input   wire             sys_rst_n   ,   //输入复位信号,低电平有效
    input   wire             rx_232     ,    //串口接收模块
    input   wire    [11:0]   pix_x       ,   //输入有效显示区域像素点X轴坐标
    input   wire    [11:0]   pix_y       ,   //输入有效显示区域像素点Y轴坐标

    output  wire    [23:0]   pix_data_out    //输出VGA显示图像数据

);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

parameter   H_VALID =   11'd1024     ,   //行有效数据
            V_VALID =   10'd768     ;   //场有效数据

parameter   H_PIC   =   10'd100     ,   //图片长度
            W_PIC   =   10'd100     ,   //图片宽度
            PIC_SIZE=   14'd10000   ;   //图片像素个数

//wire  define
wire            rd_en       ;   //RAM读使能
wire    [23:0]  pic_data    ;   //自RAM读出的图片数据

//reg   define
reg     [13:0]  ram_rdaddr    ;   //读RAM地址
reg             pic_valid   ;   //图片数据有效信号
reg     [23:0]   pix_data    ;   //背景色彩信息

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//rd_en:ROM读使能
assign  rd_en = (((pix_x >= (((H_VALID - H_PIC)/2) - 1'b1))
                && (pix_x < (((H_VALID - H_PIC)/2) + H_PIC - 1'b1))) 
                &&((pix_y >= ((V_VALID - W_PIC)/2))
                && ((pix_y < (((V_VALID - W_PIC)/2) + W_PIC)))));

//pic_valid:图片数据有效信号
always@(posedge vga_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        pic_valid   <=  1'b1;
    else
        pic_valid   <=  rd_en;

parameter   RED =    24'hff0000, //红色
             ORANGE = 24'hFF6100, //橙色
             YELLOW = 24'hffff00, //黄色
             GREEN =  24'h00ff00, //绿色
             CYAN =   24'h00ffff, //青色
             BLUE =   24'h0000ff, //蓝色
             PURPPLE =24'hCC00CC, //紫色
             BLACK =  24'h000000, //黑色
             WHITE =  24'hffffff, //白色
             GRAY =   24'hC0C0C0; //灰色
             
//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
always@(posedge vga_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        pix_data    <= 24'd0;
    else    if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
        pix_data    <=  RED;
    else    if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
        pix_data    <=  ORANGE;
    else    if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
        pix_data    <=  YELLOW;
    else    if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
        pix_data    <=  GREEN;
    else    if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
        pix_data    <=  CYAN;
    else    if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
        pix_data    <=  BLUE;
    else    if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
        pix_data    <=  PURPPLE;
    else    if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
        pix_data    <=  BLACK;
    else    if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
        pix_data    <=  WHITE;
    else    if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
        pix_data    <=  GRAY;
    else
        pix_data    <=  BLACK;

//rom_addr:读ROM地址
always@(posedge vga_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        ram_rdaddr    <=  14'd0;
    else    if(ram_rdaddr == (PIC_SIZE - 1'b1))
        ram_rdaddr    <=  14'd0;
    else    if(rd_en == 1'b1)
        ram_rdaddr    <=  ram_rdaddr + 1'd1;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
wire [7:0]rx_data;
wire rx_end_flag;
wire ram_wren;
wire ram_wraddr;
//wire [13:0]ram_wrdata;
reg [13:0]ram_wraddra;
uart_rx 
    #(
        .UART_BPS(9600      ),         //串口波特率
        .CLK_FREQ(25_000_000)    //时钟频率
    )
    uart_rx
    (
        .sys_clk     (sys_clk  ),   //系统时钟50MHz
        .sys_rst_n   (sys_rst_n),   //全局复位
        .rx          (rx_232       ),   //串口接收数据
    
        .po_data(rx_data)     ,   //串转并后的8bit数据
        .po_flag(rx_end_flag)         //串转并后的数据有效标志信号
    );
always@(posedge sys_clk or negedge sys_rst_n)
    if(!sys_rst_n)
       ram_wraddra <= 14'd0;
    else if(rx_end_flag == 1'b1 && ram_wraddra == 10000)
       ram_wraddra <= 14'd0;
    else if(rx_end_flag == 1'b1)
       ram_wraddra <= ram_wraddra + 1'b1;

wire [23:0]disp_rxdata;
assign disp_rxdata = {rx_data[7:5],5'b00000,rx_data[4:2],5'b00000,rx_data[1:0],6'b000000};
RAM RAM (
  .clka(sys_clk),    // input wire clka
  .wea(rx_end_flag),      // input wire [0 : 0] wea
  .addra(ram_wraddra),  // input wire [13 : 0] addra
  .dina(disp_rxdata),    // input wire [23 : 0] dina
  .clkb(vga_clk),    // input wire clkb
  .enb(rd_en),      // input wire enb
  .addrb(ram_rdaddr),  // input wire [13 : 0] addrb
  .doutb(pic_data)  // output wire [23 : 0] doutb
);
//pix_data_out:输出VGA显示图像数据
assign  pix_data_out = (pic_valid == 1'b1) ? pic_data : pix_data;

endmodule

需要全部代码的可以进一步交流。。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值