ISP之DGain数字增益Verilog实现(附代码)

简介

DGain(Digital Gain)模块用于控制图像的整体亮度,分为Sensor端和ISP端。

通常在CMOS Sensor摄像头中会有模拟增益Sensor AGC(Analog Gain Control)和数字增益Sensor DGC(Digital Gain Control)的配置,由对应的相关寄存器进行配置,如下图的OV2686, AMP就是Sensor端的模拟增益,digital gain就是Sensor端的数字增益。

模拟增益是指CMOS Sensor在经过光电转换后是一个非常小的信号,为了便于后续ADC转换成数字信号,会通过一个放大器来放大信号,这个放大器的增益就是模拟增益。

而Sensor端的数字增益是在经过ADC转换后成为数字信号后,对数字信号直接乘以一个增益。有些摄像头只有模拟增益,没有数字增益。

对于模拟增益和数字增益的区别可以参考:

analog_gain(模拟增益) 与digital_gain(数字增益)的区别与联系_模拟增益和数字增益-优快云博客

简单来讲在Sensor端使用使用模拟增益不会放大 ADC 的电路噪声,ADC 的量化噪声,以及 ADC 以后的噪声。所以模拟增益在获得信号增大好处的同时,相比同样的数字增益,系统最终的 Noise 要小,这样 SNR 就更大。

但是在不得不用到数字增益的时候,我们一般也不会使用Sensor端的数字增益,而是在ISP中自己添加一个数字增益。因为ADC出来的数字信号是带有很多噪声的,如果在Sensor端直接使用数字增益输出的RAW图噪声将会非常影响图像质量。

一般的设计是关闭Sensor端数字增益,输出的RAW图经过DPC坏点校正、BLC黑电平校正、以及BNR(Bayer域降噪)后再进行ISP端的数字增益,这样相比在Sensor端的数字增益,ISP端的数字增益输出的图像质量更好。

硬件实现

硬件实现比较简单,对于增益可能是一个浮点数,因此需要对其进行定点量化,这方面参考往期博客:

在本设计中,还在输入添加了一个偏移量。因此公式变为如下:

O=I*gain+offset

硬件中对每个输入像素都进行以上变换即可。

需要注意以下几点:

1、乘法结果位宽和加法结果位宽,由于涉及两个无符号数相乘,乘法结果位宽直接定义成两个输入信号位宽之和即可,加法在此基础上再扩展一位。

2、对于乘法的处理,一般FPGA中会将“*”综合成FPGA器件中的DSP资源,如果不想这样实现,则可以使用乘法IP核来计算。

3、对于结果的钳位处理

Verilog源码如下:

/*************************************************************************
    > File Name: isp_dgain.v
 ************************************************************************/
`timescale 1 ns / 1 ps

/*
 * ISP - Digital Gain
 * O = I * gain + offset
 */

module isp_dgain
#(
	parameter BITS = 8,
	parameter WIDTH = 1280,
	parameter HEIGHT = 960
)
(
	input pclk,
	input rst_n,

	input [7:0] gain, //4.4,  定点为4,小数部分占4位,整数部分占四位
	input [BITS-1:0] offset,  //偏移

	input in_href,
	input in_vsync,
	input [BITS-1:0] in_raw,

	output out_href,
	output out_vsync,
	output [BITS-1:0] out_raw
);

	reg [BITS-1+8:0] data_0;    //扩展8位用于暂存乘法中间结果
	always @ (posedge pclk or negedge rst_n) begin
		if (!rst_n) begin
			data_0 <= 0;
		end
		else begin
			data_0 <= in_raw * gain;  //*在FPGA中会自动被综合成乘法组合逻辑或者DSP
		end
	end

	reg [BITS-1+9:0] data_1;   //再扩展1位用于暂存加法中间结果
	always @ (posedge pclk or negedge rst_n) begin
		if (!rst_n) begin
			data_1 <= 0;
		end
		else begin
			data_1 <= data_0 + {offset, {4'd0}};  //注意是定点数加法
		end
	end

	reg [BITS-1:0] data_2;   //对结果进行钳位
	always @ (posedge pclk or negedge rst_n) begin
		if (!rst_n) begin
			data_2 <= 0;
		end
		else begin
            //判断增益后整数部分是否大于位宽最大值,是则输出能表示最大值,否则取整数部分
			data_2 <= data_1[BITS-1+9:4] > {BITS{1'b1}} ? {BITS{1'b1}} : data_1[BITS-1+4:4];
		end
	end

	localparam DLY_CLK = 3;   //乘法使用一个时钟周期,加法使用一个时钟周期,钳位使用一个时钟周期
	reg [DLY_CLK-1:0] href_dly;
	reg [DLY_CLK-1:0] vsync_dly;
	always @ (posedge pclk or negedge rst_n) begin
		if (!rst_n) begin
			href_dly <= 0;
			vsync_dly <= 0;
		end
		else begin
			href_dly <= {href_dly[DLY_CLK-2:0], in_href};
			vsync_dly <= {vsync_dly[DLY_CLK-2:0], in_vsync};
		end
	end

	assign out_href = href_dly[DLY_CLK-1];
	assign out_vsync = vsync_dly[DLY_CLK-1];
	assign out_raw = out_href ? data_2 : {BITS{1'b0}};
endmodule

参考

开源ISP项目

analog_gain(模拟增益) 与digital_gain(数字增益)的区别与联系_模拟增益和数字增益-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值