AM调制的FPGA实现

				版权声明:本文为博主原创文章,如果觉得不错欢迎转载,记得标明出处就行。					https://blog.csdn.net/HOOKNET/article/details/79129451				</div>
							<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
							            <div id="content_views" class="markdown_views">
						<!-- flowchart 箭头图标 勿删 -->
						<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
						<h2 id="一说明"><a name="t0"></a>一、说明:</h2>
  1. 功能:AM调制
  2. 平台:Vivado 2016.4 和 Matlab R2017a

二、原理:

1. AM调制原理

  • AM已调信号的时域表达式:

  • 已调信号的频域表达式:
    这里写图片描述
    本质上AM调制就是频谱的搬移。

  • AM调制的系统框图

    将调制信号加上一个直流分量,保证信号的最小值大于零,然后再和载波相乘,得到已调信号。

三、AM调制的FPGA实现

1.产生调制信号和载波信号

调用ROM IP核在FPGA内部产生两路余弦信号,其中一路信号用于模拟外部输入的调制信号,另一路用作载波信号。
在配置ROM IP核之前,需要用Matlab生.coe文件,存放在ROM核里。

  • Matlab生成.coe文件:
%---------------------------------%
width=8;       %设置rom的位宽
depth=1024;     %设置rom的深度
%---------------------------------%

x=linspace(0,2*pi,depth);       %在一个周期内产生depth个采样点
y_cos=cos(x);                   %生成余弦函数
%y_cos=sin(x);                   %生成正弦函数
%y_cos=round(y_cos*(2^(width-1)-1))+2^(width-1)-1;       %将数据转化成整数,生成无符号数
y_cos=round(y_cos*(2^(width-1)-1));       %将数据转化成整数,生成有符号数

plot(x,y_cos);                  %绘图

fid = fopen('E:\Workspace\DDS\Design\IP_Core\cos.coe','wt');

fprintf(fid,'memory_initialization_radix = 10;\nmemory_initialization_vector = ');
for i = 1 : depth
    if mod(i-1,8) == 0 
        fprintf(fid,'\n');
    end
    fprintf(fid,'%6d,',y_cos(i));
end

fclose(fid);                    %关闭文件
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

生成.coe文件后就可以进行IP核的配置了。

  • ROM核具体配置:



配置完IP核后,编写控制模块,产生两路信号。其中,调制信号上叠加的直流分量的大小为调制信号的峰值,这样将得到调制度为100%的已调信号。如果要得到不同的调制度,则需要叠加不同大小的直流分量,同时需要注意定义的数据位宽,防止数据溢出。

  • 产生载波和带有直流分量的调制信号:
module cos_make(
    input   clk,
    input   rst_n,
    output  reg [7:0]   cos_s,
    output  reg signed  [7:0]   cos_c
);

//------------------------------------//
parameter freq_s = 32'd429497;          //调制信号频率10k
parameter freq_c = 32'd42949673;        //载波频率1M
parameter cnt_width = 8'd32;
//------------------------------------//

//------------------------------------//
reg     [cnt_width-1:0] cnt_s = 0;
reg     [cnt_width-1:0] cnt_c = 0;
wire    [9:0]   addr_s;
wire    [9:0]   addr_c;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)  begin
        cnt_s <= 0;
        cnt_c <= 0;
    end
    else    begin
        cnt_s <= cnt_s + freq_s;
        cnt_c <= cnt_c + freq_c;
    end
end

assign  addr_s = cnt_s[cnt_width-1:cnt_width-10];
assign  addr_c = cnt_c[cnt_width-1:cnt_width-10];
//------------------------------------//

//------------调用ROM核----------------//
wire    signed  [7:0]   cos_s_r;
wire    signed  [7:0]   cos_c_r;

ROM         ROM_inst(
    .clka   (clk),
    .addra  (addr_s),
    .douta  (cos_s_r),
    .clkb   (clk),
    .addrb  (addr_c),
    .doutb  (cos_c_r)
);

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)  begin
        cos_s <= 0;
        cos_c <= 0;
    end
    else    begin
        cos_s <= cos_s_r + 8 'd128;     //加上大小为峰值的直流分量
        cos_c <= cos_c_r;
    end
end

endmodule

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

2.生成AM调制信号

得到两路信号后就可以用乘法器将两路信号相乘,得到已调信号。

  • 乘法器具体配置:

  • AM调制的顶层模块:

module modulate(
    input       clk,
    input       rst_n,
    output  signed  [15:0]  AM_mod
);

wire    [7:0]   cos_s;
wire    signed  [7:0]   cos_c;

//------------调用出波模块------------//
cos_make        cos_make_inst0(
    .clk            (clk),
    .rst_n      (rst_n),
    .cos_s      (cos_s),
    .cos_c      (cos_c)
);
//-----------------------------------//

//------------调用乘法器--------------//
MULT        MULT_inst1(     
  .CLK  (clk),
  .A        (cos_s),
  .B        (cos_c),
  .P        (AM_mod)
);

endmodule

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.仿真调制结果

以上AM调制过程基本完成,但是正确与否还需要通过仿真来确定,接下来编写仿真用的测试模块。

  • TestBeach的编写:
`timescale 1ns/1ps

module tb_AM();

//---------接口设置----------//
reg     sclk;
reg     rst_n;
wire    signed  [15:0]  AM_mod;
//--------------------------//
initial     sclk = 1;
always  #5  sclk = ~sclk;      //100M时钟

initial begin
    rst_n = 0;
    #500
    rst_n = 1;
end
//--------------------------//
modulate        modulate_inst0(
    .clk        (sclk),
    .rst_n      (rst_n),
    .AM_mod     (AM_mod)
);

endmodule

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在Vivado中将各个文件添加进工程后,运行仿真。

  • 仿真结果如下:

已调信号能明显看到包络,并且包络的频率同调制信号一致,表明AM调制正确。

				版权声明:本文为博主原创文章,如果觉得不错欢迎转载,记得标明出处就行。					https://blog.csdn.net/HOOKNET/article/details/79129451				</div>
							<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
							            <div id="content_views" class="markdown_views">
						<!-- flowchart 箭头图标 勿删 -->
						<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
						<h2 id="一说明"><a name="t0"></a>一、说明:</h2>

猜你喜欢

转载自blog.csdn.net/weixin_37182342/article/details/89502585