Verilog实现级联的CIC滤波器

碎碎念

我这个代码还是和上次一样输入250kHz和7.5MHz的混合波,滤掉高频,对于CIC滤波器的阻带,可以变更级联数量,积分上限(也是输出位宽),梳状器输出位宽和抽取率来调整阻带,具体的大家可以自己去MATLAB里算一下(其实是我不会用),我这个代码是照着下面这个大佬的写的

Verilog CIC 滤波器设计

还有就是他说输出位宽可以是17位,但是实测17位会输出奇怪的波形,可能是阻带不对,把输出设成和积分器位宽一样的21位就行了

 积分器

module Intergrator #(												//积分器,三次连续积分
	parameter					I_LEN=12,
	parameter					O_LEN=21)(
	input							CLK,
	input							RSTN,
	input							EN,
	input	[I_LEN-1:0]			DATA_I,

	output [O_LEN-1:0]		DATA_O,
	output						VAL);
	
	reg [O_LEN-1:0] 			DATA_reg[2:0];
	reg [2:0]					EN_reg;
	wire [O_LEN-1:0]			DATA_wire;

	
	assign DATA_wire = { {(O_LEN-I_LEN) {1'b0}} , DATA_I};
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			EN_reg <= 'b0;
		end else begin
			EN_reg <= {EN_reg[1:0],EN};
		end
	end
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg[0] <= 'b0;
		end else if(EN) begin
			DATA_reg[0] <= DATA_reg[0] + DATA_wire;
		end
	end
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg[1] <= 'b0;
		end else if(EN_reg[0]) begin
			DATA_reg[1] <= DATA_reg[1] + DATA_reg[0];
		end
	end
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg[2] <= 'b0;
		end else if(EN_reg[1]) begin
			DATA_reg[2] <= DATA_reg[2] + DATA_reg[1];
		end
	end

	assign DATA_O = DATA_reg[2];
	assign VAL = EN_reg[2];
	
endmodule

抽取器 

module Decimator #(												//抽取器,每隔三个抽取一个
	parameter						DATA_LEN = 21
	)	(
	input								CLK,
	input								RSTN,
	input								EN,
	input [DATA_LEN-1:0]			DATA_I,
	
	output [DATA_LEN-1:0]		DATA_O,
	output 							VAL);
	
	reg [2:0]						O_cnt;
	reg [DATA_LEN-1:0]			DATA_reg;
	reg								VAL_reg;
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			O_cnt <= 'b0;
		end else if(EN) begin
			if(O_cnt==4) begin
				O_cnt <= 'b0;
			end else begin
				O_cnt <= O_cnt + 1'b1;
			end
		end
	end
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg <= 'b0;
			VAL_reg <= 'b0;
		end else if(EN) begin
			if(O_cnt==4) begin
				DATA_reg <= DATA_I;
				VAL_reg <= 1'b1;
			end else begin
				VAL_reg <= 1'b0;
			end
		end
	end
	
	assign DATA_O = DATA_reg;
	assign VAL = VAL_reg;
	
endmodule	

 梳状器

 

module Comb #(											//梳状器
	parameter		I_LEN = 21,
	parameter		O_LEN = 21
	) (
	input								CLK,
	input								RSTN,
	input								EN,
	input [I_LEN-1:0]				DATA_I,
	
	output [O_LEN-1:0]			DATA_O,
	output 							VAL);
	
	reg [O_LEN-1:0]				DATA_reg1 [2:0];
	reg [O_LEN-1:0]				DATA_reg2 [2:0];
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg1[0] <= 'b0;
	      DATA_reg2[0] <= 'b0;
		end else if(EN) begin
			DATA_reg2[0] <= DATA_reg1[0];
	      DATA_reg1[0] <= DATA_I;
		end
	end
	wire [O_LEN-1:0] DATA_O1 =  DATA_reg1[0] - DATA_reg2[0];
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg1[1] <= 'b0;
	      DATA_reg2[1] <= 'b0;
		end else if(EN) begin
			DATA_reg2[1] <= DATA_reg1[1];
	      DATA_reg1[1] <= DATA_O1;
		end
	end
	wire [O_LEN-1:0] DATA_O2 =  DATA_reg1[1] - DATA_reg2[1];
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg1[2] <= 'b0;
	      DATA_reg2[2] <= 'b0;
		end else if(EN) begin
			DATA_reg2[2] <= DATA_reg1[2];
	      DATA_reg1[2] <= DATA_O2;
		end
	end
	wire [O_LEN-1:0] DATA_O3 =  DATA_reg1[2] - DATA_reg2[2];
	
	
	reg [O_LEN-1:0] DATA_reg;
	reg VAL_reg;
	
	always @(posedge CLK or negedge RSTN) begin
		if(!RSTN) begin
			DATA_reg <= 'b0;
			VAL_reg <= 1'b0;
		end else if(EN) begin
			DATA_reg <= DATA_O3;
			VAL_reg <= 1'b1;
		end else begin
			VAL_reg <= 1'b0;
		end
	end
	
	assign DATA_O = DATA_reg;
	assign VAL = VAL_reg;
endmodule
	

顶层模块 

module CIC_filter #(
	parameter		I_LEN = 12,							// 输入数据长度
	parameter		MAX_LEN = 21,						// 最大数据长度
	parameter		O_LEN = 21							// 输出数据长度
	)(
	input							CLK,						// 时钟输入
	input							RSTN,						// 复位信号,低有效
	input							EN,						// 输入有效信号,高有效
	input	[I_LEN-1:0]			DATA_I,					// 输入数据
	
	output [O_LEN-1:0]		DATA_O,					// 输出数据		
	output						VAL);						// 有效输出	
	
	wire [MAX_LEN-1:0]		inte_o;
	wire [MAX_LEN-1:0]		deci_o;
	wire [1:0]					VAL_wire;
																//三种部件的实例化,可视作三个CIC的级联
	Intergrator #(.I_LEN(I_LEN),.O_LEN(MAX_LEN))			My_Inte(
		.CLK(CLK),
		.RSTN(RSTN),
		.EN(EN),
		.DATA_I(DATA_I),

		.DATA_O(inte_o),
		.VAL(VAL_wire[0]));
		
	Decimator #(.DATA_LEN(MAX_LEN))							My_Deci(	//先抽取,保证功能不变
		.CLK(CLK),
		.RSTN(RSTN),
		.EN(VAL_wire[0]),
		.DATA_I(inte_o),
		
		.DATA_O(deci_o),
		.VAL(VAL_wire[1]));
		
	Comb #(.I_LEN(MAX_LEN),.O_LEN(O_LEN))					My_Comb(
		.CLK(CLK),
		.RSTN(RSTN),
		.EN(VAL_wire[1]),
		.DATA_I(deci_o),
		
		.DATA_O(DATA_O),
		.VAL(VAL));


endmodule

 

test bench

下边是test ben和一样 ,但是明显没有FIR平滑,然后发现上一次的test bench漏了一个数据,stimulus[0]没初始化,害后面数据全是未知,怪不得上次FIR的输出有一段不平整

`timescale 1 ps /1 ps
module test;
	parameter			I_LEN = 12;
	parameter			O_LEN = 21;
	
	
	reg 					clk;
	reg 					rstn;
	reg 					en;
	reg [11:0]			data_i;
	
	wire					val;
	wire [20:0]			data_o;

	
	//50Mhz clk
	localparam 			CLK_HALF=10_000;
	initial begin
		forever begin
			clk = 0;
			#CLK_HALF;
			clk = 1;
			#CLK_HALF;
		end
	end
	
	parameter    SIMU_CYCLE   = 64'd2000 ;  		//一共仿真的周期数
	parameter    SIN_DATA_NUM = 200 ;      		//输出波形的长度

	initial begin
		rstn=1'b1;
		rstn=1'b0;
		#50;
		rstn=1'b1;
		#(CLK_HALF*2*SIMU_CYCLE);
		$finish;
	end
	
	reg          [11:0] stimulus [199:0] ;
	integer      i ;
	initial begin
	

    stimulus[199] <= 12'hE53;
    stimulus[198] <= 12'hAB0;
    stimulus[197] <= 12'h814;
    stimulus[196] <= 12'h8A4;
    stimulus[195] <= 12'hBE6;
    stimulus[194] <= 12'hF26;
    stimulus[193] <= 12'hFB3;
    stimulus[192] <= 12'hD12;
    stimulus[191] <= 12'h968;
    stimulus[190] <= 12'h7B3;
    stimulus[189] <= 12'h954;
    stimulus[188] <= 12'hCEA;
    stimulus[187] <= 12'hF77;
    stimulus[186] <= 12'hED6;
    stimulus[185] <= 12'hB81;
    stimulus[184] <= 12'h82C;
    stimulus[183] <= 12'h789;
    stimulus[182] <= 12'hA11;
    stimulus[181] <= 12'hDA0;
    stimulus[180] <= 12'hF39;
    stimulus[179] <= 12'hD7A;
    stimulus[178] <= 12'h9C4;
    stimulus[177] <= 12'h716;
    stimulus[176] <= 12'h793;
    stimulus[175] <= 12'hAC3;
    stimulus[174] <= 12'hDF2;
    stimulus[173] <= 12'hE6D;
    stimulus[172] <= 12'hBBB;
    stimulus[171] <= 12'h800;
    stimulus[170] <= 12'h63B;
    stimulus[169] <= 12'h7CC;
    stimulus[168] <= 12'hB52;
    stimulus[167] <= 12'hDCF;
    stimulus[166] <= 12'hD20;
    stimulus[165] <= 12'h9BD;
    stimulus[164] <= 12'h659;
    stimulus[163] <= 12'h5A8;
    stimulus[162] <= 12'h823;
    stimulus[161] <= 12'hBA6;
    stimulus[160] <= 12'hD33;
    stimulus[159] <= 12'hB68;
    stimulus[158] <= 12'h7A8;
    stimulus[157] <= 12'h4EF;
    stimulus[156] <= 12'h562;
    stimulus[155] <= 12'h888;
    stimulus[154] <= 12'hBAE;
    stimulus[153] <= 12'hC21;
    stimulus[152] <= 12'h967;
    stimulus[151] <= 12'h5A6;
    stimulus[150] <= 12'h3DA;
    stimulus[149] <= 12'h565;
    stimulus[148] <= 12'h8E5;
    stimulus[147] <= 12'hB5E;
    stimulus[146] <= 12'hAAB;
    stimulus[145] <= 12'h744;
    stimulus[144] <= 12'h3DE;
    stimulus[143] <= 12'h32B;
    stimulus[142] <= 12'h5A4;
    stimulus[141] <= 12'h926;
    stimulus[140] <= 12'hAB2;
    stimulus[139] <= 12'h8E8;
    stimulus[138] <= 12'h529;
    stimulus[137] <= 12'h271;
    stimulus[136] <= 12'h2E7;
    stimulus[135] <= 12'h610;
    stimulus[134] <= 12'h939;
    stimulus[133] <= 12'h9B0;
    stimulus[132] <= 12'h6FB;
    stimulus[131] <= 12'h33F;
    stimulus[130] <= 12'h179;
    stimulus[129] <= 12'h30A;
    stimulus[128] <= 12'h692;
    stimulus[127] <= 12'h912;
    stimulus[126] <= 12'h867;
    stimulus[125] <= 12'h509;
    stimulus[124] <= 12'h1AD;
    stimulus[123] <= 12'h103;
    stimulus[122] <= 12'h388;
    stimulus[121] <= 12'h714;
    stimulus[120] <= 12'h8AC;
    stimulus[119] <= 12'h6EE;
    stimulus[118] <= 12'h33B;
    stimulus[117] <= 12'h91;
    stimulus[116] <= 12'h114;
    stimulus[115] <= 12'h44B;
    stimulus[114] <= 12'h783;
    stimulus[113] <= 12'h809;
    stimulus[112] <= 12'h563;
    stimulus[111] <= 12'h1B6;
    stimulus[110] <= 12'h001;
    stimulus[109] <= 12'h1A2;
    stimulus[108] <= 12'h53B;
    stimulus[107] <= 12'h7CC;
    stimulus[106] <= 12'h733;
    stimulus[105] <= 12'h3E7;
    stimulus[104] <= 12'h09C;
    stimulus[103] <= 12'h005;
    stimulus[102] <= 12'h29C;
    stimulus[101] <= 12'h63C;
    stimulus[100] <= 12'h7E6;
    stimulus[99] <= 12'h63C;
    stimulus[98] <= 12'h29C;
    stimulus[97] <= 12'h005;
    stimulus[96] <= 12'h09C;
    stimulus[95] <= 12'h3E7;
    stimulus[94] <= 12'h733;
    stimulus[93] <= 12'h7CC;
    stimulus[92] <= 12'h53B;
    stimulus[91] <= 12'h1A2;
    stimulus[90] <= 12'h001;
    stimulus[89] <= 12'h1B6;
    stimulus[88] <= 12'h563;
    stimulus[87] <= 12'h809;
    stimulus[86] <= 12'h783;
    stimulus[85] <= 12'h44B;
    stimulus[84] <= 12'h114;
    stimulus[83] <= 12'h091;
    stimulus[82] <= 12'h33B;
    stimulus[81] <= 12'h6EE;
    stimulus[80] <= 12'h8AC;
    stimulus[79] <= 12'h714;
    stimulus[78] <= 12'h388;
    stimulus[77] <= 12'h103;
    stimulus[76] <= 12'h1AD;
    stimulus[75] <= 12'h509;
    stimulus[74] <= 12'h867;
    stimulus[73] <= 12'h912;
    stimulus[72] <= 12'h692;
    stimulus[71] <= 12'h30A;
    stimulus[70] <= 12'h179;
    stimulus[69] <= 12'h33F;
    stimulus[68] <= 12'h6FB;
    stimulus[67] <= 12'h9B0;
    stimulus[66] <= 12'h939;
    stimulus[65] <= 12'h610;
    stimulus[64] <= 12'h2E7;
    stimulus[63] <= 12'h271;
    stimulus[62] <= 12'h529;
    stimulus[61] <= 12'h8E8;
    stimulus[60] <= 12'hAB2;
    stimulus[59] <= 12'h926;
    stimulus[58] <= 12'h5A4;
    stimulus[57] <= 12'h32B;
    stimulus[56] <= 12'h3DE;
    stimulus[55] <= 12'h744;
    stimulus[54] <= 12'hAAB;
    stimulus[53] <= 12'hB5E;
    stimulus[52] <= 12'h8E5;
    stimulus[51] <= 12'h565;
    stimulus[50] <= 12'h3DA;
    stimulus[49] <= 12'h5A6;
    stimulus[48] <= 12'h967;
    stimulus[47] <= 12'hC21;
    stimulus[46] <= 12'hBAE;
    stimulus[45] <= 12'h888;
    stimulus[44] <= 12'h562;
    stimulus[43] <= 12'h4EF;
    stimulus[42] <= 12'h7A8;
    stimulus[41] <= 12'hB68;
    stimulus[40] <= 12'hD33;
    stimulus[39] <= 12'hBA6;
    stimulus[38] <= 12'h823;
    stimulus[37] <= 12'h5A8;
    stimulus[36] <= 12'h659;
    stimulus[35] <= 12'h9BD;
    stimulus[34] <= 12'hD20;
    stimulus[33] <= 12'hDCF;
    stimulus[32] <= 12'hB52;
    stimulus[31] <= 12'h7CC;
    stimulus[30] <= 12'h63B;
    stimulus[29] <= 12'h800;
    stimulus[28] <= 12'hBBB;
    stimulus[27] <= 12'hE6D;
    stimulus[26] <= 12'hDF2;
    stimulus[25] <= 12'hAC3;
    stimulus[24] <= 12'h793;
    stimulus[23] <= 12'h716;
    stimulus[22] <= 12'h9C4;
    stimulus[21] <= 12'hD7A;
    stimulus[20] <= 12'hF39;
    stimulus[19] <= 12'hDA0;
    stimulus[18] <= 12'hA11;
    stimulus[17] <= 12'h789;
    stimulus[16] <= 12'h82C;
    stimulus[15] <= 12'hB81;
    stimulus[14] <= 12'hED6;
    stimulus[13] <= 12'hF77;
    stimulus[12] <= 12'hCEA;
    stimulus[11] <= 12'h954;
    stimulus[10] <= 12'h7B3;
    stimulus[9] <= 12'h968;
    stimulus[8] <= 12'hD12;
    stimulus[7] <= 12'hFB3;
    stimulus[6] <= 12'hF26;
    stimulus[5] <= 12'hBE6;
    stimulus[4] <= 12'h8A4;
    stimulus[3] <= 12'h814;
    stimulus[2] <= 12'hAB0;
    stimulus[1] <= 12'hE53;
	 stimulus[0] <= 12'hFFF;
	end
	
	initial begin

		i = 0 ;
		en = 0 ;
		data_i = 0 ;
		
		forever begin
			@(negedge clk) begin
				en          = 1'b1 ;
				data_i      = stimulus[i] ;
				if (i == SIN_DATA_NUM-1) begin  //周期送入数据控制
						i = 0 ;
				end
				else begin
						i = i + 1 ;
				end
			end
		end 
	end
	
	CIC_filter #(.O_LEN(21))				My_filter(
		.CLK(clk),
		.RSTN(rstn),
		.EN(en),
		.DATA_I(data_i),

		.VAL(val),
		.DATA_O(data_o));
	
endmodule
	

 

CIC(Cascade Integrator-Comb)滤波器是一种数字滤波器,常用于高速数据采样和下采样应用中。它通过级联积分器和累加器的结构来实现滤波功能。 CIC滤波器的原理如下: 1. 输入信号经过一个积分器,实现对信号的累积求和操作。 2. 累加器对积分器的输出进行累加操作,以降低采样率。 3. 重复以上两个步骤,形成级联结构,实现多级滤波。 在Verilog实现CIC滤波器,可以按照以下步骤进行: 1. 定义输入和输出端口: ```verilog module cic_filter ( input wire clk, input wire reset, input wire [N-1:0] data_in, output wire [M-1:0] data_out ); ``` 其中,N表示输入数据的位数,M表示输出数据的位数。 2. 实现积分器: ```verilog reg [N-1:0] integrator_reg; always @(posedge clk or posedge reset) begin if (reset) integrator_reg <= 0; else integrator_reg <= integrator_reg + data_in; end ``` 积分器使用一个寄存器(integrator_reg)来存储累加结果,并在每个时钟周期上升沿时根据输入数据进行累加操作。 3. 实现累加器: ```verilog reg [M-1:0] accumulator_reg; always @(posedge clk or posedge reset) begin if (reset) accumulator_reg <= 0; else accumulator_reg <= accumulator_reg + integrator_reg; end ``` 累加器使用一个寄存器(accumulator_reg)来存储累加结果,并在每个时钟周期上升沿时根据积分器的输出进行累加操作。 4. 实现级联结构: ```verilog reg [M-1:0] data_out_reg; always @(posedge clk or posedge reset) begin if (reset) data_out_reg <= 0; else data_out_reg <= accumulator_reg; end assign data_out = data_out_reg; ``` 级联结构中,每一级的累加器的输出作为下一级的输入。最后一级累加器的输出即为滤波器的输出。 5. 添加时钟和复位控制: ```verilog always @(posedge clk) begin if (reset) data_out_reg <= 0; else data_out_reg <= accumulator_reg; end ``` 这里使用时钟上升沿触发累加器和数据输出的更新,同时添加复位信号(reset)来清零滤波器的状态。 以上就是Verilog实现CIC滤波器的基本原理和步骤。具体实现时,根据需要调整数据宽度、级联结构的数量和参数等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值