1 YUV2RGB的模块如下:
1 module yuv2rgb( 2 clk, //时钟输入 3 rstn, //复位输入,低电平复位 4 5 y_in, //变换前Y分量输出 6 cb_in, //变换前Cb分量输出 7 cr_in, //变换前Cr分量输出 8 ena_in, //待变换数据使能,当它为高时,输入数据有效 9 10 R_out, //变换后R分量输出 11 G_out, //变换后G分量输出 12 B_out, //变换后B分量输出 13 ena_out //变换后数据使能输出 14 );
测试模块功能的方法:
step1 用MATLAB读入一张RGB图片,将RGB转成YUV数据保存在txt文件中;
step2 用该模块把YUV数据转换成RGB数据并保存;
step3 用MATLAB读取模块转换的RGB数据做显示。
接下来详细说明step1~3的实现过程。
2 step1 用MATLAB读入一张RGB图片,将RGB转成YUV数据保存在txt文件中;
clc;close all;clear
RGBimg =imread('Penguins_720p.jpg'); %%用画图软件重新调整像素大小得到的720p图片 figure;imshow(RGBimg); YUVimg = rgb2ycbcr(RGBimg); %%matlab中的转换函数 figure;imshow(YUVimg); [Hs Vs Dim] = size(YUVimg); yuvimout = zeros(1,Hs*Vs*Dim); yuvimout(1:3:Hs*Vs*Dim) = reshape(YUVimg(:,:,1)',1,Hs*Vs); %%Y yuvimout(2:3:Hs*Vs*Dim) = reshape(YUVimg(:,:,2)',1,Hs*Vs); %%U yuvimout(3:3:Hs*Vs*Dim) = reshape(YUVimg(:,:,3)',1,Hs*Vs); %%V fid= fopen('Penguins_720p.txt','w'); %%YUV数据写入到txt fprintf(fid,'%02x\n',yuvimout); %%2位十六进制格式 fclose(fid); fid= fopen('Penguins_720p.yuv','rb'); %%用“7yuv”专业软件转换得到的yuv数据 yuvdat = fread(fid,'uint8'); yuvdat = yuvdat'; fclose(fid); subAB = yuvdat-yuvimout; %%比较下matlab转换的yuv数据 figure;stem(find(subAB~=0));
3 step2 用该模块把YUV数据转换成RGB数据并保存;
testbench的代码如下:
`timescale 1ns / 1ps module tb_yuv2rgb; // Inputs reg clk; reg rstn; //复位输入,低电平复位 reg [7:0] y_in; reg [7:0] cb_in; reg [7:0] cr_in; reg ena_in; // Outputs wire [7:0] R_out; wire [7:0] G_out; wire [7:0] B_out; wire ena_out; // Instantiate the Unit Under Test (UUT) yuv2rgb uut ( .clk(clk), .rstn(rstn), .y_in(y_in), .cb_in(cb_in), .cr_in(cr_in), .ena_in(ena_in), .R_out(R_out), .G_out(G_out), .B_out(B_out), .ena_out(ena_out) ); localparam PIXNUM_1080P =(1920*1080*3); localparam PIXNUM_720P =(1280*720*3); //read pixel from .txt file reg[7:0] mem_imgpixel[0:2**24]; reg [31:0] pixaddr; integer fid,i; initial begin //读取图片的YUV数据 $readmemh("Penguins_720p.txt",mem_imgpixel); pixaddr = 0; #PIXNUM_1080P begin //等待图片的数据转换完成 fid = $fopen("Penguins_720pRGBout.txt","w"); for(i=0; i<PIXNUM_720P; i=i+1) $fdisplay(fid,"%2x",mem_rgbout[i]);//输出转换的RGB数据 $fclose(fid); $stop; end end //clk的上升沿给输入的yuv数据 always @(posedge clk or negedge rstn) begin if(!rstn) begin y_in <= 8'b0; cb_in <= 8'b0; cr_in <= 8'b0; ena_in <= 1'b0; pixaddr<= 0; end else begin y_in <= mem_imgpixel[pixaddr]; cb_in <= mem_imgpixel[pixaddr+1]; cr_in <= mem_imgpixel[pixaddr+2]; ena_in <= 1'b1; pixaddr<= pixaddr + 3; end end reg[31:0] outaddr; reg[7:0] mem_rgbout[0:2**24];//clk的下降沿读取转换的rgb数据 always @(negedge clk or negedge rstn) begin if(!rstn) begin outaddr <= 0; end else begin //存入对应下标 mem_rgbout[outaddr] <= R_out; mem_rgbout[outaddr+1] <= G_out; mem_rgbout[outaddr+2] <= B_out; outaddr <= outaddr + 3; //下标增加3 end end initial begin // Initialize Inputs clk = 0; rstn = 1; y_in = 0; cb_in = 0; cr_in = 0; ena_in = 0; #2; rstn = 0; // Wait 100 ns for global reset to finish #100; rstn = 1; // Add stimulus here end always #2 clk =~clk; endmodule
4 step3 用MATLAB读取模块转换的RGB数据做显示。
clc;close all;clear filename = 'Penguins_720pRGBout.txt'; fid = fopen(filename,'r'); rgbdat = fscanf(fid,'%x'); rgbdat = uint8(rgbdat'); %%转换为uint8 fclose(fid); imglen = 1280; imgwidth = 720; len = length(rgbdat); r = rgbdat(1:3:len); r = reshape(r,imglen,imgwidth); r = r'; g = rgbdat(2:3:len); g = reshape(g,imglen,imgwidth); g = g'; b = rgbdat(3:3:len); b = reshape(b,imglen,imgwidth); b = b'; rgbimg = cat(3,r,g,b); imshow(rgbimg);
step3中rgb数据正确时显示的图片