dds通过matlab 生成的载波nco的实现:
verilog代码为:
顶层模块:主要是来组合下面两个模块
module ddsshiyan1 (clk , dds_out) ;
input clk ;
output [9:0] dds_out ;
wire [9:0] add_out ;
add_dff u1 (.clk(clk) , .adder_dff_out(add_out)) ;
sin u2 (.clock(clk) , .address(add_out) , .q(dds_out)) ;
endmodule
/////////////////////////////////////////////////////////////////////////
add_dff模块:主要是产生频率字和累加频率字的结果
module add_dff (clk , adder_dff_out ) ;
input clk ;
output [9:0] adder_dff_out ;
reg rst ;
reg [4:0] count ;
reg [9:0] reg1 ;
reg [9:0] dff_out ;
parameter adder_dff_in = 10'd8 ;
initial
begin
rst = 1'd0 ;
count = 5'd0 ;
dff_out <= 10'd0 ;
end
always @ (posedge clk)
if (!rst)
begin
count <= count + 1 ;
reg1 <= adder_dff_in ;
if (count == 5'd30)
begin
count <= 5'd0 ;
rst <= 1'b1 ;
end
end
else
begin
dff_out <= dff_out + reg1 ;
end
assign adder_dff_out = dff_out ;
endmodule
/////////////////////////////////////////////////////////////////////
sin模块:主要是利用rom核来产生nco信号
rom核自动生成程序为:
`timescale 1 ps / 1 ps
// synopsys translate_on
module sin (
address,
clock,
q);
input [9:0] address;
input clock;
output [9:0] q;
wire [9:0] sub_wire0;
wire [9:0] q = sub_wire0[9:0];
altsyncram altsyncram_component (
.clock0 (clock),
.address_a (address),
.q_a (sub_wire0),
.aclr0 (1'b0),
.aclr1 (1'b0),
.address_b (1'b1),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_a ({10{1'b1}}),
.data_b (1'b1),
.eccstatus (),
.q_b (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_a (1'b0),
.wren_b (1'b0));
defparam
altsyncram_component.address_aclr_a = "NONE",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
`ifdef NO_PLI
altsyncram_component.init_file = "DDSrom33.rif"
`else
altsyncram_component.init_file = "DDSrom33.hex"
`endif
,
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 1024,
altsyncram_component.operation_mode = "ROM",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.widthad_a = 10,
altsyncram_component.width_a = 10,
altsyncram_component.width_byteena_a = 1;
endmodule
//////////////////////////////////////////////////////////////////////////////
matlab生成rom程序:
clc;clear;
N = 10; %储存单元地址线
depth=2^N; %存储单元;
widths=N; %数据宽度为8位;
index = linspace(0,pi*2,depth);
sin_value = sin(index);
sin_value = sin_value * (depth/2 -1); %扩大正弦幅度值
sin_value = fix((sin_value)+0.5);
plot(sin_value);
number = [0:depth];
fid=fopen('DDSrom3.mif','w+');
fprintf(fid,'depth=%d;\n',depth);
fprintf(fid,'width=%d;\n',widths);
fprintf(fid,'address_radix=UNS;\n');
fprintf(fid,'data_radix = DEC;\n');
fprintf(fid,'Content Begin\n');
for i = 1 : depth
fprintf(fid, '%d\t:\t%d;\r\n', number(i),sin_value(i));
end
fprintf(fid,'end;');
fclose(fid);
刚开始做出来自己写的一点总结:
实验一DDS总结:
一个在例化中(为了好识别端口使本来要直接连的两个端口共同连一个有意义的net字符,记得要把net字符定义为wire型数据,否则很可能综合出来的在rtl图中看见他们不是相连的),一个在modelsim仿真中(modelsim对信号的初始化要求很高,否则未定义的信号直接默认为高阻态,而高阻态的反什么的还是高阻态,最后信号显示为高阻态),写出来总结一下。 还有个就是modelsim严格按照计算机补码区别正负,十进制的正负号是识别不了的,所以rom要用hex文件储存,用mif文件的符号modelsim识别不了,所以千万把matlab生成的mif文件转成hex文件
实验总结:
主要出现问题有三:
1,在例化中为了例化信号更好识别,自己加了新的端口,但未在程序的开头声明端口,但是quartus还不报错,导致综合出来的tll图模块之间没有连接起来,
最后是在前面加了wire语句给新定义的端口
2,刚开始学,不知道一开始就要在程序里面就开始为调用modelsim就注意要初始化,因为初始化不完全,导致modelsim仿真不出结果,出错
3,不知道modelsim不能识别mif文件中储存的负数,在观察波形中,mif中定义也要注意符号数和无符号数,转化为hex文件补码16进制存储后波形终于输出正常。
待解决问题:
matlab程序中:sin_value = sin_value * (depth/2 -1); %扩大正弦幅度值 ,这个对出来的nco波形的精度有影响吧?还有存储地址的深度的关系。
文章评论(0条评论)
登录后参与讨论