简介
为了入门Verilog图像处理,熟悉modelsim的仿真是必不可少的,因此选择将直方图均衡作为一个上手项目,使用vivado对zynq进行开发,配合modelsim进行仿真,在此过程中需要借助matlab进行数据处理和结果展示。
原理
数据预处理
预处理借助matlab实现,因为modelsim可以读取txt文件,可以利用matlab将图像转为txt文件,再利用modelsim读取txt文件进行仿真。
首先,如果使用的图像不是灰度图,就需要将图像转换为灰度图
%将RGB888格式的图像转为灰度图像
clear;clc;
image=imread("lena.png");
%imshow(image),title('原始图片');
gray=rgb2gray(image);
imwrite(gray,"./gray.jpg");
imshow(gray)
然后将灰度图转为txt文件
%将灰度格式的图像转为8bit的hex格式
clear;clc;
file_path="./image_gray.txt";
file=fopen(file_path,"w");
image=imread("gray.jpg");
imshow(image),title('图片');
[image_width,image_height,channel]=size(image);
for x=1:image_height
for y=1 : image_width
fprintf(file,'%d\n',image(x,y));
end
end
fclose(file);
转换后可以打开image_gray.txt文件查看数据,可以发现其实际上就是将图像中的灰度值每一行存一个的方式存入txt文件中。
代码
顶层模块
顶层模块中使用了三个RAM ip核,用于存储数据:u_transform256x8存储映射关系、Ram32x256存储灰度直方图、u_image_mem存储原始图像,均衡化之后的图像并没有存储在FPGA里面,而是完成映射关系的计算之后直接输出了。这里有两个自定义模块:histogram负责计算直方图,并将直方图存储到Ram32x256中、reflect实现映射关系的计算并将映射关系存储到u_transform256x8中。顶层模块的主体是一个三个状态的状态机:
- 状态000:将外部输入的灰度值存入u_image_mem中,对图像进行存储,同时计算灰度直方图。其内部也是一个状态机:
整个top模块的忙信号wen管脚如果为1,则根据histogram的wea管脚进行拉低,因为该管脚意味着histogram模块已经完成计算,整个模块进入空闲状态。- 状态0:等待外部输入的灰度值,如果外部输入灰度值并且pin_clken为高电平,则将灰度值作为u_image_mem写入数值,并且自增u_image_mem的写入地址,并且灰度值作为histogram的输入和Ram32x256的读出地址,拉高top模块的wen管脚进入忙状态,进入状态001;
- 状态1:检查histogram模块的忙信号,如果处于空闲状态就拉高其写入信号pin_clken_hist,使能u_image_mem的写入,将灰度值写入对应的位置上,返回状态0。
Ram32x256的写入受控于histogram模块,histogram根据输入的灰度值读取Ram32x256中的数值,然后加1再次写入,实现直方图的计算。
- 状态001:在这个状态下,top模块的wen一直拉高,因为接来都在进行映射计算,因此不能接收下一帧图像。在这里面也有也给状态机:
- 状态0:此时Ram32x25