FPGA使用ROM存放波形,通过DAC芯片完成特定频率波形
硬件新手
1.利用 Matlab,生成分别对正弦波、三角波、 方波进行 256 个采样点的.coe 文件。
2.进行 ROM 地址译码的设计,实现可调频率、相位、幅值。
3.利用 DAC 生成波形。
4.进行时序仿真。
5.下载用示波器验证。
1.利用 DAC 实现的数字式波形合成器
波形发生器是一种数据信号发生器,在调试硬件时,常常需要加入一些信号,以观察电路工作是否正常。加入的信号
有:正弦波、三角波、方波和任意波形等。这里我们采用如下方案:
a.将所需标准信号存在 ROM 中, 当需要信号时,FPGA 利用地址译码器从 ROM 中读取信号。
b.通过调节地址译码器的参数,来实现频率、相位的调整;通过改变增益系数,来实现幅值调整的目的。
d.然后经过 DAC 芯片转换,得到我们所需要的信号。
具体设计方案如图
clear
clc
n = 0:255 ;
yn = sin(2*pi/256*n) ;
yn = round((yn+1)*127);
plot(n,yn);
fid = fopen('./Sin_Wave_Rom.coe','wt');
fprintf(fid,'memory_initialization_radix = 10;\nmemory_initialization_vector = ');
for i = 1 : 256
if mod(i-1,8) == 0
fprintf(fid,'\n');
end
fprintf(fid,'%4d,',yn(i));
end
coe文件格式
memory_initialization_radix = 10 :10进制
nmemory_initializatio在这里插初始化ROM中的数据
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201109191608885.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDMwMjYyNw==,size_16,color_FFFFFF,t_70#pic_center
3.DAC 地址译码设计
在产生波形的过程中,FPGA 读取 ROM 地址中的数据速率决定了波形的周期。 例如,当 FPGA 的主时钟为 50MHz(所对应周期为20ns),在每个时钟上升沿读取完地址 0-255 这 256 个地址的数据后输出一个完整的正弦波,即经过了一个正弦波周期,此时波形周期为20ns×256=5120ns。如果每 2 个上升沿读取的地址才加 1, 则周期为 40ns×256 = 10240ns 。如果每个上升沿读取的地址加2, 则周期为 40ns*128= 2560ns。因此通过这种改变方法可以改变输出波形的周期。
读取 ROM 地址中的偏移量决定了波形的相位。例如,256 个采样点,偏移量为 128,那么相位为(128/256) *360 为 180度。因此可以通过改变基础偏移量来改变输出波形的相位。
由此,我们可以设计地址译码器, 利用分频器产生制定频率的时钟,作为地址译码器的时钟,这样便可以实现频率控制
这段代码的意义是选择初始相位,以及在sin取样256的数值
`timescale 1ns / 1ps
module DDS_Addr_Generator(
input clk_DDS,
input Rst,
input [8:0]Phase,
output [7:0]Addr_Out
);
parameter NWORD=256;
parameter Freq=1000;
wire [7:0]PWORD=(Phase*NWORD)/360;
//=(Phase*NWORD)/360
wire clk_out;
reg [7:0]Addr_Cnt=0;
reg [30:0]FWORD=100000000/(Freq*256);
Clk_Division_0 Clk_Division0(
.clk_100MHz(clk_DDS),
.clk_mode(PWORD),
.clk_out(clk_out)
);
always @ (posedge clk_out or negedge Rst)
begin
if(!Rst)
Addr_Cnt <=0;
else
Addr_Cnt <=Addr_Cnt+1;
end
assign Addr_Out = Addr_Cnt+PWORD;
endmodule
下面例化sin函数的ROM的ip,ROM与RAM的区别,以及单双端口的区别,可以看下一篇文章。
1.在左侧中,选择IP Catalog
2.选择Block Memory Generator
3.选择FIFO、ROM、RAM以及单双端口
4.选择coe文件的width以及depth,在matlab量化中最大的数值是255,可以用8bit来表示,量化个数位256
5.选择之后matlab量化的coe文件
同理三角波、 方波也是这样例化,在此不是展开
DAC芯片DACx311
Wave_Mode波形
1:正弦波
2:三角波
3:方波
下面是整个工程的顶层.v文件
`timescale 1ns / 1ps
module Driver_DAC(
input clk_100MHz,
input clk_DAC,
input DAC_En,
input [1:0]Wave_Mode,
input [8:0]Phase,
output reg DAC_Din,
output reg DAC_Sync
);
//8-bit address, corresponding to the data in the ROM
wire [7:0]Addr_Out;
wire [7:0]Addr_Out_Sin=(Wave_Mode==1)?Addr_Out:0;
wire [7:0]Addr_Out_Triangle=(Wave_Mode==2)?Addr_Out:0;
wire [7:0]Addr_Out_Square=(Wave_Mode==3)?Addr_Out:0;
//ROM DAC data output
wire [7:0]DAC_Data_Sin;
wire [7:0]DAC_Data_Triangle;
wire [7:0]DAC_Data_Square;
//DAC dataSEA 开发实验指导书
reg [7:0]DAC_Data=0;
//DAC cycle state machine count
reg [4:0] DAC_Cnt = 5'd0;
//Combinational logic
always@(*)
begin
case(Wave_Mode)
1:DAC_Data=DAC_Data_Sin;
2:DAC_Data=DAC_Data_Triangle;
3:DAC_Data=DAC_Data_Square;
default:DAC_Data=DAC_Data_Sin;
endcase
end
//DAC state machine task execution
always@(posedge clk_DAC)
begin
if(DAC_Cnt == 16)
DAC_Cnt <= 5'd0;
else
DAC_Cnt <= DAC_Cnt + 5'd1;
case(DAC_Cnt)
5'd0: DAC_Din <= 1'b0;
5'd1: DAC_Din <= DAC_Data[7];
5'd2: DAC_Din <= DAC_Data[6];
5'd3: DAC_Din <= DAC_Data[5];
5'd4: DAC_Din <= DAC_Data[4];
5'd5: DAC_Din <= DAC_Data[3];
5'd6: DAC_Din <= DAC_Data[2];
5'd7: DAC_Din <= DAC_Data[1];
5'd8: DAC_Din <= DAC_Data[0];
5'd9: DAC_Din <= 1'b0;
5'd10: DAC_Din <= 1'b0;
5'd11: DAC_Din <= 1'b0;
5'd12: DAC_Din <= 1'b0;
5'd13: DAC_Din <= 1'b0;
5'd14: DAC_Din <= 1'b0;
5'd15: begin
DAC_Din <= 1'b0;
DAC_Sync <= 1'b1;
end
5'd16: begin
DAC_Din <= 1'b0;
DAC_Sync <= 1'b0;
end
endcase
end
//Phase accumulator module
DDS_Addr_Generator DDS_Addr_Generator0 (
.clk_DDS(clk_100MHz),
.Rst(DAC_En),
.Phase(Phase),
.Addr_Out(Addr_Out)
);
//Sine wave waveform data module
Rom_Sin Sin_Rom(
.clka(clk_DAC), // input wire clka
.ena(DAC_En&(Wave_Mode==1)), // input wire ena
.addra(Addr_Out_Sin), // input wire [7 : 0] addra
.douta(DAC_Data_Sin) // output wire [7 : 0] douta
);
//Square wave waveform data module
Rom_Square Square_Rom(
.clka(clk_DAC), // input wire clka
.ena(DAC_En&(Wave_Mode==3)), // input wire ena
.addra(Addr_Out_Square), // input wire [7 : 0] addra
.douta(DAC_Data_Square) // output wire [7 : 0] douta
);
//Triangle wave waveform data module
Rom_Triangle Triangle_Rom(
.clka(clk_DAC), // input wire clka
.ena(DAC_En&(Wave_Mode==2)), // input wire ena
.addra(Addr_Out_Triangle), // input wire [7 : 0] addra
.douta(DAC_Data_Triangle) // output wire [7 : 0] douta
);
endmodule