quartus写一个verilog的DDS 或叫做NCO,modelsim仿真

8 篇文章 0 订阅

先上代码

module	Carrier_NCO
(
	clock,
	reset,
	f_carrier_nco,				//载波NCO频率控制字
	cos_I,						//余弦输出
	sin_Q					   	//正弦输出
);

parameter		CARR_NCO_WIDTH	= 8;		//载波NCO累加位数
input									clock;
input									reset;

input		[CARR_NCO_WIDTH-1 : 0]		f_carrier_nco;
output		[8:0]						cos_I;
output		[8:0]						sin_Q;

reg			[CARR_NCO_WIDTH-1 : 0]		phase;

wire		[7:0]						phase_key;
wire		[CARR_NCO_WIDTH-1 : 0]		accum_sum;


///
//32位相位累加//
///
	always @(posedge clock)
begin
	if(reset==1'b1)
		phase <= 0;
	else
		phase <= accum_sum[CARR_NCO_WIDTH-1:0];
end
	
assign	accum_sum = phase + f_carrier_nco;
assign	phase_key = accum_sum[CARR_NCO_WIDTH-1:0];
///
//本地正弦相位查找表产生//
///
cos_table cos_talbe_m1(
	.address(phase_key),
	.clken(1'b1),
	.clock(clock),
	.q(cos_I)
	);
sin_table sin_talbe_m1(
	.address(phase_key),
	.clken(1'b1),
	.clock(clock),
	.q(sin_Q)
	);
/*********************************************************************************/
/************************************程序段结束***********************************/
/*********************************************************************************/		
endmodule

输入一个nco频率控制字f_carrier_nco。输出一个正弦波和余弦波。

在这里插入图片描述
上图是一个DDS(直接数字频率合成器)原理图。其主要部分是一个数字控制振荡器(NCO,numerically controlled oscillator)。
NCO三大组成部分:频率控制字、相位累加器、rom查找表
在这里插入图片描述
程序中相位累加器采用8位,则输入频率控制字最大为8位。累加器模型就是x=x+a.其中累加过程采用组合逻辑直接赋值;x的更新采用时序逻辑。
累加采用组合逻辑assign直接赋值assign accum_sum = phase + f_carrier_nco;
phase的更新采用时序逻辑

	always @(posedge clock)
begin
	if(reset==1'b1)
		phase <= 0;
	else
		phase <= accum_sum[CARR_NCO_WIDTH-1:0];
end

然后把相位累加器的值作为地址,送入rom中。

rom核的生成

以生成一个sin数据为例。生成前先想好数据深度和宽度。数据深度就是一个周期的采样点数由于前面相位累加器(rom地址)采用8位,这里就把数据深度设置为2^8=256。数据宽度就是一个采样点用几位数据表示,这个可以随便设(依实际需求设),我这里设置为9位有符号数。以下为matlab生成.mif文件程序。

depth=256;width=9;
max=2^(width-1)-1;
n=0:depth-1;
t=n./depth*2*pi;
s=sin(t);
s=s*max;
s=round(s);
c=cos(t);
c=c*max;
c=round(c);
fidc = fopen('SIN.mif','wt')
fprintf(fidc , 'depth = %d;\n',depth);
fprintf(fidc, 'width = %d;\n',width);
fprintf(fidc, 'address_radix = UNS;\n');%地址用无符号数表示
fprintf(fidc,'data_radix = DEC;\n');%数据用有符号十进制表示
fprintf(fidc,'content begin\n');
for(x = 0 : depth-1)
fprintf(fidc,'%d:%d;\n',x,s(x+1));
end
fprintf(fidc, 'end;');


fclose(fidc);
fidc = fopen('COS.mif','wt')
fprintf(fidc , 'depth = %d;\n',depth);
fprintf(fidc, 'width = %d;\n',width);
fprintf(fidc, 'address_radix = UNS;\n');
fprintf(fidc,'data_radix = DEC;\n');
fprintf(fidc,'content begin\n');
for(x = 0 : depth-1)
fprintf(fidc,'%d:%d;\n',x,c(x+1));
end
fprintf(fidc, 'end;');
fclose(fidc);

注意:生成的mif文件虽然可以直接在quartus中加载,但是不能在modelsim中加载(加载进去不报错,但是仿真出来某一地址下的数据是与文件中不一样的)。所以这里要在quartus中将.mif文件另存为.hex文件,然后再加载.hex。

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值