1.matlab产生混频信号x = 5*sin(2*pi*200*t) + 5*sin(2*pi*1000*t) + 5*sin(2*pi*2000*t)
clear;
clc;
fs = 8000;N=1024;n=0:N-1;t=n/fs;
x = 5*sin(2*pi*200*t) + 5*sin(2*pi*1000*t) + 5*sin(2*pi*2000*t);%混频信号
% c = min(x); %得出信号的最小值
% f1 = x + 5;
f = round(x+14)';%根据所得最小值,把信号取正
% c = min(f);
%c = max(f); %可以得出取正之后数据的最大值,从而知道ROM当中的数据长度
% save ffile.txt -ascii f;
fid = fopen('b.mif','wt'); %将所得的数据存在b.mif当中,(数据文件类型也可以是txt类型)
fprintf(fid,'%g\n',f);
fclose(fid);
% length(f);
[a,b] = size(f); %可以得出数据的位数,好设置ROM的容量
I = a*b;
得出的数据文件
2.将matlab的数据存储在quartus的ROM中
新建一个文件
因为matlab里面的数据有1024个,然后最大数是14,所以设置如下:
在第一个地址 点击右键,然后把数据复制过来
将该mif文件保存到工程中
在ip catalog中搜索ROM,点击进入,保存到IPcore中,命名为my_rom
然后配置ip核,把期望的数据个数改为rom当中的数据量
然后一直点击next,当出现下面界面时,将之前的mif文件加进去
然后编写rom控制程序,产生递增的地址
//rom的控制模块,用于产生递增的地址信号
module rom_ctrl(
input clk_100m,
input rst_n,
output reg [9:0] addr //地址输出
);
always @(posedge clk_100m or negedge rst_n)
begin
if(!rst_n)
addr <= 10'd0; //复位时地址为十进制0
else
begin
if(addr < 1024)
addr <= addr + 1;
else
addr <= 10'd0;
end
end
endmodule
2.然后加入锁相环IP核,这里是将50M的时钟频率改为了100M(大家可以根据实际需求去改,也可以看我之前的关于pll_clk的设置介绍)
module pll_clk(
input sys_clk, //系统时钟
input sys_rst_n, //系统复位信号
output clk_100m, //输出100mhz时钟
output rst_n
);
wire locked;
//wire rst_n;
assign rst_n = sys_rst_n & locked; //当sys_rst_n和locked都为1时,rst_n才为高电平,
//所以只有系统稳定时,这个可以用于其他模块的复位状态
my_pll my_pll_inst(
.areset (~sys_rst_n), //复位信号和按键复位相连,但锁相环是高电平复位,所以要取反
.inclk0 (sys_clk) ,
.c0 (clk_100m),
.locked (locked) //标志输出稳定
);
endmodule
3.滤波部分(我这里只做了简单的处理)
//滤波模块,这只是简单的滤波
module dsp_iir(
input clk_100m,
input rst_n,
input [7:0] q , //有效数据输出
output reg [7:0] Q
);
reg [7:0] Q_1 = 0;
reg [7:0] Q_2 = 0;
always @(negedge clk_100m or negedge rst_n)
begin
if(!rst_n)
begin
Q_1 <= 8'd0; //复位时地址为十进制0
Q_2 <= 8'd0;
Q <= 8'd0;
end
else
begin
Q_1 <= q;
Q_2 <= Q_1;
Q <= (197*Q_1 + 3*Q_2)/2;
end
end
endmodule
4.顶层模块的编写
//系统顶层模块,负责子模块的联级
module dsp_iir_top(
input sys_clk,
input sys_rst_n,
output Q,
output q //有效数据输出
);
wire [9:0] addr; //定义地址信号
wire clk_100m;
wire rst_n;
/*
assign rst_n = sys_rst_n & locked; //当sys_rst_n和locked都为1时,rst_n才为高电平,
//所以只有系统稳定时,这个可以用于其他模块的复位状态
my_pll my_pll_inst(
.areset (~sys_rst_n), //复位信号和按键复位相连,但锁相环是高电平复位,所以要取反
.inclk0 (sys_clk) ,
.c0 (clk_100m),
.locked (locked) //标志输出稳定
);
*/
//实例化rom_ctrl
rom_ctrl rom_ctrl(
.clk_100m(clk_100m),
.rst_n(rst_n),
.q(q),
.addr(addr)
);
pll_clk u_pll_clk(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.rst_n (rst_n),
.clk_100m (clk_100m )
);
dsp_iir u_dsp_iir(
.q(q),
.Q(Q),
.rst_n (rst_n),
.clk_100m (clk_100m )
);
/*
//ip核 rom调用
my_rom my_rom_inst(
.clock(clk_100m),
.q(q),
.address(addr)
);*/
/*
my_pll my_pll_inst(
.areset (~sys_rst_n), //复位信号和按键复位相连,但锁相环是高电平复位,所以要取反
.inclk0 (sys_clk) ,
.c0 (clk_100m),
.locked (locked) //标志输出稳定
);*/
endmodule
RTL图
5.测试文件的编写:
`timescale 1ns/1ns
module dsp_iir_tb ;
parameter SYS_PERIOD = 20; //定义系统时钟周期
reg sys_clk ;
reg sys_rst_n ;
wire clk_100m ;
wire rst_n ;
wire [7:0] q ;
wire [7:0] Q ;
wire [9:0] addr ;
always #(SYS_PERIOD/2) sys_clk <= ~sys_clk ;
initial begin
sys_clk <= 1'b0 ;
sys_rst_n <= 1'b0 ;
#(20*SYS_PERIOD)
sys_rst_n <= 1'b1 ;
end
//例化ip_pll模块
rom_ctrl rom_ctrl(
.clk_100m(clk_100m),
.rst_n(rst_n),
.q(q),
.addr(addr)
);
pll_clk u_pll_clk(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.rst_n (rst_n),
.clk_100m (clk_100m )
);
dsp_iir u_dsp_iir(
.q(q),
.Q(Q),
.rst_n (rst_n),
.clk_100m (clk_100m )
);
//ip核 rom调用
my_rom my_rom_inst(
.clock(clk_100m),
.q(q),
.address(addr)
);
endmodule
6.波形图:
下面是matlab里面的信号波形图:
modelsim看图形的方法如下:
ps:不知道为什么 地址总是会延迟,就是前面三个地址的输出全是第一个地址的值,然后后面就全都错位了(希望有大神指教)