概述
FPGA具有高度实时的特性。这里讨论基于FPGA设计一款简单的正弦信号发生器。
DDS原理
Direct Digital frequency Synthesis如下图所示:
3. DAC原理
这里DAC采用TLC5620,下面分别给出DAC的原理图和时序图。
4. ROM文件的生成
ROM波形可以通过MIF或HEX文件保存在FPGA的ram或rom模块中,也可以自己编写HDL文件存储。这里我们采用后者。
利用win-tc或matlab生产所需格式的函数数据,参考C代码如下:
#include "stdio.h"
#include "math.h"
#definePi 3.1416
#defineDEPTH 256
#defineLENTH DEPTH/2
intmain()
{
FILE*fp;
int j;
unsigned char i= 0;
unsigned char x= 0;
if((fp=fopen("d:\\sin.txt","w"))==NULL)
{
printf("can't open this file..\n");
exit(0);
}
for(j=0;j<DEPTH;j++)
{
x=(int)(LENTH+LENTH*sin(2*Pi*i/DEPTH - 0.5*Pi));
fprintf(fp," 'd%d: data = 'h%x;\n",i,x);
i++;
}
fprintf(fp,"\n");
fclose(fp);
printf("success\n");
return 0;
}
5. DAC控制逻辑设计
module dac_ctrl(
input clk,
input rst_n,
output reg dac_clk,
output reg dac_load,
output reg dac_ldac,
output reg dac_dat,
input [7:0] rom_dat,
output reg [7:0] rom_addr,
input [7:0] freq_ctrl
);
//=====================================
//The frequency of clk is divided by N
parameter bitsize = 4;
parameter N = 20;
reg [bitsize:0] cnt0;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt0 <= 0;
dac_clk <= 0;
end
else
begin
if(cnt0 < (N/2-1))
cnt0 <= cnt0 + 1'b1;
else
cnt0 <= 0;
if(cnt0==0 && cnt1 >=1 && cnt1 <= 4'hb)
dac_clk <= ~ dac_clk;
else
dac_clk <= dac_clk;
end
end
wire clk_1M;
assign clk_1M = (cnt0 == 0)?1'b1:1'b0;
//======================================
reg [3:0] cnt1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt1 <= 0;
else
if(clk_1M)
cnt1 <= cnt1 + 1'b1;
else
cnt1 <= cnt1;
end
reg [7:0] cnt2;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt2 <= 0;
else
if(cnt1 == 4'hf)
if(cnt2 != freq_ctrl)
cnt2 <= cnt2 + 1'b1;
else
cnt2 <= 0;
else
cnt2 <= cnt2;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
rom_addr <= 0;
else
if(clk_1M && cnt1==4'hf && cnt2 == freq_ctrl)
rom_addr <= rom_addr + 1'b1;
else
rom_addr <= rom_addr;
end
always @(cnt1)
begin
case(cnt1)
4'h2: begin
dac_dat <= 1'b0;
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h3: begin
dac_dat <= 1'b0;
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h4: begin
dac_dat <= 1'b1;
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h5: begin
dac_dat <= rom_dat[7];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h6: begin
dac_dat <= rom_dat[6];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h7: begin
dac_dat <= rom_dat[5];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h7: begin
dac_dat <= rom_dat[4];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h8: begin
dac_dat <= rom_dat[3];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'h9: begin
dac_dat <= rom_dat[2];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'ha: begin
dac_dat <= rom_dat[1];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'hb: begin
dac_dat <= rom_dat[0];
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
4'hc: begin
dac_dat <= 1'b0;
dac_load <= 1'b0;
dac_ldac <= 1'b1;
end
4'hd: begin
dac_dat <= 1'bx;
dac_load <= 1'b1;
dac_ldac <= 1'b0;
end
default:
begin
dac_dat <= 1'bx;
dac_load <= 1'b1;
dac_ldac <= 1'b1;
end
endcase
end
endmodule
6. 测试结果