2FSK数字调制实现
FSK原理
FSK(Frequency Shift-Keying)频移键控分为非连续相位FSK和连续相位FSK,区别在于转换处是否连续。
- Matlab生成输入的两种不同频率的载波
f1 = 5000;%波形频率
f2 = 4000;
fs = 20000; %采样频率
N = 12; % 量化位数
len = 2000;%长度
t = 0:1/fs:(len - 1)/fs;
s1 = sin(2*pi*f1*t);
s2 = sin(2*pi*f2*t);
s = s1;
%对仿真产生的合成单频信号进行量化处理
s=s/max(abs(s)); %归一化处理
Q_s=round(s*(2^(N-1)-1));%12比特量化
%将生成的数据以二进制数据格式写入txt文件中
fid=fopen('E:\Work\IC\Modem\code\FSK\testdata.txt','w');
for i=1:length(Q_s)
B_noise=dec2bin(Q_s(i)+(Q_s(i)<0)*2^N,N);
for j=1:N
if B_noise(j)=='1'
tb=1;
else
tb=0;
end
fprintf(fid,'%d',tb);
end
fprintf(fid,'\r\n');
end
fclose(fid);
- Verilog顶层文件,利用M序列发生器生成基波,用分频实现不同频率载波读入
//clock frequency 50MHz
//carrier frequency 1 and 2 = 1MHz and 5MHz
//baseband frequency 0.1MHz
module fsk(
input clk,
input rst,
input [11:0] sin0,
input [11:0] sin1,
output [11 :0] Mod_out
);
reg[11 :0] Mod_out1,Mod_out0;
wire clk_M,clk_1M,clk_5M;
reg M_reg;
//clk_1M
clk_div #(
.Max (50)
)
u1 (
.clk(clk),
.rst(rst),
.clk_div(clk_1M)
);
//clk_5M
clk_div #(
.Max (10)
)
u2 (
.clk(clk),
.rst(rst),
.clk_div(clk_5M)
);
//clk_M
clk_div #(
.Max (500)
)
u3 (
.clk(clk),
.rst(rst),
.clk_div(clk_M)
);
//M squencer generator
M_gen #(
.width (8)
)
u4 (
.clk(clk_M),
.rst(rst),
.M_out(M_out)
);
//载波选择
always@(posedge clk_1M or negedge rst) begin
if (!rst)
Mod_out0 <= 0;
else
Mod_out0 <= sin0;
end
always@(posedge clk_5M or negedge rst) begin
if (!rst)
Mod_out1 <= 0;
else
Mod_out1 <= sin1;
end
assign Mod_out = (M_out == 1'b0)?Mod_out0:Mod_out1;
endmodule
- M序列发生器
//clock frequency 50MHz
//carrier frequency 1 and 2 = 10MHz and 5MHz
//baseband frequency 1MHz
//M squencer generator
module M_gen #(
parameter width = 4
)
(
input clk,
input rst,
output M_out
);
reg[width -1: 0] shift;
always@(posedge clk or negedge rst) begin
if (!rst)
shift <= 1;
else
shift <= {shift[0]^shift[3],shift[7:1]}; //f = x^3 + x + 1
//shift <= {shift[0]^shift[3],shift[width -1-:width-1]}; //f = x^3 + x + 1
end
assign M_out = shift[0];
endmodule
- 分频
module clk_div #(
parameter Max = 8
)
(
input clk,
input rst,
output reg clk_div
);
reg[8:0] cnt;
always@(posedge clk or negedge rst) begin
if (!rst)
cnt <= 0;
else if (cnt == Max/2 -1)
cnt <= 0;
else
cnt <= cnt + 1'b1;
end
always@(posedge clk or negedge rst) begin
if (!rst)
clk_div <= 1'b0;
else if (cnt == Max/2 -1)
clk_div <= ~clk_div;
end
endmodule
- 测试
`timescale 1ns/1ps
module test();
reg clk;
reg rst;
reg [11: 0] sin0;
reg [11: 0] sin1;
wire[11: 0] Mod_out;
fsk u1
( .clk(clk),
.rst(rst),
.sin0(sin0),
.sin1(sin1),
.Mod_out(Mod_out)
);
//rst
initial begin
rst = 1'b1;
#10 rst = 1'b0;
#20 rst = 1'b1;
#4000000 $finish;
end
//clk
initial begin
clk = 1'b1;
forever #10 clk = ~clk;
end
reg [11: 0] mem0 [0:1999];
reg [11: 0] mem1 [0:1999];
integer i,j;
initial begin
$readmemb("/home/IC/Mylearn/FSK/testdata1.txt", mem0);
i = 0;
repeat(1999) begin
i = i + 1;
sin0 = mem0[i];
#1000;
end
end
initial begin
$readmemb("/home/IC/Mylearn/FSK/testdata2.txt", mem1);
j = 0;
repeat(1999) begin
j = j + 1;
sin1 = mem1[j];
#400;
end
end
initial begin
$fsdbDumpfile("fsk.fsdb");
$fsdbDumpvars;
end
endmodule
- verdi仿真结果,第一二列为载波,第三列为基波,最后一列为调制后信号
- vivado仿真结果