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, //待變換數據使
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; endmoduleView Code
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數據正確時顯示的圖片