一、前言
FSK作为数字通信中不可或缺的一种调制方式,其具有抗干扰能力强,不受信道参数的影响的优点,为此,设计合适的FSK调制解调系统便具有重要意义。
二、主要步骤
该系统产生主要分为三个步骤:
1、通过matlab产生两个不同频率的正弦载波
产生方式:通过matlab软件编程生成一个.mif文件,存放正弦波一个周期的编码值,采样点数为1024,辐值为0-1024。再调用一个12bit数据宽度,深度为1024的ROM,生成两个例化ROM文件,在基准时钟下通过计数器累加不断送入新地址,以两种不同的方法来取地址(本设计采用的是一个地址加一,另一个加二)。 这样即可生成两个不同频率的载波。
.mif文件生成参考代码为:
clc;
clear;
depth =1024; %存储器的深度
widths = 12; %数据宽度为12位
N = 0 :1023; %把一个周期的正弦信号分为256份
s =sin(2*pi *N/256); %计算0 ~2*pi之间的sin值
qqq = fopen('sine.mif','wt') %使用fopen函数生成sine.mif
fprintf(qqq, 'depth = %d;\n',depth); %使用fprintf打印depth = 1027;
fprintf(qqq, 'width = %d;\n',widths); %使用fprintf打印width = 12;
fprintf(qqq, 'address_radix = UNS;\n'); %使用fprintf打印address_radix = UNS; 表示无符号显示数据
fprintf(qqq,'data_radix = UNS;\n'); %使用fprintf打印data_radix = UNS; 表示无符号显示数据
fprintf(qqq,'content begin\n'); %使用fprintf打印content begin
for(x = 1 : depth) %产生正弦数据
fprintf(qqq,'%d:%d;\n',x-1,round(128*sin(2*pi*(x-1)/256)+128));
end
fprintf(qqq, 'end;'); %使用fprintf打印end;
fclose(qqq);
生成的.mif文件内容如下:
对应的调数据代码为:
module fangwen(clk,dout1,dout2);
input clk;
output dout1,dout2;
wire [10:0] dout1,dout2;
reg [9:0] addr1 =0,addr2 =0;
rom rom1(
.clock(clk),
.address(addr1),
.q(dout1)
);
rom rom2(
.clock(clk),
.address(addr2),
.q(dout2)
);
always @(negedge clk)
begin
addr1<=addr1+1;
end
always @(negedge clk)
begin
addr2<=addr2+2;
end
endmodule
产生的载波效果如下:
2、通过产生m序列的方式模拟数字信源
信源部分代码为:
module DDS(clk,enable,code,dt);
input clk,enable;
output code,dt;
reg code=0;
reg [7:0] dt = 8'b1010_1010,cnt=0; //设置信源的初始状态
integer i=8;
always @(negedge clk)
begin
if(enable)
begin
if(i!=1)
begin
code<=dt[i-1];
i=i-1;
end
else
begin
code<= dt[0];
dt <= dt<<1;
dt[0]<=((dt[7]^dt[3])^dt[2])^dt[1];
i<=8;
cnt<=cnt+1'b1;
end
end
else
begin
code<=code;
i<=8;
end
end
endmodule
波形如下:
3、将数字信息加载在载波上
调制部分代码为:
module tiaozhi(clk,enable,shuchu,clk1);//顶层
input clk,enable;
output shuchu,clk1;
wire [7:0] dt;
reg clk1=0;
wire [10:0] dout1,dout2;
wire code;
wire [10:0] shuchu;
reg [9:0] sum1=0;
always @(negedge clk)
begin
sum1<=sum1+1; //计数,看什么时候下一个周期,用来控制下一个码元的出现
if(sum1==10'd1023)
clk1=~clk1;
end
fangwen u1(.clk(clk),.dout1(dout1),.dout2(dout2));
DDS u2(.clk(clk1),.enable(enable),.code(code),.dt(dt));
switch u3(.clk(clk),.code1(code),.dataout(shuchu),.d1(dout1),.d2(dout2));
endmodule
module switch(clk,code,dataout,d1,d2);
input clk;
input code;
input d1,d2;
wire [10:0] d1,d2;
output dataout;
reg [10:0]dataout;
always @(negedge clk)
begin
case(code)
1'b1:dataout<=d1;
1'b0:dataout<=d2;
endcase
end
endmodule
4、通过解调的方式将数字信息恢复出来
解调部分采用过零检测的方法,即数一个码元周期内零点的个数,个数多的是高频对应原数字信息1,反之则对应0。
具体功能模块代码为:
module jietiao(clk,enable,count,cnt,dout,shuchu,code);
input clk,enable;
wire code;
output dout;
output count,cnt,shuchu;//count记512(相当于记零点)的个数,cnt记脉冲的个数,shuchu是引的调制的输出
output code;
reg [10:0] buffer;
wire[10:0]shuchu;
reg [10:0] cnt=0;
reg dout=0; //输出的为原基带信号 0 1
integer count=0;
//实例化部分
wire clk1;
always @(negedge clk)
begin
buffer<=shuchu;
cnt<=cnt+1;
if(buffer==11'b01000000000)
count<=count+1;
if(cnt==2047)
begin
if(count<=6)
dout<=1;
else
dout<=0;
count<=0;
end
end
tiaozhi u1(.clk(clk),.enable(enable),.shuchu(shuchu),.clk1(clk1),.code(code));
endmodule
测试模块代码为:
module jietiao_tb;
reg clk=0;
wire dout;
wire [10:0] cnt;
wire [10:0]shuchu;
reg enable=1;
wire code;
always #2 clk=~clk;
jietiao u1(.clk(clk),.enable(enable),.cnt(cnt),.dout(dout),.shuchu(shuchu),.code(code));
endmodule
三、仿真结果
可以发现,这样便实现了2FSK调制解调器的功能。