FPGA series # gamma模块总结文档

虽说回头再看的时候这东西很基础,但也是一开始花了些时间一点点啃下来的。勿忘初心。

一、引言

1.编写目的:

总结gamma矫正模块的总体设计、详细设计及仿真测试、后期优化。

2.项目背景:

编写gamma矫正模块。

3.定 义:

  1. gamma校正: 大多数CRT显示器的变换函数产生的亮度值正比于信号幅度的某种能量(称为gamma)。因此高亮度的范围被扩展了,而低亮度的范围被压缩了。在发射之前对视频信号进行gamma校准,显示器的亮度输出就大体上是线性的了,并且发射过程中产生的噪声也会受到抑制。
    目的: 为图像进行gamma编码的目的是用来对人类视觉的特性进行补偿,从而根据人类对光线或黑白的感知,最大化地利用表示黑白的数据位或带宽。
    原理: 归一化、预补偿、反归一化
    算法: 假设图像中有一个像素A,值是150,那么对这个像素进行校正须执行如下步骤。
    归一化: 将像素值转换为 0~1 之间的实数。 算法如下: ( i + 0. 5)/256 。对于像素 A 而言 ,其对应的归一化值为 0. 587891。
    预补偿: 根据公式L_in=〖L_org〗^(1/gamma),求出像素归一化后的数据以 1/gamma 为指数的对应值。若 gamma 值为 2. 2,则 1/gamma 为 0. 45454,对归一化后的 A 值进行预补偿的结果就 是 0. 587891^0. 454545 = 0.785479。
    反归一化: 将经过预补偿的实数值反变换为 0 ~ 255 之间的整数值。具体算法为: f*256 - 0. 5 。续前例,将 A 的预补偿结果0.785479 代入上式,得到 A 预补偿后对应的像素值为 201 ,这个 201 就是最后送 入显示器的数据。
  2. 图像数据 : 用数值表示的各像素的灰度值的集合。
  3. 灰 度 值 : 指黑白图像中点的颜色深度,范围一般从0到255,白色为255,黑色为0,故 黑白图片也称为灰度图像。灰度也可认为是亮度,简单的说就是色彩的深浅程 度,R、G、B值均相等。
  4. 参考资料: [1] PG058 Block Memory Generator v8.4 LogiCORE IP Product Guide.
         [2] UG908 Vivado Design Suite User Guide Programming and Debugging.
         [3] PG021 AXI DMA v7.1 LogiCORE IP Product Guide.

二、总体设计

1.需求概述:

从BRAM数据源读取图像数据,进行gamma矫正,然后存入RAM中。

2.模块结构:

0
  后期将RAM2接口改为AXIS型,只取RAM2_gamma模块,将其放入整个工程中。修改后的模块结构应为:
(接口对应工程中的前后两个模块分别为:alinx_ov5640_0,System_i)
1

3.Schematic:

2

4.模块描述

  • Top
    功能:顶层模块,调用下面三个模块,加一个ila的IP核以实时仿真时探取信号
    输入:clk,rst

  • Module1
    功能:存放图像数据源,导入.coe文件
    输入:clk,rst_b 输出:dout_b

  • Module2
    功能:存放matlab计算结果,调取像素值相对应的gamma矫正结果
    输入:clk,rst_g,din_g 输出:dout_g

  • Module3
    功能:存放矫正后的数据
    输入:clk,rst_g,dina_a 输出:doutb_a

  • 后期将Module2模块改为AXIS接口,则该模块应为:
    RAM_gamma
    功能:存放matlab计算结果,调取像素值相对应的gamma矫正结果
    输入:clk,resetn, 输出:
    s_axis_gamma_rdata, m_axis_gamma_tdata,
    s_axis_gamma_rvalid, m_axis_gamma_tvalid,
    m_axis_gamma_rready, s_axis_gamma_tready,
    s_axis_gamma_rlast, m_axis_gamma_tlast,
    s_axis_gamma_ruser, m_axis_gamma_tuser,
    s_axis_gamma_rkeep m_axis_gamma_tkeep

三、详细设计

1.代码语言:

verilogHDL,c语言

2.运行环境:

Vivado 2017.4,modelsim,ALINX黑金AX7020开发板,matlab 2014

3.各模块设计:

3

  • RAM1:存放图像数据;
  • RAM2:存放0~255之间整数gamma矫正的结果;
  • RAM3:存放图像数据gamma矫正的结果
    ① 数据源位宽:RAM1输入输出数据位宽:8位; RAM2输入输出数据位宽:8位;RAM3输入输出数据位宽:8位;
    ② 数据源深度:RAM1深度:128128(图像数据源:128124);RAM2深度:256;RAM3深度:2^14
    ③ 时钟同步
    ④ 图像矩阵作为数据源读入顺序:从上到下
      后期将RAM2模块改为AXIS接口直接加到工程里,端口为:data,keep,valid,ready,last,user。参考datasheet,如图:
    4
    由上图分析,
  • aclk为时钟线,所有信号都在aclk上升沿被采样;
  • data为数据线,主机发送,从机接收。
  • keep为主机数据有效指示,为高代表对应的字节为有效字节,否则表示发送的为空字节。
  • valid为主机数据同步线,为高表示主机准备好发送数据;
  • ready为从机数据同步线,为高表示从机准备好接收数据;这两根线完成了主机与从机的握手信号,一旦二者都变高有效,数据传输开始。
  • last为主机最后一个字指示,下一clk数据将无效,TVALID将变低。
    另,user为valid和ready同时为高时才为有效数据。
      考虑到RAM2模块的输入输出为8位,模块alinx_ov5640_0和System_i输入输出为16位,将输入数据取高8位为0,低8位输入。输出时,将8位的输出数据放在最终输出数据的低8位,其高八位置0。这里的keep始终为2’b11。分析得具体接口连接如图:
    5

4.实现方案:

  • 在matlab中计算、对比:计算0~255之间所有整数的gamma矫正结果。
  • 将仿真数的结果放入matlab,恢复成图像,输出处理后的图像。
  • 在modelsim中仿真:ila中探针探取想要看的结果。
  • 在FPGA中实现:将matlab中读出的图像数据存入RAM1作为数据源,其输出与RAM2中的gamma矫正结果相匹配,将匹配后的值存入RAM3。

5.步 骤:

① 从matlab中提取图像的一维数组元素存入.COE文档;

src_path = 'rice.jpg';
I = imread(src_path);
x = I(:,:,1);
my_write(x,'E:\practice\gamma\RAM1.COE','%0.2x\n');

② 将文档中的数据作为数据源,存入RAM1中,RAM1选择single port ROM,导入.COE文件;
6
7
③ 在matlab上计算0~255之间所有整数的gamma矫正结果,并存入RAM2;

i  = [0:1:255];							//生成0~255的整数数组
A = (i+0.5)/256;						//归一化
f = A.^(1/2.2);							//预补偿
s = f*256 - 0.5;						//反归一化
r=round(s);								//四舍五入取整
my_write(r,'E:\gamma.dat','%0.2x\n')	//数据读出到.dat文档中

④ 将每个时钟周期从RAM1输出的数据作为地址在RAM2中查找计算结果;
⑤ RAM2输出的值存入到RAM3中,RAM3可选选择Block Memory Generator中的Simple Dual Port RAM。
8
⑥ 在testbench中导出RAM3中的数据:

//宏定义
define stor_file "E:/practice/gamma/out.dat"
//变量声明
integer fid1;
initial begin
//打开输出数据文件 
fid1 = $fopen(`stor_file,"w");
end
//-----------导出输出数据----------
always@(posedge clk) begin       
$fdisplay(fid1,"%x",doutb_a[7:0]);
end

⑦ 在top文件中加入IP核ila,探取需要知道的信号波形。这里举例探取dout_b和doutb_a信号。 9
10

ila_0 ila_0(
  					.clk(clk),	                	 	
					.probe0(dout_b),
					.probe1(doutb_a)
					);

⑧ 将top模块例化,加入到整个工程中去,clk和resetn分别对应工程中的FCLK_CLK1和FCLK- CLK1RESETN。在综合布线后生成bit文件,将bit文件名改为fpga.bit,替换板子上sd卡里 的bit文件。在vivado中open target,连接开发板,进行时序仿真。
⑨ 在matlab里对比分析matlab矫正的结果和verilog矫正的结果是否一致。
 matlab代码:

src_path = 'rice.jpg';
gamma = 2.2 ;
N = 256;
S = 0.5;
%读取数据
I = imread(src_path);
%gamma矫正
i = double(I);
A = (i + 0.5) / 256;
F = A.^(1/gamma);
B = F*N - S;
b = uint8(B);
%画图分析
figure;
subplot(1, 2, 1); 
imshow(I, []);
title('原图');
subplot(1, 2, 2); 
imshow(b, []);
title('matlab处理后');

将verilog矫正后的数据提取出来,输出图像:

fid = fopen('out.dat');
a = textscan(fid,'%s');             %读取矫正后的数据
b = a{1};                           %textscan生成的是cell型的数组
c = cell2mat(b);                    %cell转换为矩阵
d = hex2dec(c);                     %转为十进制
s = cat(3,d,d,d);
e = reshape(s,124,128,3);           %重组回原图像的像素值
f = uint8(e);                       %强制转换为uint8的格式
imshow(f);                          %显示图像
title('verilog处理后');

⑩ 后期将RAM2改为AXIS型接口,单独作为一个模块整合进工程代码中。

四、测试仿真

1.测试要点:

① 将RAM3存储的处理后的数据与matlab处理后的数据对比
② 将上两组数据转化为图像,进行对比

2.测试结果:

① matlab correction:
11Verilog correction:
12
② matlab:
13
Verilog:
14

3.仿 真:

modelsim仿真,ila的探针探取的结果与之前仿真结果对比

4.仿真结果:

  • ila分别采样三个模块的输出数据
    15
    16
  • ila采样的module1和module3的数据,在随机抓取的样值中看到空出来的数据00和0f 17
  • 这里的00分为两段,前一段是RAM深度为16384,但图像数据为128*124=15872,空余的深度值 18
  • 后一段的00是延时 19
    将RAM2改为AXIS型接口,单独作为一个模块整合进工程代码中之后的仿真结果。
  • ila探取输入值和输出值
    20
    21
    23
    24

不足:仿真中波形为随机抓取,可以考虑将触发改为从地址0开始。

后期将RAM2接口改为AXIS型,只取RAM2_gamma模块,将其放入整个工程中。修改后的模块结构应为:
(接口对应工程中的前后两个模块分别为:alinx_ov5640_0,System_i)

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值