采用matlab产生mif文件,具体的代码如下:
clear;
clc;
width=8;
depth=256;
fid =fopen ('sin.mif','w');
fprintf(fid,'WIDTH=%d;\n',width);
fprintf(fid,'DEPTH=%d;\n',depth);
fprintf(fid,'ADDRESS_RADIX=UNS;\n');
fprintf(fid,'DATA_RADIX=UNS;\n');
fprintf(fid,'CONTENT BEGIN\n');
for i=0:depth-1
sin_data=floor((sin(2*pi*i/depth)+1)*0.5*(2^width-1));
data=sin_data;
fprintf(fid,'%d : %d;\n',i,data);
end
fprintf(fid,'END;\n');
fclose (fid);
通过运行.m文件可以产生一个sin.mif文件用作rom的初始状态
首先创建工程
调用单个端口的ROM IPcore,位宽为8,深度为256,RTL视图如下
顶层文件如下
module dds_v3(
input wire clk,
input wire rst_n,
output wire [7:0] wave
);
wire [7:0] addr ;
roml256x8 roml256x8_inst (
.address ( addr ),
.clock ( clk ),
.q ( wave )
);
dds_ctrl dds_ctrl_inst(
.clk(clk),
.rst_n(rst_n),
.addr_sin(addr)
);
endmodule
dss_ctrl代码如下
module dds_ctrl(
input wire clk,
input wire rst_n,
output wire [7:0] addr_sin
);
parameter P_word = 0; //xiangwei
parameter FREQ = 123456; //f
localparam [63:0] F_word = FREQ*(2**32)*20/(10**9);
reg [31:0] cnt;
assign addr_sin=cnt[31:24]+P_word;
always @(posedge clk)begin
if(rst_n==1'b0)
cnt<=32'd0;
else
cnt<=cnt+F_word[31:0];
end
endmodule
由于开发芯片频率为50MHz,可以知道单个周期的时间为20ns,由于选择的cnt的位宽是32位,所以存满一个周期所需要的时间为
T=2^32✖20ns
f=1/T
f=(10^9) / (2^32✖20)
假设我们一步的步长为F_word,那么
f=F_word✖(10^9) / (2^32✖20)
F_word=f ✖ (2^32) ✖ 20 / (10^9)
我们取cnt寄存器的高8位作为rom的地址,通过对地址的不断读取即可以实现dds功能
仿真代码如下
`timescale 1ns/1ps
module dds_v3_tb;
reg clk;
reg rst_n;
wire [7:0] wave;
wire [7:0] wave1;
defparam dds_v3_inst1.dds_ctrl_inst.FREQ=123456;
defparam dds_v3_inst2.dds_ctrl_inst.FREQ=654321;
dds_v3 dds_v3_inst1(
.clk(clk),
.rst_n(rst_n),
.wave(wave)
);
dds_v3 dds_v3_inst2(
.clk(clk),
.rst_n(rst_n),
.wave(wave1)
);
initial clk=1'b0;
always #10 clk=~clk;
initial begin
rst_n=1'b0;
#200;
@(posedge clk)
#2;
rst_n=1'b1;
repeat (20) begin
while (wave != 255)
@(posedge clk);
while (wave != 0)
@(posedge clk);
end
#2000;
$stop;
end
endmodule