Verilog 串行FIR滤波器设计

串行FIR滤波器设计

输入要求:

输入频率:    7.5MHz 和 250KHz
采样频率:    50MHz
阻带:           1MHz-6MHz
阶数:           15 (N=15)

串行设计->16个时钟周期内对16个延时数据分时依次进行乘法、加法运算,然后再时钟驱动下输出滤波值。 FIE滤波器系数的对称性->计算1个滤波输出值的周期可以减少到8个,串行设计时每个周期只进行1此乘法运算,所以设计中只需要1个乘法器。 需要每8个时钟周期有效输入1次,但是为了保证输出信号频率的正确性,工作时钟需要为采样频率的8倍, YesbutWhy

串行设计

`define SAFE_DESIGN

module fir_serial_low(
	input rstn,
	input clk,
	input en,
	input [11:0] xin,
	output valid,
	output [28:0] yout
);
	reg[11:0] en_r;
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			en_r[11:0] <= 'b0;
		end
		else begin
			en_r[11:0] <= {en_r[10:0],en};
		end
	end
	
	wire [11:0] coe[7:0];
	assign coe[0] = 12'd11;
	assign coe[1] = 12'd31;
	assign coe[2] = 12'd63;
	assign coe[3] = 12'd104;
	assign coe[4] = 12'd152;
	assign coe[5] = 12'd198;
	assign coe[6] = 12'd235;
	assign coe[7] = 12'd255;
	
	reg [2:0] cnt;
	integer i,j;
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			cnt<=3'0;
		end
		else if(en||cnt!=0)begin
			cnt<=cnt+1'b1;
		end
	end
	
	reg[11:0] xin_reg[15:0];
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			for(i=0;i<16;i=i+1)
				xin_reg[i]<=12'b0;
			end
		end
		else if (cnt==3'd0&&en)begin
			xin_reg[0]<=xin;
			for(j=0;j<15;j=j+1)begin
				xin_reg[j+1]<=xin_reg[j]
			end
		end
	end
	
	reg [11:0] add_a,add_b;
	reg [11:0] coe_s;
	wire [12:0] add_s;
	wire [2:0] xin_index = cnt<=1?cnt-1:3'd7;
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			add_a<=13'b0;
			add_b<=13'b0;
			coe_s<=12'b0;
		end
		else if(en_r[xin_index])begin
			add_a<=xin_reg[xin_index];
			add_n<=xin_reg[15-xin_index];
			coe_s<=coe[xin_index];
		end
	end
	assign add_s = {add_a}+{add_b};
	
	reg [24:0] mout;
`ifdef SAFE_DESIGN
	wire en_mult;
	wire [3:0] index_mult=cnt>=2?cnt-1:4'd7+cnt[0];
	mult_man #(13,12) u_mult_single
		(.clk (clk),
		 .rstn (rstn),
		 .data_rdy (en_r[index_mult]),
		 .mult1 (add_s),
		 .mult2 (coe_s),
		 .res_rdy (en_mult),
		 .res (mout)
		);
`else
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			mout<=25'd0;
		end
		else if(|en_r[8:1])begin
			mout<=coe_s+add_s;
		end
	end
	wire en_mult=en_r[2];
`endif

	reg [28:0] sum;
	reg valid_r;
	//mult output en counter
	reg [4:0] cnt_acc_r;
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			cnt_acc_r<='b0;
		end
		else if(cnt_acc_r==5'd7)begin
			cnt_acc_r<='b0;
		end
		else if(en_mult||cnt_acc_r!=0)begin
			cnt_acc_r<=cnt_acc_r+1'b1;
		end
	end
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			sum<=29'b0;
			valid_r<=1'b0;
		end
		else if(cnt_acc_r==5'd7)begin//第八个周期累加
			sum<=sum+mout;
			valid_r<=1'b1;
		end
		else if(en_mult&&cnt_acc_r==0)begin//初始化
			sum<=mout;
			valid_r<=1'b0;
		end
		else if(cnt_acc_r!=0)begin
			sum <=sum+mout;
			valid_r<=1'b0;
		end
	end
	reg [28:0] yout_r;
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			yout_r<='b0;
		end
		else if(valid_r)begin
			yout_r<=sum;
		end
	end
	assign yout=yout_r;
	
	//输出信号有效延迟
	reg [4:0] cnt_valid;
	always @(posedge clk or negedge rstn)begin
		if(!rstn)begin
			cnt_valid<='b0;
		end
		else if(valid_r&&cnt_valid!=5'd16)begin
			cnt_valid<=cnt_valid+1'b1;
		end
	end
	assign valid = (cnt_valid == 5'd16)&valid_r;
	
endmodule