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 / 1psView Code
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数据正确时显示的图片