基于FPGA的滑动累加器的设计

项目简述

滑动累加器在算法的实现过程中经常碰见,最典型的就是均值滤波。相信大家对滑动累加的概念已经有了不错的掌握,其实就是给原始数据加一个窗然后求这个窗里面所有数据之和。本次实验我们先使用MATLAB实现滑动累加器,然后使用VIVADO实现滑动累加器,最后将两组生成的数据在MATLAB中对比从而相互验证我们实验的正确性。

本次实验所用到的软硬件环境如下:
1、VIVADO 2019.1
2、Modelsim 10.7
3、MATLAB 2015b

MATLAB代码

因为这次的项目没有任何算法的成分在里面,所以我们不再对理论部分多加赘述,这里直接给出相应的代码。

clc;
clear all;
PATH_SPD_RANGE = 6;


fid1 = fopen('data_in_fix.txt','r');
DataIn = fscanf(fid1,'%d');
h_path_pow_fix = DataIn.';
h_path_pow_win = filter(ones(1,2*PATH_SPD_RANGE+1),1,h_path_pow_fix);
h_path_pow_win = h_path_pow_win(2*PATH_SPD_RANGE+1:end);
h_path_pow_win_fix = h_path_pow_win; 


fid1 = fopen('mb_pow_win.txt','w');
fprintf(fid1,'%d\n',h_path_pow_win_fix);

代码就是如此简单,可以使用filter函数一步生成。

FPGA代码

FPGA逻辑代码

因为过程比较简单,我们这里直接给出相应的代码:


module pow_win
(
	input 						sclk				,
	input 						rst_n				,
	input  			[15:0]		POUT				,
	input  						POUT_EN				,		
	output wire 	[19:0]		pow_win_data		,
	output reg 					pow_win_en
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
parameter MAX_DATA = 13'd523 +4'd12;
	 	
reg  				[12:0]	  	read_cnt				;
reg 						  	h_path_pow_fix_en		;
reg  				[15:0] 		shift_h_path_pow[12:0] 	;
reg  				[19:0]		sum_pow_win		 		;  
reg  				[19:0] 		sum_pow_win_T		 	;  
reg  				[15:0]     	pow_mid            		;   
reg  				[15:0]   	fix_h_path_pow		 	;
reg  				[15:0]   	fix_shift_h_path_pow_12	;
integer   	  					j						;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
assign 	pow_win_data 			=  		sum_pow_win;

always @(posedge sclk)
	h_path_pow_fix_en  			<=   	POUT_EN;

always @(posedge sclk)
	if(rst_n == 1'b0)
		read_cnt 				<=   	MAX_DATA+3'd5;
	else if(~h_path_pow_fix_en&&(POUT_EN))
		read_cnt 				<=   	13'd0;
	else if(read_cnt==MAX_DATA+3'd5)
		read_cnt 				<=   	read_cnt;
	else
		read_cnt 				<=   	read_cnt + 1'b1;

always @(posedge sclk)begin
		shift_h_path_pow[0] 	<=   	POUT;
    for (j=0; j<4'd12; j=j+1)
		shift_h_path_pow[j+1] 	<=   	shift_h_path_pow[j];
end

always @(posedge sclk)
	fix_h_path_pow				<=  	POUT;

always @(posedge sclk)
	fix_shift_h_path_pow_12  	<=  	shift_h_path_pow[12];

always @(posedge sclk)
	if(read_cnt<=13'd12&&h_path_pow_fix_en)
		pow_mid 				<=   	{fix_h_path_pow};
	else
		pow_mid 				<=   	{fix_h_path_pow}-{fix_shift_h_path_pow_12};

always @(posedge sclk)                                                    
	if(rst_n == 1'b0)
		sum_pow_win_T 			<=   	0;
	else if(read_cnt == 13'd0)
		sum_pow_win_T 			<=   	0;
	else
		sum_pow_win_T 			<=   	sum_pow_win_T + {{4{pow_mid[15]}},pow_mid};

always @(posedge sclk)                                                    
	if(rst_n == 1'b0)
		sum_pow_win 			<=   	0;
	else if(sum_pow_win_T[19] == 1'b1) 
		sum_pow_win 			<=   	{1'b0,{(15){1'b1}}};
	else 
		sum_pow_win 			<=   	sum_pow_win_T;

always @(posedge sclk)
	if(read_cnt>=13'd14 && (read_cnt<=MAX_DATA-10))
		pow_win_en 				<=   	1'b1;
	else 
		pow_win_en 				<=   	1'b0;

endmodule 

代码的核心模块是下面的部分,大家只需要把这一部分搞透彻那么整个逻辑便非常简单。
在这里插入图片描述

FPGA测试代码

上面逻辑代码的测试代码如下:

`timescale 1ns / 1ps

module tb_pow_win;

reg 					sclk		;
reg 					rst_n		;
reg  		[15:0]		POUT		;
reg  					POUT_EN		;	
reg						POUT_EN_delay1;

wire   [19:0]		pow_win_data;
wire  				pow_win_en;
initial begin
	sclk =1'b0;
	rst_n = 1'b0;
	POUT_EN = 1'b0;
	
	repeat(10) @(posedge sclk)#1;
	rst_n = 1'b1;	
	POUT_EN = 1'b1;
	repeat(524) @(posedge sclk)#1;
	POUT_EN=1'b0;
end

always @(posedge sclk)
begin
	POUT_EN_delay1 <=  POUT_EN;
end 

integer fid1;
initial 
begin
	fid1 = $fopen("data_in_fix.txt","r");
end

always@(posedge sclk)
begin
	if(POUT_EN)
		$fscanf(fid1,"%d",POUT);		
end

integer fid4;
initial 
begin
	fid4 = $fopen("ms_pow_win.txt","w");
end

always@(posedge sclk)
begin
	if(pow_win_en)
		$fwrite(fid4,"%d\n",pow_win_data);
end

always #10 sclk = ~sclk;
	
pow_win uut(
	.sclk				(sclk				),
	.rst_n				(rst_n				),
	.POUT				(POUT				),
	.POUT_EN			(POUT_EN_delay1		),		
	.pow_win_data		(pow_win_data		),
	.pow_win_en         (pow_win_en         )
);

endmodule

整个代码非常简单,大家直接学习代码即可,这里博主没什么多说的。

MATLAB测试代码

我们将MATLAB中的生成的代码与Modelsim中生成的代码相互对比,从而验证我们实验的正确性。代码如下:

clc;
clear all;
fid1 = fopen('mb_pow_win.txt','r');
DataIn = fscanf(fid1,'%d');

fid2 = fopen('ms_pow_win.txt','r');
Dataout = fscanf(fid2,'%d');
 real_data_result = sum(abs(Dataout-DataIn));
   

运行结果如下:
在这里插入图片描述
上面的结果意味着MATLAB与Modelsim两者生成的数据完全一致,从而验证了我们实验的正确性。

参考文献

[1]、电子发烧友学院

总结

创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。为行业贡献及其微小的一部分。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章