基於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]、電子發燒友學院

總結

創作不易,認爲文章有幫助的同學們可以關注、點贊、轉發支持。爲行業貢獻及其微小的一部分。或者對文章有什麼看法或者需要更近一步交流的同學,可以加入下面的羣:
在這裏插入圖片描述

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