基于FPGA实现CIC升采样滤波器verilog HDL代码总结
一、概述
上文中我们总结了CIC基本原理设计,本文将基于xilinx FPGA通过verilog HDL实现CIC升采样及仿真情况总结如下,作为相关项目开发参考。
二、设计说明
系统工作时钟50M
正弦信号频率50M/16/8=0.390625MHz
正弦信号采样频率50M/16=3.125Msps,每个正弦波周期采集8个点
正弦信号升采样频率50M/2=25Msps,即8倍内插
CIC升采样滤波器实现框图及内部信号定义:
三、代码实现
1、顶层代码
module top(
input wire sclk,
input wire rst_n,
input wire [31:0] phase_init,
input wire [31:0] freq_para,
output wire [23:0] dataout
);
wire [7:0] sin_data;
wire data_valib;
pro_sin pro_sin_inst(
.sclk (sclk), //系统时钟50M
.rst_n (rst_n),
.phase_init(phase_init),//初始相位
.freq_para (freq_para),//频率配置字
.data_v (data_valib),
.dataout (sin_data)
);
cic_filter cic_filter_inst(
.sclk (sclk), //系统频率为50M
.rst_n (rst_n),
.datain (sin_data),
.data_v (data_valib),
.dataout (dataout)
);
endmodule
2、产生正弦信号代码(调用了xilinx RAM IP)
module pro_sin(
input wire sclk, //系统时钟50M
input wire rst_n,
input wire [31:0] phase_init,//初始相位
input wire [31:0] freq_para,//频率配置字
output reg data_v,//输出有效标识
output wire [7:0] dataout
);
reg [31:0] phase;//相位累加器
wire [7:0] addr;
parameter DIV=16-1; //分频系数,用于产生采样频率50M/16=3.125Msps的正弦信号
reg [5:0] div_cnt;//分频计数器
reg div_flag;
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
div_cnt<=6'd0;
else if(div_cnt==DIV)
div_cnt<=6'd0;
else
div_cnt<=div_cnt+1'b1;
end
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
div_flag<=1'b0;
else if(div_cnt==6'd0)
div_flag<=1'b1;
else
div_flag<=1'b0;
end
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
phase<=phase_init;
else if(div_flag==1'b1)
phase<=phase+freq_para; //频率配置字由f1=M*fs/2^N计算得到M值。
end
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
data_v<=1'b0;
else
data_v<=1'b1;
end
assign addr=phase[31:24];
blk_mem_gen_0 blk_mem_gen_0_inst (
.clka(sclk), // input wire clka
.ena(1'b1), // input wire ena
.wea(1'b0), // input wire [0 : 0] wea
.addra(addr), // input wire [7 : 0] addra
.dina('d0), // input wire [7 : 0] dina
.douta(dataout) // output wire [7 : 0] douta
);
endmodule
3、CIC升采样滤波实现代码
module cic_filter(
input wire sclk, //系统频率为50M
input wire rst_n, //复位信号
input wire [7:0] datain, //DDS输入的8为正弦波信号
input wire data_v, //输入信号的有效标识
output wire [23:0] dataout
);
parameter DIV=16-1; //分频系数,信号采样频率:50M/16=3.125Msps
parameter DIV_R=2-1;//分频系数,8倍内插后的信号采样频率:50M/2=25Msps
parameter W=24;//8倍内插后的信号位宽
reg [5:0] div_cnt; //原采样率分频计数器
reg [4:0] div_cnt_r; //内插后采样率分频计数器
reg div_flag; //16倍分频标识
reg div_flag_r;//8倍内插后的分频标识
//梳妆滤波器寄存器
reg [W-1:0] comb1_r;
reg [W-1:0] comb2_r;
reg [W-1:0] comb3_r;
wire [W-1:0] comb1_w;
wire [W-1:0] comb2_w;
wire [W-1:0] comb3_w;
//积分器寄存器
reg [W-1:0] integrator1_r;
reg [W-1:0] integrator2_r;
reg [W-1:0] integrator3_r;
wire [W-1:0] integrator1_w;
wire [W-1:0] integrator2_w;
wire [W-1:0] integrator3_w;
//对50M系统时钟进行16分频
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
div_cnt<=6'd0;
else if(div_cnt==DIV)
div_cnt<=6'd0;
else
div_cnt<=div_cnt+1'b1;
end
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
div_flag<=1'b0;
else if(div_cnt==6'd0)
div_flag<=1'b1;
else
div_flag<=1'b0;
end
//对50M系统时钟进行2分频
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
div_cnt_r<=5'd0;
else if(div_cnt_r==DIV_R)
div_cnt_r<=5'd0;
else
div_cnt_r<=div_cnt_r+1'b1;
end
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
div_flag_r<=1'b0;
else if(div_cnt_r==5'd0)
div_flag_r<=1'b1;
else
div_flag_r<=1'b0;
end
//梳妆滤波器
assign comb1_w={{16{datain[7]}},datain}-comb1_r;
assign comb2_w=comb1_w-comb2_r;
assign comb3_w=comb2_w-comb3_r;
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
begin
comb1_r<='d0;
comb2_r<='d0;
comb3_r<='d0;
end
else if((data_v==1'b1)&&(div_flag==1'b1))
begin
comb1_r<={{16{datain[7]}},datain};
comb2_r<=comb1_w;
comb3_r<=comb2_w;
end
else if(data_v==1'b0)
begin
comb1_r<='d0;
comb2_r<='d0;
comb3_r<='d0;
end
end
//积分器
assign integrator1_w=comb3_w+integrator1_r;
assign integrator2_w=integrator1_w+integrator2_r;
assign integrator3_w=integrator2_w+integrator3_r;
always@(posedge sclk or negedge rst_n)
begin
if(rst_n==1'b0)
begin
integrator1_r<='d0;
integrator2_r<='d0;
integrator3_r<='d0;
end
else if((data_v==1'b1)&&(div_flag_r==1'b1))
begin
integrator1_r<=integrator1_w;
integrator2_r<=integrator2_w;
integrator3_r<=integrator3_w;
end
end
assign dataout=integrator3_w;
endmodule