X

FPGA SDR(18)自作CICフィルタ(可変間引き率版)

IP CatalogのCICフィルタも自作CICフィルタも入力rateの値で間引き率を動的に変更できます。ただし平均の分母が常に最高間引き率固定なので、最高間引き率より小さい間引き率のときは出力データが小さくなってしまいます。段数が多いとべき乗で小さくなってしまいます。

AM/FMラジオの間引き率は、AM 1/1024、FM 1/64にしているので、1段のフィルタでもFMのときのCICフィルタの出力はAMのときの1/16になります。2段、3段にすると小さくなりすぎて復調できません。

そこで、間引き率で出力レベルが変化しないCICフィルタを作ってみました。

`timescale 1ns/1ns


module MyCIC
 #(
	parameter NUM_STAGES = 3,
	parameter MAX_RATE_WIDTH = 12,
	parameter IN_WIDTH = 19,
	parameter OUT_WIDTH = 19
 )
(
	input wire clk,
	input wire reset_n,
	input wire [MAX_RATE_WIDTH:0] rate,
	
	input wire signed [IN_WIDTH-1:0] in_data,
	output wire in_ready,
	input wire in_valid,
	input wire [1:0] in_error,

	output reg signed [OUT_WIDTH-1:0] out_data,
	input wire out_ready,
	output reg out_valid,
	output wire [1:0] out_error
);


	localparam WIDTH = MAX_RATE_WIDTH * NUM_STAGES + IN_WIDTH;
	
	integer i;

	reg signed [WIDTH-1:0] integ [0:NUM_STAGES];
	reg signed [WIDTH-1:0] diff [0:NUM_STAGES];
	reg signed [WIDTH-1:0] diff_d [0:NUM_STAGES];

	reg [MAX_RATE_WIDTH:0] count;
	reg [3:0] rate_width;
	reg next_out_valid;

	
	assign in_ready = 1'b1;
	assign out_error = 2'b00;
	
	always @(posedge clk)
	begin
		if (~reset_n)
		begin
			for (i = 1; i = 16384) rate_width = 8192) rate_width = 4096) rate_width = 2048) rate_width = 1024) rate_width = 512) rate_width = 256) rate_width = 128) rate_width = 64) rate_width = 32) rate_width = 16) rate_width = 8) rate_width = 4) rate_width = 2) rate_width = 1) rate_width >> (rate_width * NUM_STAGES + IN_WIDTH - OUT_WIDTH);
			end
		end
	end
	
endmodule

 

snoopy: