基于FPGA实现YCbCr444转RGB888
目录
一.YCbCr444转RGB888的公式算法
1.YCbCr444转RGB888计算公式
这里为什么不和RGB888转YCbCr一样放大256倍?
二.Verilog代码的实现
一.YCbCr444转RGB888的公式算法
我们通常认为YUV 和YCbCr是一个概念,但是两者还是有很大区别的:
YUV是模拟信号,其中Y的取值范围在0-1之间,而U,V取值在-0.5至0.5之间。YCbCr是数字信号,如果再细分的话,可以分为tv range和full range两种格式。对于tv range,Y的取值在16-235之间,Cb的取值在16-240之间,Cr的取值在16-240之间;而对于full range,Y,Cb,Cr的取值都在0-255之间。
我们这里以RGB888与YCbCr444(对于full range 或者pc range的YCbCr格式)转换为例,YCbCr444转RGB888的转换公式如下所示:
如果我们要在FPGA 上实现YCbCr转RGB,可以将上述的YCbCr转RGB公式在硬件加速的理论下,转换成如下公式:
1.YCbCr444转RGB888计算公式
上述硬件加速的核心思想是放大1024倍,去除小数点,而后再右移10位(缩小1024倍)。
这里为什么不和RGB888转YCbCr一样放大256倍?
这里笔者原先是放大256倍的,但是复原的 数据与原先数据对比有偏差,放大1024倍的可以复原出原来的数据。
二.Verilog代码的实现
`timescale 1ns / 1ps module YCbCr444_RGB888 ( input wire clk, input wire reset_n, input wire img_in_vsync, input wire img_in_href, input wire img_in_de, input wire [7:0] img_in_Y, input wire [7:0] img_in_Cb, input wire [7:0] img_in_Cr, output wire img_out_vsync, output wire img_out_href, output wire img_out_de, output wire [7:0] img_out_red, output wire [7:0] img_out_green, output wire [7:0] img_out_blue ); //--------------------------------------------------------------------- (* ASYNC_REG = "TRUE" *)reg [2:0] img_in_de_reg; (* ASYNC_REG = "TRUE" *)reg [2:0] img_in_vsync_reg; (* ASYNC_REG = "TRUE" *)reg [2:0] img_in_href_reg; reg [19:0] img_y_r0; reg [19:0] img_cb_r0,img_cb_r1; reg [19:0] img_cr_r0,img_cr_r1; reg [19:0] img_red_r0,img_green_r0,img_blue_r0; reg [7:0] img_red_r1,img_green_r1,img_blue_r1; //--------------------------------------------------------------------- always @(posedge clk or negedge reset_n) begin if(~reset_n) begin img_in_de_reg <= 3'd0; img_in_vsync_reg <= 3'd0; img_in_href_reg <= 3'd0; end else begin img_in_de_reg <= {img_in_de_reg[1:0],img_in_de}; img_in_vsync_reg <= {img_in_vsync_reg[1:0],img_in_vsync}; img_in_href_reg <= {img_in_href_reg[1:0],img_in_href}; end end always@(posedge clk) begin img_y_r0 <= img_in_Y * 'd1024; img_cb_r0 <= img_in_Cb * 'd352; img_cb_r1 <= img_in_Cb * 'd1815; img_cr_r0 <= img_in_Cr * 'd1437; img_cr_r1 <= img_in_Cr * 'd731; end always@(posedge clk) begin img_red_r0 <= img_y_r0 + img_cr_r0 - 20'd183763; img_green_r0 <= 20'd138674 + img_y_r0 - img_cb_r0 - img_cr_r1; img_blue_r0 <= img_y_r0 + img_cb_r1 - 20'd232260; end reg [1:0] img_red_p; reg [1:0] img_green_p; reg [1:0] img_blue_p; always@(posedge clk) begin img_red_r1 <= img_red_r0[17:10]; img_green_r1 <= img_green_r0[17:10]; img_blue_r1 <= img_blue_r0[17:10]; img_red_p <= img_red_r0[19:18]; img_green_p <= img_green_r0[19:18]; img_blue_p <= img_blue_r0[19:18]; end //----------------------output data------------------------------------ assign img_out_de = img_in_de_reg[2]; assign img_out_href = img_in_href_reg[2]; assign img_out_vsync = img_in_vsync_reg[2]; assign img_out_red = img_out_href ? (img_red_p[1] ? 8'd0 : (img_red_p[0] ? 8'd255 : img_red_r1)) : 8'd0; assign img_out_green = img_out_href ? (img_green_p[1] ? 8'd0 : (img_green_p[0] ? 8'd255 : img_green_r1)) : 8'd0; assign img_out_blue = img_out_href ? (img_blue_p[1] ? 8'd0 : (img_blue_p[0] ? 8'd255 : img_blue_r1)) : 8'd0; endmodule内容仅供参考,如有错误,欢迎批评指正。