FM调制解调---FPGA

这篇具有很好参考价值的文章主要介绍了FM调制解调---FPGA。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        实验通过编写一个DMA读模块获取FM调制的数据源,DMA模块的实现是基于AXI协议。因为在数据的传输中,Xilinx提供的官方DMA IP核在传输完一次突发数据后需要在PS 端重新启动一次都或者写操作,如此的话,在进行大量数据的传输工作时,尤其是对DDR 不同地址区域同时进行读写操作时,IP 核不能有效工作。所以通过创建一个模块用于读取DDR,无需PS端参与即可完成读DDR操作。

 AXI_DMA_RD模块突发读时序:

FM调制解调---FPGA

        该模块读取的内容是先由PS端提前写入DDR某一地址区间的音频数据,按照AXI突发读时序进行数据读取,同时需要添加FIFO IP核来完成数据位宽转换和跨时钟域处理。为了防止数据丢失,当判断FIFO写入数据计数器为0,才启动一次突发读DDR。

 FIFO 读时序:

FM调制解调---FPGA

         FM调制模块:

        依据调频信号的数学表达式:

        FM调制解调---FPGA

        实现图中公式高亮部分,需要用到两个ROM IP用于存放正余弦波形,正余弦波形可由matlab获得,以及一个乘法器IP完成调制中的乘法操作。

c = 0:1/1024:1023/1024; %ROM 中有 1024 点
c_rom = fix(1024*sin(2*pi*c));
%c_rom = fix(1024*cos(2*pi*c));

         重要参数:调频灵敏度Kf 和 最大频偏频率控制字 W

         FM调制解调---FPGA

         FM解调模块:

        首先用两个寄存器将接收到的 I Q 两路数据进行缓存,再用两个寄存器进行延时一拍,就可以得到 i(i)i(i-1)q(i)q(i-1),再调用乘法器完成乘法运算,再将乘法器结果进行加减运算,再进行除法,即可得到解调结果。

        FM调制解调---FPGA

module fm_demod(
		input	wire 			sclk,
		input	wire 			rst_n,
		input	wire 			adc_valid,
		input	wire 	[11:0]	adc_data_i,
		input	wire 	[11:0]	adc_data_q,
		input	wire 	[31:0]	end_count,

		output	reg 			dmsout,
		output	reg		[15:0]	dmout

	);

reg 	[11:0]	i_fm=0,q_fm=0,i_fm_r=0,q_fm_r=0;
reg 	isin,isin_r;
wire  [23:0] cr1,cr2,cj1,cj2;
reg 	[23:0] cr,cj;
reg 			flag1=0;
reg 	[23:0]	cjabs=0;
reg 	[23:0]	cj_r,cr_r;
reg 			flag2;
reg 	[23:0]	dividend=0;
reg 	[23:0]	divisor =1;
reg 			flag3;
wire 			div_valid;
wire 	[39:0]  div_dout;
reg 	[23:0]	cr_r3,cj_r3;
wire 	[23:0]	cr_fifo_data,cj_fifo_data;
reg 	[39:0]	angle=0;	
reg 			div_valid_r;	
wire 	[15:0]	pi4;
wire 	[55:0]	angle_r;
reg 	[23:0]	cj_r4;
reg 	[23:0]	cj_r5;
reg 	[55:0]	angle_dout;		
reg 			div_valid_rr;
reg 			angel_dsout;
reg 	[11:0]		cnt_mean;
reg 	[49:0]	dm_sum;

reg		[11:0]	i_data,q_data;
wire	[11:0]	i_data_16,q_data_16;
reg				adc_valid_r;


// LPF
assign i_data_16 = {i_data[11],i_data[11],i_data[11],i_data[11],i_data[11:4]};
assign q_data_16 = {q_data[11],q_data[11],q_data[11],q_data[11],q_data[11:4]};
always @(posedge sclk) begin
	if (rst_n == 1'b0) begin		// reset
		i_data	<=	0;
		q_data	<=	0;
	 end
	else if (adc_valid == 1'b1) begin
		i_data	<=	{adc_data_i[11],adc_data_i[11],adc_data_i[11],adc_data_i[11],adc_data_i[11:4]} + i_data - i_data_16;
		q_data	<=	{adc_data_q[11],adc_data_q[11],adc_data_q[11],adc_data_q[11],adc_data_q[11:4]} + q_data - q_data_16;
	 end
end

always @(posedge sclk) begin
	adc_valid_r <= adc_valid;
end


always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		{i_fm_r,i_fm} <= 'd0;
		{q_fm_r,q_fm} <= 'd0;
	end
	else if(adc_valid_r == 1'b1) begin
		{i_fm_r,i_fm} <= {i_fm,i_data};
		{q_fm_r,q_fm} <= {q_fm,q_data};
	end
end

always @(posedge sclk) begin
	{isin_r,isin} <= {isin,adc_valid_r};
end

mult_crcj mult_cr1 (
  .CLK(sclk),  // input wire CLK
  .A(i_fm),      // input wire [11 : 0] A
  .B(i_fm_r),      // input wire [11 : 0] B
  .P(cr1)      // output wire [23 : 0] P
);

mult_crcj mult_cr2 (
  .CLK(sclk),  // input wire CLK
  .A(q_fm),      // input wire [11 : 0] A
  .B(q_fm_r),      // input wire [11 : 0] B
  .P(cr2)      // output wire [23 : 0] P
);


mult_crcj mult_cj1 (
  .CLK(sclk),  // input wire CLK
  .A(q_fm),      // input wire [11 : 0] A
  .B(i_fm_r),      // input wire [11 : 0] B
  .P(cj1)      // output wire [23 : 0] P
);

mult_crcj mult_cj2 (
  .CLK(sclk),  // input wire CLK
  .A(i_fm),      // input wire [11 : 0] A
  .B(q_fm_r),      // input wire [11 : 0] B
  .P(cj2)      // output wire [23 : 0] P
);

always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		cr <= 'd0;
		cj <= 'd0;
	end
	else begin
		cr <= cr1+ cr2;
		cj <= cj1-cj2;
	end
end

always @(posedge sclk) begin
	flag1 <= isin_r;
end

always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		cjabs <= 'd0;
	end
	else if (flag1 == 1'b1 && cj[23] == 1'b1 ) begin
		cjabs <= (~cj) +1'b1;
	end
	else if (flag1 == 1'b1 && cj[23] == 1'b0 ) begin
		cjabs <= cj;
	end
end

always @(posedge sclk) begin
	{cj_r,cr_r} <= {cj,cr};
end

always @(posedge sclk) begin
	flag2 <= flag1;
end


always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		dividend <='d0;
		divisor <= 'd1;
	end
	else if (flag2 == 1'b1 && cr_r[23] == 1'b0) begin
		dividend <= cr_r - cjabs;
		divisor <= cr_r + cjabs;
	end
	else if (flag2 == 1'b1 && cr_r[23] == 1'b1) begin
		dividend <= cr_r + cjabs;
		divisor <= cjabs - cr_r;
	end
end

always @(posedge sclk) begin
	flag3 <= flag2;
end

div_gen_0 div_gen_0_inst (
  .aclk(sclk),                                      // input wire aclk
  .s_axis_divisor_tvalid(flag3),    // input wire s_axis_divisor_tvalid
  .s_axis_divisor_tdata(divisor),      // input wire [23 : 0] s_axis_divisor_tdata
  .s_axis_dividend_tvalid(flag3),  // input wire s_axis_dividend_tvalid
  .s_axis_dividend_tdata(dividend),    // input wire [23 : 0] s_axis_dividend_tdata
  .m_axis_dout_tvalid(div_valid),          // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata(div_dout)            // output wire [39 : 0] m_axis_dout_tdata
);

always @(posedge sclk) begin
	cr_r3 <= cr_r;
	cj_r3 <= cj_r;
end


fifo_w24x64_r24x64 cr_buffer (
  .clk(sclk),      // input wire clk
  .din(cr_r3),      // input wire [23 : 0] din
  .wr_en(flag3),  // input wire wr_en
  .rd_en(div_valid),  // input wire rd_en
  .dout(cr_fifo_data),    // output wire [23 : 0] dout
  .full(),    // output wire full
  .empty()  // output wire empty
);

fifo_w24x64_r24x64 cj_buffer (
  .clk(sclk),      // input wire clk
  .din(cj_r3),      // input wire [23 : 0] din
  .wr_en(flag3),  // input wire wr_en
  .rd_en(div_valid),  // input wire rd_en
  .dout(cj_fifo_data),    // output wire [23 : 0] dout
  .full(),    // output wire full
  .empty()  // output wire empty
);

always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		angle <='d0;
	end
	else if(div_valid == 1'b1 && cr_fifo_data == 'd0 && cj_fifo_data == 'd0) begin
		angle <='d0;
	end
	else if (div_valid == 1'b1 && cr_fifo_data[23] == 1'b0) begin
		angle <= 40'd65536 - div_dout;
	end
	else if(div_valid == 1'b1 && cr_fifo_data[23] == 1'b1) begin
		angle <= 40'd196608 - div_dout;
	end
end


always @(posedge sclk) begin
	div_valid_r <= div_valid;
end

assign pi4 =16'd51472;//PI/4  (3.1415926/4)*65536
mult_a40xb16 mult_a40xb16_inst (
  .CLK(sclk),  // input wire CLK
  .A(angle),      // input wire [39 : 0] A
  .B(pi4),      // input wire [15 : 0] B
  .P(angle_r)      // output wire [55 : 0] P
);

always @(posedge sclk) begin
	cj_r4 <= cj_fifo_data;
end

always @(posedge sclk) begin
	cj_r5 <= cj_r4;
end

always @(posedge sclk) begin
	div_valid_rr <= div_valid_r;
end

always @(posedge sclk) begin
	if(rst_n==  1'b0) begin
		angle_dout <='d0;
	end
	else if (div_valid_rr == 1'b1 &&  cj_r5[23] == 1'b0) begin
		angle_dout <= angle_r;
	end
	else if (div_valid_rr == 1'b1 &&  cj_r5[23] == 1'b1) begin
		angle_dout <= (~angle_r) + 1'b1;
	end
end

always @(posedge sclk) begin
	angel_dsout <= div_valid_rr;
end

always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		cnt_mean <='d0;
	end
	else if (angel_dsout == 1'b1 && cnt_mean == end_count[12:1]-1) begin
		cnt_mean <= 'd0;
	end
	else if (angel_dsout == 1'b1) begin
		cnt_mean <= cnt_mean + 1'b1;
	end
end

always @(posedge sclk)begin
	if(rst_n == 1'b0) begin
		dm_sum <= 'd0;
	end
	else if (angel_dsout == 1'b1 && cnt_mean == end_count[12:1]-1) begin
		dm_sum <='d0;
	end
	else if (angel_dsout == 1'b1 ) begin
		dm_sum <= dm_sum + {{10{angle_dout[55]}},angle_dout[55:16]};
	end
end

always @(posedge sclk) begin
	if(rst_n == 1'b0) begin
		dmout <='d0;
		dmsout <= 'd0;
	end
	else if (angel_dsout == 1'b1 && cnt_mean == end_count[12:1]-1) begin
		dmout <= {dm_sum[49],dm_sum[24:10]};
		dmsout <= 1'b1;
	end
	else begin
		dmsout <= 1'b0;
		dmout <= dmout; 
	end
end

endmodule 

FM调制解调---FPGA文章来源地址https://www.toymoban.com/news/detail-506661.html

到了这里,关于FM调制解调---FPGA的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 VIVADO 的 FM 调制解调(上)设计篇

            本文先简要介绍了频率调制(frequency modulation,FM,简称调频)的原理,然后对其进行方案设计,最后基于 VIVADO 2018.3 使用 Verilog 进行实现。         角度调制(angle modulation)是已调波的总相角  随着基带信号  作某种变化的调制方式,它包括频率调制和相位调制。

    2023年04月09日
    浏览(41)
  • Gnuradio 和 USRP 实现FM的调制与解调

    1. 硬件设备:HM B200mini; 天线 2. 软件环境: ubuntu 20.04; gnuradio 3.8; uhd 4.0; a. UHD: USRP Source USRP Source 块将通过在选定的天线上以特定频率、采样率和增益采样RF信号来产生基带样本。 b. Ratinal Resampler 因为USRP速率不是音频接收器速率的整数倍, 所以这里需要进行重采样。 c. WBFM Rec

    2024年02月12日
    浏览(36)
  • FIR 基础应用 - FM 调频波调制解调(FIR 低通滤波)

    本文链接:https://blog.csdn.net/qq_46621272/article/details/125337119 FIR 基础应用 - FM 调频波调制解调(FIR 低通滤波) 这是 XILINX FIR IP 详解、Verilog 源码、Vivado 工程 这篇文章的实验部分,用 FIR 低通滤波实现了调频波的解调输出。 和上篇文章 FIR 基础应用 - AM 调幅波调制解调(FIR 低通滤波

    2024年02月08日
    浏览(51)
  • 基于FPGA的FM信号解调

    这是本人第一次写博客,写的不好请多多担待。 本次实验是将一个已知的FM信号通过FPGA进行解调,解调出波形并进行FFT得到调制频率fm,并且每一步都通过MATLAB进行波形的验证。 已知FM信号的载波频率fc为22MHZ,调制信号频率fm为8KHZ,采样率为50MHZ,在MATLAB中采样20000个点,位

    2023年04月15日
    浏览(39)
  • FM调制的FPGA-DDS实现

    本文是作者最近的课程设计,花费了不少时间,以下是自己的一些思路,希望可以帮助到正在学习的你,理解关于FM调制的FPGA-DDS实现,接着往下看吧! 平台为  Quartus 17.1 波形生成软件为 Mif_Maker2010 FPGA芯片的型号为5CEFA5F23I7,系统时钟为50MHZ 关于FM: 简单来说就是: 幅度改

    2024年02月04日
    浏览(41)
  • 2ASK调制解调实验

    一,数字信号的键控调制 在数字调制技术中,由于数字信号具有离散值的特点,因此数字调制技术通常有两种 方法:一是利用模拟调制的方法去实现数字调制,即把数字调制看成是模拟调制的一个特 例,把数字基带信号当做模拟信号的特殊情况来处理;二是利用数字信号的

    2023年04月08日
    浏览(43)
  • 数字带通调制系统实验-BPSK的调制与解调

    1、实验原理 BPSK的调制原理 在二进制数字调制中,当正弦载波的相位随二进制数字基带信号离散变化 时,则产生二进制移相键控(2PSK)信号。通常用已调信号载波的0度和180 度分别表示二进制数字基带信号的1和0.二进制移相键控信号的时域表达式为 这种以载波的不同相位直接

    2024年02月02日
    浏览(65)
  • 基于FPGA的QPSK调制解调-------(1)QPSK调制技术的原理

    QPSK(正交相移键控)是M=4的MPSK一种,也可叫做四进制相移键控。即有四个不同相位的状态,每个码元需要传输2bit的数字信息,可由00、01、11、10组合来对应表示四个不同的相位0、pi/2、pi、3pi/2或pi/4、3pi/4、5pi/4、7pi/4。 由 QPSK调制原理框图如图所示:        首先将输入的数

    2024年02月04日
    浏览(51)
  • 基于FPGA的2FSK调制解调系统

            FSK作为数字通信中不可或缺的一种调制方式,其具有抗干扰能力强,不受信道参数的影响的优点,为此,设计合适的FSK调制解调系统便具有重要意义。   该系统产生主要分为三个步骤:         产生方式:通过matlab软件编程生成一个.mif文件,存放正弦波一个周期

    2024年02月03日
    浏览(48)
  • 基于FPGA的FSK调制解调系统verilog开发

    目录 1.算法仿真效果 2.verilog核心程序 3.算法涉及理论知识概要 4.完整verilog VIVADO2019.2仿真结果如下:       频移键控是利用载波的频率变化来传递数字信息。数字频率调制是数据通信中使用较 早的一种通信方式,由于这种调制解调方式容易实现,抗噪声和抗衰减性能较强,

    2024年02月05日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包