Verilog实现2FSK调制

2FSK数字调制实现

      • FSK原理

FSK原理

FSK(Frequency Shift-Keying)频移键控分为非连续相位FSK和连续相位FSK,区别在于转换处是否连续。
Verilog实现2FSK调制_第1张图片

  • 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仿真结果,第一二列为载波,第三列为基波,最后一列为调制后信号
    Verilog实现2FSK调制_第2张图片
  • vivado仿真结果
    Verilog实现2FSK调制_第3张图片

你可能感兴趣的:(IC,matlab,verilog,信号处理)