双非硕士 研一下学期视觉转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
需要全部代码的可以进一步交流。。。。