在一个小的项目中,需要用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 <&#61; 1&#39;b0;
DVAL_reg1 <&#61; 1&#39;b0;
oDVAL <&#61; 1&#39;b0;
end
else
begin
DVAL_reg0 <&#61; iDVAL;
DVAL_reg1 <&#61; DVAL_reg0;
oDVAL <&#61; DVAL_reg1;
end
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
Hsync_reg0 <&#61; 1&#39;b0;
Hsync_reg1 <&#61; 1&#39;b0;
oHsync <&#61; 1&#39;b0;
end
else
begin
Hsync_reg0 <&#61; iHsync;
Hsync_reg1 <&#61; Hsync_reg0;
oHsync <&#61; Hsync_reg1;
end
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
Vsync_reg0 <&#61; 1&#39;b0;
Vsync_reg1 <&#61; 1&#39;b0;
oVsync <&#61; 1&#39;b0;
end
else
begin
Vsync_reg0 <&#61; iVsync;
Vsync_reg1 <&#61; Vsync_reg0;
oVsync <&#61; Vsync_reg1;
end
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mR0 <&#61; 17&#39;d0;
else
mR0 <&#61; 9&#39;d132 * iR;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mR1 <&#61; 17&#39;d0;
else
mR1 <&#61; 9&#39;d76 * iR;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mR2 <&#61; 17&#39;d0;
else
mR2 <&#61; 9&#39;d225 * iR;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mG0 <&#61; 17&#39;d0;
else
mG0 <&#61; 9&#39;d258 * iG;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mG1 <&#61; 17&#39;d0;
else
mG1 <&#61; 9&#39;d149 * iG;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mG2 <&#61; 17&#39;d0;
else
mG2 <&#61; 9&#39;d188 * iG;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mB0 <&#61; 17&#39;d0;
else
mB0 <&#61; 9&#39;d50 * iB;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mB1 <&#61; 17&#39;d0;
else
mB1 <&#61; 9&#39;d225 * iB;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
mB2 <&#61; 17&#39;d0;
else
mB2 <&#61; 9&#39;d36 * iB;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
sY <&#61; 18&#39;d0;
else
sY <&#61; ((mR0 &#43; mG0 &#43; mB0) >> 9 ) &#43; 18&#39;d16;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
sCb <&#61; 18&#39;d0;
else
sCb <&#61; ((mB1 - mR1 - mG1) >> 9 ) &#43; 18&#39;d128;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
sCr <&#61; 18&#39;d0;
else
sCr <&#61; ((mR2 - mG2 - mB2) >> 9 ) &#43; 18&#39;d128;
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
oY <&#61; 8&#39;d0;
else if(sY[8])
oY <&#61; 8&#39;d240;
else
oY <&#61; sY[7:0];
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
oCr <&#61; 8&#39;d0;
else if(sCr[8])
oCr <&#61; 8&#39;d240;
else
oCr <&#61; sCr[7:0];
end
always&#64;(posedge clk or negedge rst_n)
begin
if(~rst_n)
oCb <&#61; 8&#39;d0;
else if(sCb[8])
oCb <&#61; 8&#39;d240;
else
oCb <&#61; sCb[7:0];
end
endmodule
对应模块fmax&#61;155MHz&#xff0c;完全达到我所需求的最大fmax&#61;148.5MHz&#xff0c;当然如果要提升fmax&#xff0c;可以考虑在程序中增加几级流水线。