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

 

 

<think>好的,用户问的是如何区分PC和H5获取录音权限。首先,我需要明确用户的需求。他们可能是在开发一个需要录音功能的Web应用,想要了解在桌面浏览器(PC)和移动浏览器(H5)上获取麦克风权限的不同方法。需要从技术实现、API使用、用户交互、兼容性等方面进行分析。 首先,回忆一下Web Audio API的相关知识。在Web开发中,获取用户麦克风权限通常使用navigator.mediaDevices.getUserMedia方法。这个方法在PC和移动端的基本调用方式是一样的,但实际应用中可能会有差异。需要分步骤说明两者的不同点。 接下来,权限请求的触发方式。在PC端,大多数浏览器要求用户必须在用户交互(比如点击事件)中触发权限请求,否则会被阻止。而在移动端,尤其是H5页面,可能同样需要用户交互,但不同移动浏览器的行为可能不同。需要确认这一点,是否有例外情况。 然后,用户提示的差异。PC端浏览器通常会在地址栏显示权限请求的图标,而移动端可能会以弹窗或底部提示的方式出现。这里可能需要具体举例,比如Chrome在PC和手机上的不同表现。 安全上下文的要求。无论是PC还是移动端,使用getUserMedia都需要在HTTPS环境下,本地开发环境(localhost)除外。这一点是否一致?需要确认。 设备检测方面,移动端可能需要处理更多设备适配问题,比如前后麦克风的选择,而PC端可能通常只有一个麦克风。但这里可能需要更准确的描述,比如移动设备可能有多个麦克风,但通常由系统管理,而开发者可能不需要特别处理。 兼容性问题。需要列举不同浏览器在PC和移动端对录音权限的支持情况。比如Safari在iOS上的限制,或者某些安卓浏览器的不同行为。 接下来,代码示例部分。需要提供一个基本的请求麦克风权限的代码示例,并指出在PC和H5中的注意事项。比如在移动端可能需要处理自动播放策略,或者用户拒绝后的不同处理方式。 另外,权限持久化方面,PC端浏览器可能会记住用户的选择,而移动端可能每次都需要重新请求,或者有不同的会话管理方式。需要确认不同浏览器的具体行为。 最后,总结关键点,帮助用户区分两者的主要差异,比如触发方式、用户提示、兼容性处理等。确保回答结构清晰,步骤明确,用户能够逐步理解和应用。 需要验证一些不确定的点,比如移动端是否真的每次都需要用户交互触发,或者不同浏览器是否有不同的策略。例如,iOS上的Safari对getUserMedia的调用是否有严格的用户手势要求,而Chrome on Android是否允许在某些情况下自动触发。此外,权限请求的UI展示在不同平台上的具体表现,可能需要进一步查证。 另外,设备检测方面,是否需要使用mediaDevices.enumerateDevices来列出麦克风设备,这在移动端是否有必要,或者是否通常只有一个可用麦克风。这部分可能需要简化,避免复杂化问题。 最后,确保回答符合用户可见层的要求,结构清晰,逐步解决问题,并且内容真实可靠。避免技术错误,比如错误的API名称或不兼容的浏览器示例。</think>区分PC端和移动端H5获取录音权限的实现差异,主要涉及浏览器API调用方式、用户交互流程及兼容性处理。以下是关键点分析: --- ### **一、核心API调用** 无论PC或H5均使用Web API `navigator.mediaDevices.getUserMedia()`,但实现细节不同: ```javascript // 通用代码框架 async function requestMicrophone() { try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); // 成功获取音频流 } catch (error) { // 处理权限拒绝或错误 } } ``` --- ### **二、用户交互差异** | **场景** | **PC端** | **H5(移动端)** | |----------------|----------------------------------------|---------------------------------------| | **触发条件** | 需用户主动交互(如点击按钮) | 同样需用户手势触发,部分浏览器更严格 | | **权限弹窗** | 浏览器顶部地址栏提示 | 系统级弹窗或底部提示栏 | | **持久化策略** | 浏览器可记住用户选择 | 部分移动浏览器每次刷新需重新授权 | --- ### **三、兼容性注意事项** 1. **PC端重点问题** - 旧版Edge/Firefox 需处理 `getUserMedia` 前缀 - Safari 要求 HTTPS 环境 2. **H5移动端特殊处理** - **iOS Safari**:首次拒绝后需手动开启(设置 > Safari > 麦克风) - **微信浏览器**:需配置JS接口安全域名 - **安卓WebView**:需应用层声明录音权限 --- ### **四、关键代码适配技巧** 1. **检测设备类型** ```javascript const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); ``` 2. **错误处理优化** ```javascript catch (error) { if (error.name === 'NotAllowedError') { // 提示用户手动开启权限 if (isMobile) alert('请前往系统设置启用麦克风权限'); } } ``` 3. **自动播放策略(H5重点)** ```javascript // 移动端需在用户交互后立即播放音频,避免静音阻塞 audioElement.play().catch(() => { /* 处理自动播放失败 */ }); ``` --- ### **五、调试建议** 1. **PC端**:使用Chrome `chrome://settings/content/microphone` 管理权限 2. **H5移动端**: - Android Chrome:长按页面 > 站点设置 - iOS Safari:需完全关闭页面后重新进入 --- ### **总结** - **本质相同**:均依赖 `getUserMedia` API,但交互流程和系统限制不同 - **核心差异**:移动端涉及更多系统级权限管控和浏览器兼容问题 - **适配关键**:结合设备检测优化提示逻辑,优先在HTTPS环境部署
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

菜菜菜~~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值