注:本设计的参数为:D=2,R=5,N=3;时钟频率为50mhz,输入信号为有符号8位,根据公式bmax=bin+N*log(2,R*D);可以得到bmax=18;
1,cic抽取滤波器原理
网上资料一大堆,不说了。重点在于传递函数,以及各个部分的结构。
2,simulink仿真
模型图
频谱仪显示结果
3,cic滤波器verilog 代码
module cic_dec(clk,rst_n,datain,dataout); input clk,rst_n; input [7:0] datain; output [7:0] dataout; reg [17:0] data_buff; always@(posedge clk or negedge rst_n) begin if(!rst_n) data_buff<=0; else data_buff<={{10{datain[7]}},datain}; end
reg [17:0] integ1_result;
always@(posedge clk or negedge rst_n) begin if(!rst_n) integ1_result<=0; else integ1_result<=data_buff+integ1_result; end
reg [17:0] integ2_result;
always@(posedge clk or negedge rst_n) begin if(!rst_n) integ2_result<=0; else integ2_result<=integ1_result+integ2_result; end
reg [17:0] integ3_result; always@(posedge clk or negedge rst_n) begin if(!rst_n) integ3_result<=0; else integ3_result<=integ2_result+integ3_result; end //integrator end //decimation start reg dec_flag; reg [17:0] dec_result; reg [2:0] cnt1; always@(posedge clk or negedge rst_n) begin if(!rst_n) cnt1<=0; else if(cnt1==3'd4) cnt1<=0; else cnt1<=cnt1+1'b1; end always@(posedge clk or negedge rst_n) begin if(!rst_n) dec_result<=0; else if(cnt1==3'd4) dec_result<=integ3_result; end always@(posedge clk or negedge rst_n) begin if(!rst_n) dec_flag<=1'b0; else if(cnt1==3'd4) dec_flag<=1'b1; else dec_flag<=1'b0; end //decimation end // comb filter begin reg [2:0] cnt2; always@(posedge clk or negedge rst_n) begin if(!rst_n) cnt2<=0; else if(dec_flag) cnt2<=0; else cnt2<=cnt2+1'b1; end reg [17:0] comb1_delay1; reg [17:0] comb1_delay2; reg [17:0] comb1_result; always@(posedge clk or negedge rst_n)//first comb begin if(!rst_n) begin comb1_delay1<=0; comb1_delay2<=0; end else if(cnt2==3'd3) begin comb1_delay1<=dec_result; comb1_delay2<=comb1_delay1; end end always@(posedge clk or negedge rst_n) begin if(!rst_n) comb1_result<=0; else if(dec_flag) comb1_result<=dec_result-comb1_delay2; end
reg [17:0] comb2_delay1; reg [17:0] comb2_delay2; reg [17:0] comb2_result; always@(posedge clk or negedge rst_n)//second comb begin if(!rst_n) begin comb2_delay1<=0; comb2_delay2<=0; end else if(cnt2==3'd3) begin comb2_delay1<=comb1_result; comb2_delay2<=comb2_delay1; end end always@(posedge clk or negedge rst_n) begin if(!rst_n) comb2_result<=0; else if(dec_flag) comb2_result<=comb1_result-comb2_delay2; end
reg [17:0] comb3_delay1; reg [17:0] comb3_delay2; reg [17:0] comb3_result; always@(posedge clk or negedge rst_n)//third comb begin if(!rst_n) begin comb3_delay1<=0; comb3_delay2<=0; end else if(cnt2==3'd3) begin comb3_delay1<=comb2_result; comb3_delay2<=comb3_delay1; end end always@(posedge clk or negedge rst_n) begin if(!rst_n) comb3_result<=0; else if(dec_flag) comb3_result<=comb2_result-comb3_delay2; end reg [7:0] dataout_buff; always@(posedge clk or negedge rst_n) begin if(!rst_n) dataout_buff<=0; else dataout_buff<=(comb3_result[17:0]+{!comb3_result[17],{9{comb3_result[17]}}})>>10; end assign dataout=dataout_buff; endmodule
4,matlab产生正弦波形文件采样频率50m,正弦频率1m
0=1e6; fs=50e6; N=fs/f0; n=0:N-1; t=n/fs; width=8;
sinwave=sin(2*pi*f0*t); sindata = round(sinwave .* (2^(width-1) - 1)); for i=1:N if(sindata(i)<0) sindata(i)=2^width+sindata(i); else sindata(i)=sindata(i); end end
fid=fopen('sindata.txt','a'); for i=1:N fprintf(fid,'%x \n',sindata(i)); i=i+1; end fclose(fid);
5,verilog读取波形文件产生正弦波
module sin_gen(clk,rst_n,sin_out); input clk,rst_n; output [7:0] sin_out; parameter N = 50; reg [7:0] mem[0:N-1]; initial begin $readmemh("sindata.txt",mem); end reg [7:0] sin_out_buff; reg [5:0] i; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin sin_out_buff<=0; i<=6'd0; end else begin sin_out_buff<=mem[i]; if(i==6'd49) i<=6'd0; else i<=i+1'b1; end end assign sin_out=sin_out_buff; endmodule
6, testbench
`timescale 1ns/1ps module testbench(); reg clk,rst_n; initial begin clk=0; forever #10 clk=~clk; end initial begin rst_n=0; #50 rst_n=1'b1; end wire [7:0] sin_out; sin_gen u0_sin_gen(.clk(clk),.rst_n(rst_n),.sin_out(sin_out)); wire [7:0] data_out; cic_dec u0_cic_dec(.clk(clk),.rst_n(rst_n),.datain(sin_out),.dataout(data_out)); reg [10:0] cnt; always@(posedge clk or negedge rst_n ) begin if(!rst_n) cnt<=0; else if(cnt==11'd1024) cnt<=cnt; else cnt<=cnt+1'b1; end integer fid; initial begin fid=$fopen("dataout.txt","a"); end always@(posedge clk ) begin $fwrite(fid,"%x \n",data_out); end always@(posedge clk) begin if(cnt==11'd1024) begin
$fclose(fid);
$stop; end
end
endmodule
7,modelsim 仿真波形
|
请发表评论