XU.J.P

利用matlab进行ROM初始化mif文件方法

0
阅读(6326)

工具使用版本:Quartus II 13.0+Matlab2012d

撰写人:Strive_JP

关于FPGA中ROM初始化,最近学会了利用matlab强大的数据处理能力来初始化ROM当中的数据。

先简单介绍下FPGA内部的RAM。这里为了简单起见,以EP4CE10为例,先来看下资源情况。

EP4CE10内部有414Kbits的存储容量。有EP4CE10的片内存储器内存为M9K。这样,可以计算出EP4CE10内部的M9K有46片。再看看handbook里面介绍的配置特性。

由上图可以看出FPGA虽然内部拥有一定数量的M9K,但配置深度和配置位宽均有一定的限制。

介绍完上述那些,言归正传,这里提出一种利用matlab文件来初始化ROM内部数据的方式,即对.mif文件进行配置。

假设一组图像数据,现在想将其写入ROM中,以供后续的工程调用。图像数据保存在.txt文件中,格式类型如下所示:

这里只显示了部分图像数据,实际数据有几千上万行。咋办?总不能一点点地敲入ROM的初始化文件中去吧。别人介绍的软件处理方法也没提过这种情况。这时候,想到是否可以利用matlab强大的数据处理能力,来对.txt文件进行处理,再修改为.mif文件保存后直接让quartusII读取呢。

思路是有了,接下来看看一个可供quartusII识别的.mif文件内部是什么结构。此时以txt文档打开一个简单配置完成的文件来看看。

    .mif文件中的内容包括以下几个重要方面:

               WIDTH=8; //数据位宽为8

               DEPTH=256; //存储深度为256

               ADDRESS_RADIX=UNS; //地址类型为无符号整型

               DATA_RADIX=UNS; //数据类型为无符号整型

               CONTENT BEGIN

               0:1;   //地址0的存储器内容为1

               1:3;   //地址为1的存储器内容的3

               [2:255]:0;//地址为2~255的存储器内容为0

               END;

这样,即可利用matlab构造类似的文件存储方式。利用matlab将上述的图像数据转换成.mif。代码如下所示:

clear;
clc;
close all;
fid=fopen('data_8bits.txt');%打开待转换数据的.txt文件
temp=fscanf(fid,'%x');%扫描文件
n=1024;
fid=fopen('convert_data.mif','w');%打开待写入的.mif文件
fprintf(fid,'WIDTH=8;\n');%写入存储位宽8位
fprintf(fid,'DEPTH=1024;\n');%写入存储深度1024
fprintf(fid,'ADDRESS_RADIX=UNS;\n');%写入地址类型为无符号整型
fprintf(fid,'DATA_RADIX=HEX;');%写入数据类型为16进制
fprintf(fid,'CONTENT BEGIN\n');%起始内容
for i=0:n-1
fprintf(fid,'\t%d:%x;\n',i,temp(i+1));
end fprintf(fid,'END;\n'); fclose(fid);%关闭文件

这样将data_8bits.txt文件转换后文件convert_data.mif打开后以及利用quartusII打开.mif文件如下所示:

完全没有任何问题。

针对这种.txt文档其实更直接的方法是采用EXCEL表,将数据做成符合.mif文件格式。这样或许也会比较简单。

除此以外,针对某些算法,同样也可以用matlab仿真,然后生成.mif文件在FPGA当中做算法处理。例如,通常的gamma矫正。借鉴黑金里面的范例,来简单说明下。

剔除那些必要的描述,这里直接列出gamma矫正的公式:


利用matlab来进行代码验证,之后再生产.mif文件,代码如下所示:  

x=0:1:255;
y=uint8(256*((x/256).^(0.95)));%gamma = 0.95
fid=fopen('gamma_data.txt','wt+');
fprintf(fid,'WIDTH=8;\n');
fprintf(fid,'DEPTH=256;\n');
fprintf(fid,'ADDRESS_RADIX=UNS;\n');
fprintf(fid,'DATA_RADIX=UNS;');
fprintf(fid,'CONTENT BEGIN\n');
for i = 0 : 255
     fprintf(fid,'\t%d : %d;\n',i,y(i+1));
end
fprintf(fid,'END;\n');
fclose(fid);
plot(x,y);

生成的ROM内部初始化文件.mif,将地址作为输入数据,相应的内容作为gamma矫正后的像素值。这样即可完成gamma矫正。这Bingo的开发板平台上,编写verilog代码如下:

`timescale 1ns/1ns
module gamma
(
input				clk,  				
input				rst_n,				
input				per_frame_vsync,	
input				per_frame_href,		
    		input				per_frame_clken,	
input		[7:0]	per_img_data,		
output				post_frame_vsync,
output				post_frame_href,	
	    output				post_frame_clken,	
output		[7:0]	post_img_data,			
);

wire [7:0] img_data
Ram256_8_gamma_data	ram256_8_gamma_data_rom(
	.data (),
	.rdaddress (per_img_data),
	.rdclock (clk),
	.wraddress (),
	.wrclock (),
	.wren (),
	.q (img_data)
);

reg [1:0] per_frame_vsync_r;
reg [1:0] per_frame_href_r;	
reg [1:0] per_frame_clken_r;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		per_frame_vsync_r <= 0;
		per_frame_href_r <= 0;
		per_frame_clken_r <= 0;
		end
	else
		begin
		per_frame_vsync_r 	<= 	{per_frame_vsync_r[0], 	per_frame_vsync};
		per_frame_href_r 	<= 	{per_frame_href_r[0], 	per_frame_href};
		per_frame_clken_r 	<= 	{per_frame_clken_r[0], 	per_frame_clken};
		end
end
assign	post_frame_vsync 	= 	per_frame_vsync_r[1];
assign	post_frame_href 	= 	per_frame_href_r[1];
assign	post_frame_clken 	= 	per_frame_clken_r[1];
assign	post_img_data	= 	post_frame_href ? img_data : 8'd0;
endmodule

这样的思想我不知道是否正确,因为从实验结果显示的图像来看,效果很差,实在难以理解,希望哪天有人能和我详细讲解下。

事实证明,采用以上方法做gamma矫正,会破坏图像的相关度。是不行滴,找时间试试对RGB转换成YCRCB图像,对亮度信息做gamma矫正。