正弦信号,是一个模拟信号。而FPGA只能产生数字信号。因此需要用DA将数字量转化为模拟量。这里采用modelsim的模拟波形显示,就不需要DA模块了。产生正弦信号的方法有很多,这里用的是查找rom的方法,产生正弦信号。

正弦信号,是一个介于-1和1之间的模拟量。而正弦信号是周期变化的,因此这里只需要将半个正弦信号周期的值存进rom里,其余周期可以根据这个半个周期的值变化可得到。用matlab产生正弦信号的值。以0.01为步长,从0采集到pi/2。共158个点。

因此sin的值是小数,而FPGA是不能表示小数的,因此需要将小数扩大,以整数来表示。此次是以12位二进制来显示这整数。扩大的方法就是乘以212即可了。12位二进制数最大能表示212-1的值。这里用0表示最小值0,212-1表示最大值1,则0到1中间的数,就可以扩大到用0到212-1中间的数来表示了。例如,0.3,就可用整数0.3*2^12=1228.8,在向上取整,为1228,当然这样表示会有误差。

这里rom用的是ISE的IP rom。将matlab生成的数据放进rom里面。然后依次读取rom的值,即可生成正弦信号了。

首先是生成rom的初始化文件。Xilinx的rom的初始化文件的后缀为.coe。而这个特殊文件有固定的格式。

第一行的10表示下面的数字是10进制的。。。 后面的数据是依次存入rom的值,以逗号分开,最后一个以分号结束。前面两行的内容是固定的。

生成初始化文件的matlab如下所示:

fid = fopen(‘sin_rom.txt’,‘w’);
fprintf(fid,‘MEMORY_INITIALIZATION_RADIX = 10;\n’);
fprintf(fid,‘MEMORY_INITIALIZATION_VECTOR =\n’);
for i = 0:1:pi/2*100
y = sin(i/100);
rom =floor( y * 2^12);
if i == 157
fprintf(fid,’%d;’,rom);
else
fprintf(fid,’%d,’,rom);
end

if mod(i,10)==0 && i ~= 0fprintf(fid,'\n');
end

end
fclose(fid);
生成的文件是.txt文件。将后缀直接改为.coe即可。然后复制到ISE分工程目录下。

初始化文件生成后,剩下就是编写verilog代码。

首先建一个工程,然后新建一个IP。找到rom,打开。设置按如下设置:


这里是设置位宽,采用的是13位(第一位为符号位,后面12位为数据位)来显示sin的值。因此这里是设置为13.深度是因为要存158个值,所以这里设置为158.

这里将刚刚生成的.coe文件载入,如果没有显示红色,就说明正确,否则错误。错误的原因是数据和设定的深度没有对齐。

接下来直接生成就行了。

接着就是编写verilog代码了。

首次查看用ip生成的rom的HDL例化代码.

sin_rom your_instance_name (
.clka(clka), // input clka
.addra(addra), // input [7 : 0] addra
.douta(douta) // output [12 : 0] douta
);
从上面的程序可看出,只需要给时钟信号,和输入地址,就可以了。输出的就是正弦的数字信号了。分析正弦信号,前1/4个周期,地址从0自加,一直加到157(1/4个周期的点数)。然后再自减,减到0。然后进入到负半周了。大家都知道,负数的表示是以二进制的补码来表示的,即绝对值数的二进制取反在加一。

因此要编写地址自加自减的代码,然后再根据地址的值,判断输出的值是正数,还是负数,负数的话,rom的输出值还要取反加一后再输出。

其代码,如下所示:

module sin_top(
input clk, //输入时钟信号
input [9:0] address, //输入地址信号
output reg [12:0] data_out //输出sin的数字值
);

reg [7:0] add;
wire [12:0] douta;
// 以下是判断地址的值
always@ * begin
if( address <= 157 )
add = address;
else if( address <= 315 )
add = 10’d315 - address;
else if( address <= 473 )
add = address - 10’d316;
else if( address <= 631 )
add = 10’d631 - address;
else
add = 0;
end

//例化之前生成的sin_rom
sin_rom u1_sin_rom (
.clka(clk), // input clka
.addra(add), // input [7 : 0] addra
.douta(douta) // output [12 : 0] douta
);
// 判断输出值是正数还是负数。
always@ * begin
if( address <= 315 )
data_out = douta;
else if( address <= 631 )
data_out = ~douta + 1’b1;
else
data_out = 0;
end
endmodule
程序写好了,剩下就是要仿真了。仿真的testbench,只需要输入时钟和地址信号就可以了。地址信号一直加一,直到不小于631,刚好一个周期结束。就返回0值,在继续自加。

测试代码如下所示:

module sin_top_test;
// Inputs
reg clk;
reg [9:0] address;

   // Outputswire [12:0] data_out;// Instantiate the Unit Under Test (UUT)sin_top uut (.clk(clk),.address(address),.data_out(data_out));always#5  clk = ~clk;initial begin// Initialize Inputsclk = 0;address = 0;// Wait 100 ns for global reset to finishwhile(1)   begin@(negedge(clk));if( address < 631 )address = address + 1;elseaddress = 0;end               end

endmodule
接着用modelsim仿真。因为有用到xilinx的IP ROM。因此用modelsim单独仿真比较麻烦。因此这里是直接在ISE里面调用modelsim,这样比较简单。

只需在设置器件这里将仿真器设置为modelsim就可以了。

然后就可以直接仿真了。

在modelsim里面

将out的format的格式改为analog。这样一会显示的波形就会以模拟的形式显示了。

仿真后,标准的正弦波形就出来了。是不是很酷啊。。哈哈哈

这里采用的modelsim仿真,而不是用的是ISE自带的仿真,因为ISE的波形不能以模拟波形显示。

这样产生的正弦波,方法比较简单,但是不能调节,调节的话,就要重新生成rom的值。而且还伴随着误差。可以增大位数,和减小采样间隔时间来减小误差。

如果你想要快速入门、转行做数字前端设计,不妨到移知官网学习这些课程,给自己一次蜕变的可能。芯片东西还是挺多的,要讲的也太多。慢慢学吧。祝好运!

原文首发于骏的世界博客
作者:卢骏.

用FPGA产生正弦信号相关推荐

  1. ROM存储1/4周期正弦信号构造DDS

    简单的dds程编写过程中我遇到问题以及一些个人的思考.初次接触FPGA,如有问题请多多指教~ 1.几个疑问,解决和没有解决的. 为何采用ROM而不是直接采用DDS核来进行正弦信号的合成? 实际中如果只 ...

  2. 基于FPGA的FM信号解调

    这是本人第一次写博客,写的不好请多多担待. 本次实验是将一个已知的FM信号通过FPGA进行解调,解调出波形并进行FFT得到调制频率fm,并且每一步都通过MATLAB进行波形的验证. 开发工具 VIVA ...

  3. FPGA产生2FSK信号(1)

    目录 FPGA产生2FSK信号(1) 一.2FSK介绍 1.相干解调: 2.非相干解调 二.FPGA生成2FSK方法 1.正弦ROM表产生 (1)生成mif文件 (2)生成rom IP核并导入mif文 ...

  4. matlab 方波_MATLAB之Simulink(二)利用switch模块将正弦信号变为方波信号

    ##MATLAB之Simulink(二) ##利用switch模块将正弦信号变为方波信号 今天给大家展示一个simulink电路仿真,将正弦信号转化为方波信号. 下面开始教程: 1.首先直接在MATL ...

  5. 通过示波器数据进行正弦信号参数估计

    实验要求 在第一次作业中的第二小题,练习了根据信号的波形写出对应信号的表达式.但在实际中,我们观测到的信号往往是在示波器上的波形,此时该如何获得这些波形的数学表达式? 测量波形的示波器 本质上讲,实际 ...

  6. 【数字信号处理】相关函数应用 ( 正弦信号 的 自相关函数 分析 二 | 在白噪声中检测正弦信号 )

    文章目录 一.正弦信号 的 自相关函数 分析 一.正弦信号 的 自相关函数 分析 正弦信号 s(n)=Asin⁡ωns(n) = A \sin \omega ns(n)=Asinωn , 其 幅度 A ...

  7. 【数字信号处理】相关函数应用 ( 正弦信号 的 自相关函数 分析 | 在白噪声中检测正弦信号 )

    文章目录 一.正弦信号 的 自相关函数 分析 一.正弦信号 的 自相关函数 分析 正弦信号 Asin⁡ωnA \sin \omega nAsinωn , 其 幅度 A=1A = 1A=1 , 功率 P ...

  8. 【matlab代码】生成特定频率的正弦信号,X轴以时间表示

    模拟信号:   正弦波三要素: 幅度A,角频率\omega,相位\varphi y=A sin\left ( \omega t+\varphi \right )   角频率\omega与频率f的关系: ...

  9. matlab单边衰减正弦信号,指数衰减正弦信号

    连续实指数信号, 连续正弦信号, 连续复指数信号的 Matlab 源代码 连续实指数信号 y1=0.5e-0.5x x=-5:0.01:5; y1=0.5*exp(0.5*x); y2=0.5*exp ...

  10. matlab simulink_MATLAB之Simulink(二)利用switch模块将正弦信号变为方波信号

    ##MATLAB之Simulink(二) ##利用switch模块将正弦信号变为方波信号 今天给大家展示一个simulink电路仿真,将正弦信号转化为方波信号. 下面开始教程: 1.首先直接在MATL ...

最新文章

  1. 包含min函数的栈 大坑
  2. 我对观察者模式的理解,之前一直很乱
  3. 菜鸟教程之工具使用(六)——让Maven项目直接在eclipse内部的Tomcat中执行
  4. backtracking算法
  5. spark mongo java_Spark Mongodb集成 - Python版
  6. TAppEncoder的main函数
  7. css div撑满窗口高度_如何使用CSS将div的高度设置为窗口的100%?
  8. mysql noinstall 5.5_mysqlnoinstall 手动安装
  9. 基于javaweb的宠物管理系统
  10. 前额单通道脑电睡眠分期算法设计
  11. 【小程序开发】uniapp引入iconfont图标及使用方式
  12. 计算机自顶向下WireShark实验2:DNS
  13. 【机器学习】Sklearn-cluster聚类方法
  14. java青蛙跳台阶问题
  15. 超信咋老是显示服务器不可用,超信创始人自述:微信是很强大 但我们敢叫板
  16. No discret job created in Oracle
  17. 最低成本DIY视频遥控车方案:ESP32-CAM视频遥控车
  18. 网络概念- IPRAN的含义及来历——转载
  19. javascript库概念与连缀
  20. Java实现字数统计(中文英文韩文日文混合),类似word效果

热门文章

  1. Registry Workshop —— 强大的注册表编辑工具
  2. 由企业证书打包的app--提示证书不受信任的解决途径
  3. html中w3c标准,css标准 - W3C中国
  4. 故宫的首夜,一票难求,网站遭“围攻”宕机
  5. 解决ubuntu16.04插耳机没有声音的问题
  6. 两年3亿用户,淘特跑出中国电商“加速度”
  7. 蓝牙连接不上车要hfp_hfp是什么意思车上
  8. 登机牌,机票,行程单的区别
  9. 2022/7/9 考试总结
  10. Mac 开发工具汇总