之前在ZEDBOARD上实现了FM发射,移植到荔枝糖FPGA开发板上,运行异常,抓波形看,波形紊乱,由于最高时钟为450M,估计是荔枝糖FPGA开发板跑不了这么高,那就降频吧,降到18M果然可以发射了
top代码如下:
module top(
output [2 : 0] rgb_led_o,
input clk24mhz,
input reset,
output fm_tx
);
wire ireset;
wire lock;
wire clk90MHz;
wire iclk20MHz;
wire [15:0] in_factor;
wire [7:0] addr;
reg clk_audio;
reg [11:0] cnt;
reg [14:0] music_cnt;
always @(posedge iclk20MHz)
begin
if (!reset)
begin
cnt <= 0;
clk_audio <= 0;
end
else
begin
if (cnt == 453)//22.1KHz sample rate
begin
clk_audio <= !clk_audio;
cnt <= 0;
end
else
cnt <= cnt + 1;
end
end
always @(posedge clk_audio)
begin
if (!reset)
begin
music_cnt <= 0;
end
else
music_cnt <= music_cnt + 1;
end
clk u1(
.refclk(clk24mhz),
.reset(ireset),
.stdby(),
.extlock(lock),
.clk0_out(iclk20MHz),
.clk1_out(clk90MHz)
);
divider u2(
.clk_in(clk90MHz),
.nreset(reset),
.in_factor(in_factor),
.nclk(fm_tx)
);
music u3(
.doa(addr),
.addra(music_cnt),
.clka(clk_audio),
.rsta(ireset)
);
blk_mem u4(
.doa(in_factor),
.addra(addr),
.clka(iclk20MHz),
.rsta(ireset)
);
assign ireset = !reset;
assign rgb_led_o[0] = !lock;
assign rgb_led_o[1] = 1;
assign rgb_led_o[2] = 1;
endmodule
divider代码如下:
module divider(
input wire clk_in,
input wire nreset,
input wire [15:0]in_factor,
output wire nclk
);
reg r0, r1, r2, r3, r4;
reg [15:0]factor=0;
reg [15:0]fcnt;
reg short;
reg short_f;
always @(posedge clk_in or negedge nreset)
begin
if(~nreset)
begin
r0 <= 0;
r1 <= 0;
r2 <= 0;
r3 <= 0;
r4 <= 1;
end
else
begin
r0 <= r1;
r1 <= r2;
r2 <= r3;
if(short)
r3 <= r0;
else
r3 <= r4;
if(~short)
r4 <= r0;
end
end
assign nclk = r0;
always @(posedge clk_in or negedge nreset)
if(~nreset)
begin
fcnt <= 0;
short <= 0;
short_f <= 0;
end
else
begin
if(r0)
fcnt <= short ? 0 : fcnt +1;
if(r2)
short <= (fcnt == factor);
if(r0)
short_f <= short;
if(r0 & short_f)
factor <= in_factor;
end
endmodule
u4的fm_tx_rom初始化mif文件生成matlab代码如下:
clear all;
close all;
clc;
BASE_FREQ = 90000000;
CARRIER = 18000000;
BAND = 50000;
fid_s = fopen('fm_tx_rom.mif', 'wt');
fprintf(fid_s, '%s\n', 'DEPTH=256;');
fprintf(fid_s, '%s\n', 'WIDTH=16;');
fprintf(fid_s, '%s\n', 'ADDRESS_RADIX=UNS;');%UNS表示为十进制
fprintf(fid_s, '%s\n', 'DATA_RADIX=UNS;');
fprintf(fid_s, '%s\n', 'CONTENT BEGIN');
for (i=1:256)
freq_wish = CARRIER + BAND*(i-1)/256;
divider = BASE_FREQ / freq_wish;
m=(divider-4)/(5-divider);
fprintf(fid_s, '%03d', i-1);
fprintf(fid_s, '%s', ' : ');
fprintf(fid_s, '%d', round(m));
fprintf(fid_s, '%s\n', ';');
end
fclose(fid_s);
disp('===================转换完成=========================');
测试音频rom文件初始化mif文件生成matlab代码如下:
fs = 44100/2; %采样频率
T = 1/fs; %采样周期
time1 = 0.7; %第一个声音片段的总时长
time2 = 0.1;
time3 = 0.686;
freq1 = 261; %第一个声音片段的频率(音调)
freq2 = 0;
freq3 = 1000;
vol1 = 127; %第一个声音片段的音量
vol2 = 0;
vol3 = 100;
tone1 = 128+sin(2*pi*freq1*(0:T:time1))*(vol1); %生成第一个声音片段,注意需要用db2mag()函数把dB转换成magnitude。
tone2 = sin(2*pi*freq2*(0:T:time2))*(db2mag(vol2));
tone3 = 128+sin(2*pi*freq3*(0:T:time3))*(vol3);
Tone = [round(tone1), round(tone2), round(tone3)]; %组合所有声音片段
sound(Tone,fs) %可以播放声音的函数 sound()
fid_s = fopen('music_rom.mif', 'wt');
fprintf(fid_s, '%s\n', 'DEPTH=32768;');
fprintf(fid_s, '%s\n', 'WIDTH=8;');
fprintf(fid_s, '%s\n', 'ADDRESS_RADIX=UNS;');%UNS表示为十进制
fprintf(fid_s, '%s\n', 'DATA_RADIX=UNS;');
fprintf(fid_s, '%s\n', 'CONTENT BEGIN');
for (i=1:32768)
fprintf(fid_s, '%05d', i-1);
fprintf(fid_s, '%s', ' : ');
fprintf(fid_s, '%d', Tone(i));
fprintf(fid_s, '%s\n', ';');
end