赞
踩
这两天做的东西要用到FIRip核,我用的是Quartus18.0网上几乎都是老版的,新版的教程说明很少,于是就研究了一下,写出来共大家一起学习
我用的是单通道所以在通道选项就选者1,下面输入采样时钟50Mhz,
这里前面都默认,记住这里是有符号位的,并且下面输入你的采样位宽,
这里我选择的是用matlab生成系数,并导入进去,matlab生成系数看后文Matlab部分,记住生成的系数写入文件要用逗号隔开,否则这个页面不显示波形,
因为是有符号位的所以比采样的位宽多一位,这里输入9,后面的都默认,在代码里面再截断选着有用的数据 (这里我花费了好长时间才搞明白),后面的都默认,最后电机Finish,接下来就是MATLAB系数的生成
打开Matlab,在命令行输入fdatool,进入配置选项
这里选择低通fir窗函数凯撒窗(如图)
接下来在选着fix point(一定要),左边第三个,输入位宽8和Specify all
选着输入位宽含符号位9,下面选着,输出也是含有符号位9和8,然后点击Apply
最后导出生成的系数,文件里选着导出到工作台
可以看到多了一个Num,接下来把数据导出到文件,
- fid=fopen('C:\Users\123\Desktop\FPGA_Integrated_projects\matlab\fir_data.txt',"W")
- [r,c]=size(Num); % 得到矩阵的行数和列数
- for i=1:r
- for j=1:c
- fprintf(fid, '%f,',Num(i,j));
- end
- end
- fclose(fid);
到这里Matlab数据就生成好了,就可以写Verilog代码了。Firip核具体时序图可以看别的博主,这里重点讲一下怎么从FIR输出的数据里面选着有效的数据,代码写好后 打开逻辑分析仪,
选着Fir输出的数据,可以看到大部分数据都是连续的,突然会有几个很大的数据进来(这是因为是符号位有负数),看一下连续的数据里面最大值是多少,然后从从这个数据的二进制位宽向下选着你输入数据的位宽,这里我选的是8,然后很大的数据变成二进制看看含1的最高位在多少,然后有效的数据取反加1,这样就完成了 代码如下
- module FFT_test
- (
- input wire sys_clk ,
- input wire sys_rst_n ,
-
- output wire [7:0] data_modulus,
- output wire [9:0] index ,
- output wire data_sop ,
- output wire data_eop ,
- output wire data_valid
-
- );
-
- wire fir_valid ;
-
- reg [7:0] address ;
- wire [7:0] data ;
- wire [7:0] fft_data_in ;
- wire fir_source_valid;
- wire [23:0]fir_data_out ;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- address <=0;
- else if(fir_valid==1'b1)
- address <=address+1;
- else
- address <=address;
-
- rom rom_inst_U1
- (
- .address ( address ),
- .clock ( sys_clk ),
- .rden ( fir_valid),
- .q ( data )
- );
- fir fir_U11
- (
- .clk ( sys_clk ),// clk.clk
- .reset_n ( sys_rst_n ),// rst.reset_n
- .ast_sink_data ( {1'b0,data} ),// avalon_streaming_sink.data
- .ast_sink_valid ( fir_valid ),// .valid
- .ast_sink_error ( 2'b0 ),// .error
- .ast_source_data ( fir_data_out ),// avalon_streaming_source.data
- .ast_source_valid( fir_source_valid ),// .valid
- .ast_source_error( ) // .error
- );
- assign fft_data_in = (fir_data_out[22]==1'b1)?(~fir_data_out[17:10]+1):fir_data_out[17:10];//非常主要,
-
- FFT_top FFT_top_U2
- (
- .sys_clk (sys_clk ) ,
- .sys_rst_n (sys_rst_n ) ,
- .data_in (fft_data_in ) ,
- .fir_source_valid(fir_source_valid),
-
- .data_modulus(data_modulus) ,
- .data_sop (data_sop ) ,
- .data_eop (data_eop ) ,
- .data_valid (data_valid ) ,
- .fir_valid (fir_valid ) ,
- .index (index)
- );
- endmodule
这里我输入的信号在1,5,12,50,90的地方有数值,并且也输入了噪声
将数据写入mif文件,并烧到rom里面(选着Mif文件)
- clc; %清除命令行命令
- clear all; %清除工作区变量,释放内存空间
- F1=1; %信号频率
- Fs=2^8; %采样频率
- P1=0; %信号初始相位
- N=2^8; %采样点数
- t=[0:1/Fs:(N-1)/Fs]; %采样时刻
- ADC=2^7 - 1; %直流分量
- A=2^7; %信号幅度
- %生成正弦信号
- s=A*(sin(2*pi*F1*t)+5*sin(2*pi*12*t)+sin(2*pi*50*t)+sin(2*pi*90*t)+randn(size(t)))/10+ ADC;
- plot(t,s); %绘制图形
- %创建mif文件
- fild = fopen('C:\Users\123\Desktop\FPGA_Integrated_projects\matlab\FFTsin_wave_256x8.mif','wt');
- %写入mif文件头
- fprintf(fild, '%s\n','WIDTH=8;'); %位宽
- fprintf(fild, '%s\n\n','DEPTH=4096;'); %深度
- fprintf(fild, '%s\n','ADDRESS_RADIX=UNS;'); %地址格式
- fprintf(fild, '%s\n\n','DATA_RADIX=UNS;'); %数据格式
- fprintf(fild, '%s\t','CONTENT'); %地址
- fprintf(fild, '%s\n','BEGIN'); %开始
- for i = 1:N
- s0(i) = round(s(i)); %对小数四舍五入以取整
- if s0(i) <0 %负1强制置零
- s0(i) = 0
- end
- fprintf(fild, '\t%g\t',i-1); %地址编码
- fprintf(fild, '%s\t',':'); %冒号
- fprintf(fild, '%d',s0(i)); %数据写入
- fprintf(fild, '%s\n',';'); %分号,换行
- end
- fprintf(fild, '%s\n','END;'); %结束
- fclose(fild);
-
-
在逻辑分析仪核上板上可以看到正确滤掉了90处的信号,
这里成功显示了几个频率并且12处的最大,90处的没有了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。