RGB转YCrCb笔记

  在一个小的项目中,需要用FPGA实现一个RGB格式的图像数据转换成YCrCb格式,然后再YCrCb444转成YCrCb422输出。这里暂且先记录下自己RGB转YCrCb这个模块的实现方式。转换公式:

  Y = 0.257R + 0.504G + 0.0.098B + 16
  Cb = -0.148R - 0.291G + 0.439B + 128
  Cr = 0.439R - 0.368G - 0.071B + 128

  Y = (132R + 258G + 50B ) >> 9 + 16
  Cb = (-76R - 149G + 225B ) >> 9 + 128
  Cr = (225R - 188G - 36B) >> 9 + 128

对应实现Verilog代码:

  

`timescale 1ns/1ps

module RGB2YUV(
 input     clk,
 input     rst_n,
 
 input[7:0]    iR,
 input[7:0]    iG,
 input[7:0]    iB,
 input     iDVAL,
 input     iHsync,
 input     iVsync,
 
 output reg[7:0]   oY,
 output reg[7:0]   oCr,
 output reg[7:0]   oCb,
 output reg   oDVAL,
 output reg   oHsync,
 output reg    oVsync
 );

//wire[9:0] R,G,B; 
 
reg[16:0] mR0,mR1,mR2;
reg[16:0] mG0,mG1,mG2;
reg[16:0] mB0,mB1,mB2;

reg[17:0] sY,sCr,sCb;
reg DVAL_reg0,DVAL_reg1;
reg Hsync_reg0,Hsync_reg1;
reg Vsync_reg0,Vsync_reg1;

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 begin
 DVAL_reg0 <= 1'b0;
 DVAL_reg1 <= 1'b0;
 oDVAL <= 1'b0;
 end
else
 begin
 DVAL_reg0 <= iDVAL;
 DVAL_reg1 <= DVAL_reg0;
 oDVAL <= DVAL_reg1;
 end
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 begin
 Hsync_reg0 <= 1'b0;
 Hsync_reg1 <= 1'b0;
 oHsync <= 1'b0;
 end
else
 begin
 Hsync_reg0 <= iHsync;
 Hsync_reg1 <= Hsync_reg0;
 oHsync <= Hsync_reg1;
 end
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 begin
 Vsync_reg0 <= 1'b0;
 Vsync_reg1 <= 1'b0;
 oVsync <= 1'b0;
 end
else
 begin
 Vsync_reg0 <= iVsync;
 Vsync_reg1 <= Vsync_reg0;
 oVsync <= Vsync_reg1;
 end
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mR0 <= 17'd0;
else
 mR0 <= 9'd132 * iR;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mR1 <= 17'd0;
else
 mR1 <= 9'd76 * iR;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mR2 <= 17'd0;
else
 mR2 <= 9'd225 * iR;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mG0 <= 17'd0;
else
 mG0 <= 9'd258 * iG;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mG1 <= 17'd0;
else
 mG1 <= 9'd149 * iG;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mG2 <= 17'd0;
else
 mG2 <= 9'd188 * iG;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mB0 <= 17'd0;
else
 mB0 <= 9'd50 * iB;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mB1 <= 17'd0;
else
 mB1 <= 9'd225 * iB;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 mB2 <= 17'd0;
else
 mB2 <= 9'd36 * iB;
end


always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 sY <= 18'd0;
else
 sY <= ((mR0 + mG0 + mB0) >> 9 ) + 18'd16;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 sCb <= 18'd0;
else
 sCb <= ((mB1 - mR1 - mG1) >> 9 ) + 18'd128;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 sCr <= 18'd0;
else
 sCr <= ((mR2 - mG2 - mB2) >> 9 ) + 18'd128;
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 oY <= 8'd0;
else if(sY[8])
 oY <= 8'd240;
else
 oY <= sY[7:0];
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 oCr <= 8'd0;
else if(sCr[8])
 oCr <= 8'd240;
else
 oCr <= sCr[7:0];
end

always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
 oCb <= 8'd0;
else if(sCb[8])
 oCb <= 8'd240;
else
 oCb <= sCb[7:0];
end


endmodule

 对应模块fmax=155MHz,完全达到我所需求的最大fmax=148.5MHz,当然如果要提升fmax,可以考虑在程序中增加几级流水线。

 

posted on 2013-11-09 10:00  无情剑客lufy  阅读(1698)  评论(0编辑  收藏  举报

导航