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

 

 

  • 5
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
FPGA ASK解调是指在FPGA芯片上对ASK信号进行解调的过程。解调的目的是从ASK信号的包络中恢复出原始的ASK信息。在解调过程中,有两个关键的步骤,即判决门限的获取和抽样。 判决门限的获取是通过记录多个符号周期内的最大值来确定的。在每个符号周期内,通过包络检波得到的包络数据会有明显的变化。当符号为0时,包络数据较小;当符号为1时,包络数据较大。因此,可以通过记录多个符号周期内的最大值来确定判决门限。具体的实现过程是使用一个计数器来计算5个符号周期的时间,判决门限会每5个符号周期进行一次变化。在每个5个符号周期内,通过比较相邻的两个5个符号周期内的判决门限的值,如果新的判决门限与前一个5个符号周期的判决门限相差较大,则保持前一个5个符号周期的判决门限。这样做的目的是防止连续的0或连续的1出现,导致判决门限出错,进而影响接下来的解调过程。 抽样是指在什么时刻对信号进行取值。在解调过程中,需要对ASK信号进行抽样,以获取信号的具体取值。抽样的时机通常是在每个符号周期的中间位置。通过在合适的时机对信号进行抽样,可以准确地恢复出ASK信号的原始信息。 综上所述,FPGA ASK解调的过程包括判决门限的获取和抽样。判决门限的获取是通过记录多个符号周期内的最大值来确定的,而抽样是在合适的时机对信号进行取值,以恢复出ASK信号的原始信息。 #### 引用[.reference_title] - *1* [【FPGA-ASK调制解调】2-ASK调制和解调的Verilog代码实现](https://blog.csdn.net/qq_42605300/article/details/116127517)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [FPGA数字信号处理基础----ASK解调的判决门限与抽样](https://blog.csdn.net/qq_41332806/article/details/110483693)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜yuan~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值