笔记八是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文件的生成
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%% 二进制码序列的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. 顶层文件
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113module 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. 测试文件
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
37module 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调制解调内容请搜索靠谱客的其他文章。
发表评论 取消回复