我是靠谱客的博主 苗条电话,最近开发中收集的这篇文章主要介绍FPGA学习笔记(八):ASK调制解调的仿真,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

笔记八是ASK调制解调的仿真实现。

ASK调制解调的实现原理:首先使用MATLAB产生存储基带波形的coe文件,再让ROM读取coe文件输出基带波形,然后DDS产生正弦波信号作为载波信号,接下来使用乘法器将两者相乘产生ASK信号,ASK信号与载波信号相乘之后,再经过FIR低通滤波器解调出基带波形再抽样判决。

 1. 打开VIVADO,点击IP Catalog

 

 2. 搜索ROM,点击Block Memory Generator

 3. ROM的配置

(1) 选择Single Port ROM

 

 (2) 选择需要加载的coe文件的位宽和深度

 

(3) 加载coe文件 

 

 coe文件的生成

%% 二进制码序列的coe文件生成
clear all ;                 % 清除变量
clc ;                       % 清屏
N = 8 ;                     
L = 512;                    % 每个码元的采样点数
y = zeros(4096 , 1) ;       % 生成4096行1列的全为1的列向量
% 生成4096行1列取值为0,1的二进制码序列向量
% 最大值为1,因此数据位宽为1bit
% code = randi([0,1],1,N);   %N为码元个数 
code = [1 1 0 1 1 0 0 1];
fz=ones(1,L);             %定义复制的次数L,L为每码元的采样点数
x1=code(fz,:);            %复制的第1行复制L次,将原来wave的第一行复制L次,称为L*M的矩阵
dnrz=reshape(x1,1,L*N);   %产生单极性不归零矩形脉冲波形,将刚得到的L*M矩阵,按列重新排列形成1*(L*M)的矩阵
y = 255*dnrz';
plot(y);                    % 绘制图像
hold on;                    % 保留之前的图,实现多图共存
fid = fopen('mayuan_4096_2.coe','wt');% 以写的形式创建文件,文件名为mayuan_4096_1.coe     
% 文件格式保存为十进制,以换行隔开 
fprintf( fid, 'MEMORY_INITIALIZATION_RADIX = 10;n');                     
fprintf( fid, 'MEMORY_INITIALIZATION_VECTOR =n');
% 将上面的矩形波值写入文件
for i = 1:1:4096
    fprintf(fid,'%d,n',y(i,1));  
end
fclose(fid);                % 关闭文件

4. 搜索DDS,点击DDS Complier

 

 5. DDS参数配置 依照之前配置DDS IP核

 

 

 

 6. 点击IP Catalog,搜索mult,选择Multiplier

 

 

 7. 参数配置

 

 同样配置另外一个Multiplier

 

8. 点击IP Catalog,搜索fir,选择FIR Complier 

 

 9. 配置参数

(1) 选择coe文件格式,将FIR 的coe文件加载进去,FIR低通滤波器的设计可以参照

(3条消息) FPGA学习笔记(六): FIR IP核的使用_菜yuan~的博客-CSDN博客

低通滤波器的带宽一般设置为第一零点带宽,即基带码元宽度的倒数,采样频率满足奈奎斯特采样定理就行。

 

 (2) 采样频率 50kHz,时钟频率 50MHz

 

 (3) 输入信号位宽为24bit,滤波器抽头系数16个

 

 10. 顶层文件

module ASK_top(
    input clk,			// 输入clk
    input rst_n,		// 输入复位
    output [7:0] dout,	// 输出8位波形,数据宽度,码元输入
	output clk2,			// 输出clk2
	output sig1,				// 输出余弦信号,即载波信号
	output sig2,				// 输出已调信号
	output sig3,				// 输出已调信号和载波相乘
	output code,				// 输出判决码元
	output fir_out,				// fir滤波后的截断信号
	output sig4				// 输出fir滤波信号
    );
	reg ena_reg;			// ROM使能信号
	reg [24:0]  counter;	//
    reg clk2;
	wire [7:0] sig1;
	wire [15:0] sig2;
	wire [23:0] sig3;
	wire [47:0] sig4;
	wire [15:0] fir_out;
	reg   [7:0] code;
	
// 设计计数器,分频使用,10分频
always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)					
            counter <= 1'b0;
        else if (counter == 4)
            counter <= 1'b0;
        else
            counter <= counter + 1'b1;
    end
// 产生10分频的clk2
always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            clk2 <= 1'b0;
        else if(counter == 4)
            clk2 <= !clk2;
    end
		
// ROM使能信号
always@(posedge clk2 or negedge rst_n)
    begin
        if(~rst_n)
            ena_reg <= 0;
        else
            ena_reg <= 1;
    end
// ROM的地址
reg [11:0] addr_reg; 	

always@(posedge clk2 or negedge rst_n)
    begin
        if(~rst_n)
            addr_reg <= 12'd0;
        else
            addr_reg <= addr_reg + 1;
    end


  
// ROM的例化,产生码元方波信号

blk_mem_gen_0 U1 (
  .clka(clk2),    // input wire clka
  .ena(ena_reg),      // input wire ena
  .addra(addr_reg),  // input wire [11 : 0] addra
  .douta(dout)  // output wire [7 : 0] douta
);
// DDS的例化,产生载波信号
dds_compiler_0 U2 (
  .aclk(clk),                              // input wire aclk
  .m_axis_data_tvalid(m_axis_data_tvalid),  // output wire m_axis_data_tvalid
  .m_axis_data_tdata(sig1)    // output wire [7 : 0] m_axis_data_tdata
);
// 乘法器的例化,产生已调信号
mult_gen_0 multi0 (
  .CLK(clk),  // input wire CLK
  .A(dout),      // input wire [7 : 0] A
  .B(sig1),      // input wire [7 : 0] B
  .P(sig2)      // output wire [15 : 0] P
);
// 乘法器的例化,产生已调信号和载波相乘
mult_gen_1 multi1 (
  .CLK(clk),  // input wire CLK
  .A(sig2),      // input wire [15 : 0] A
  .B(sig1),      // input wire [7 : 0] B
  .P(sig3)      // output wire [23 : 0] P
);
// fir低通滤波器的例化
fir_compiler_0 U3 (
  .aclk(clk),                              // input wire aclk
  .s_axis_data_tvalid(1'b1),  // input wire s_axis_data_tvalid
  .s_axis_data_tready(),  // output wire s_axis_data_tready
  .s_axis_data_tdata(sig3),    // input wire [23 : 0] s_axis_data_tdata
  .m_axis_data_tvalid(),  // output wire m_axis_data_tvalid
  .m_axis_data_tdata(sig4)    // output wire [39 : 0] m_axis_data_tdata
);
//fir的截断
assign fir_out = sig4[47:22];
// 判决
always@(posedge clk)
    begin
        if(!rst_n)					
            code <= 1'b0;
        else if (sig4 == 0)
            code <= 8'd0;
        else
            code <= 8'd255;
    end

endmodule

 11. 测试文件

module ASK_tb();
    reg clk;			// 输入clk
    reg rst_n;			// 输入复位
	wire clk2;
    wire [7:0] dout;	// 输出8bit波形数据
    wire [7:0] sig1;	// 输出信号1	
	wire [15:0] sig2;    // 输出信号2
	wire [23:0] sig3;    // 输出信号3
	//wire [39:0] sig4;    // 输出信号4
	wire [15:0] fir_out;
	wire [7:0] code;
// 顶层文件的例化
ASK_top u0 (
  .clk(clk),
  .clk2(clk2),
  .rst_n(rst_n),
  .dout(dout),
  .sig1(sig1),
  .sig2(sig2),
  .sig3(sig3),
  //.sig4(sig4),
  .fir_out(fir_out),
  .code(code)
);

//reg memdata[0:7] ;

initial					// 初始化
begin
    clk = 1;			// 初始clk为高电平
    rst_n = 0;			// 复位为低电平
    #1					// 延时50ns
    rst_n = 1;			// 复位为高电平
//$readmemb("F:/shiyan/lab/ASK/data.txt",memdata);
end
always #10 clk = ~clk;	// clk周期为20ns
endmodule

 12. 结果显示

(1) dout和code的Waveform Style要选择Analog Settings中的hold,这样才能产生方波信号,并且Radix要选择Unsigned Decimal

 

 

 

 除fir_outd其余信号的Waveform Style同样操作,Radix选择Signed Dicemal

Fir_out 的Waveform Style选择Analog就可以,Radix选择Unsigned Dicemal

 

 

最后

以上就是苗条电话为你收集整理的FPGA学习笔记(八):ASK调制解调的仿真的全部内容,希望文章能够帮你解决FPGA学习笔记(八):ASK调制解调的仿真所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部