ZYNQ上的简单 FSK 基带发射器

这篇具有很好参考价值的文章主要介绍了ZYNQ上的简单 FSK 基带发射器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ZYNQ上的简单 FSK 基带发射器,fpga开发

绪论

由于某种需求需要生成正弦波,因此使用 C 应用程序中的sin()函数来计算单位圆的幅度值,然后将该幅度值转换为 AD9717 的适当 DAC 代码(当然将每个角度值转换为弧度)。

ZYNQ上的简单 FSK 基带发射器,fpga开发

能够使用DAC生成简单的正弦波,下一个想法就是在 SDR(软件定义无线电)中使用频率调制。

大多数 SDR 设计都有 3 个不同的内部运行频率:一个低基带频率,用于处理来自 ADC/DAC 的数据;一个或多个中间频率,最终基带数据流作为中间步骤提升到该频率;以及最终的 RF 将输入/输出天线的输出频率。显然,最简单的起点是基带,因为它是最低频率,并且是实际模拟数据流从各个数字数据位组合在一起/提取的地方。为了进一步缩小范围,1 和 0 的数字位与某些相关模拟波形相关的确切点被称为符号映射器,它是前面提到的 SDR 基本构建块。

因此,本项目将是一个非常简化的基带符号映射器,用于 FSK 数字调制方案的链(数字到模拟)的发送端。

数字调制

频移键控 (FSK) 是一种数字调制,通过更改频率来表示数据流中的不同位/符号。在其最基本的形式中,一个频率用于表示二进制 1,另一个频率用于表示二进制 0。这种形式的 FSK 被称为二进制 FSK 或 2-FSK。

ZYNQ上的简单 FSK 基带发射器,fpga开发

从上面可以看出,1比特由大约是表示0比特的频率的两倍的频率来表示。对于 ZYNQ+SDR 来说,这意味着它需要能够分别以连续相位输出两个不同的频率。换句话说:定时在这里很重要,可以确保一个频率的相位恰好在最后一个频率的相位停止的地方出现。每个频率的一个完整周期也是每一位完成的。

Vivado 中的逻辑设计

由于本演示中只关注发送器端,为了处理符号映射器逻辑可能在 MM2S 读取中对来自 DDR 内存的数据流施加的背压,将带有 FSK 符号映射器的 sin LUT 放置在 AXIS 数据 FIFO 和 DAC 控制器 IP 之间。这样,FIFO 可以完成从内存的 MM2S 传输,当符号映射器逻辑每比特输出一个周期的相应频率值时,AXI DMA 不会被锁定tdata。

ZYNQ上的简单 FSK 基带发射器,fpga开发

代码如下:

`timescale 1ns / 1ps

module sin_lut(
    input clk,
    input rst,
    input [8:0] sel,
    output [15:0] DAC_code
    );
    
    reg [15:0] DAC_code;
    
    always @ (posedge clk)
        begin
            if (rst == 1'b0)
                begin 
                end
            else 
                begin
                    case (sel)
                        9'd0   : DAC_code = 16'h0000;
                        9'd1   : DAC_code = 16'h01C8;
                        9'd2   : DAC_code = 16'h0390;
                        9'd3   : DAC_code = 16'h0558;
                        9'd4   : DAC_code = 16'h0724;
                        9'd5   : DAC_code = 16'h08EC;
                        9'd6   : DAC_code = 16'h0AB0;
                        9'd7   : DAC_code = 16'h0C78;
                        9'd8   : DAC_code = 16'h0E3C;
                        9'd9   : DAC_code = 16'h1004;
                        9'd10  : DAC_code = 16'h11C4;
                        9'd11  : DAC_code = 16'h1388;
                        9'd12  : DAC_code = 16'h1548;
                        9'd13  : DAC_code = 16'h1708;
                        9'd14  : DAC_code = 16'h18C4;
                        9'd15  : DAC_code = 16'h1A7C;
                        9'd16  : DAC_code = 16'h1C38;
                        9'd17  : DAC_code = 16'h1DEC;
                        9'd18  : DAC_code = 16'h1FA0;
                        9'd19  : DAC_code = 16'h2154;
                        9'd20  : DAC_code = 16'h2304;
                        9'd21  : DAC_code = 16'h24B0;
                        9'd22  : DAC_code = 16'h2658;
                        9'd23  : DAC_code = 16'h2800;
                        9'd24  : DAC_code = 16'h29A4;
                        9'd25  : DAC_code = 16'h2B44;
                        9'd26  : DAC_code = 16'h2CE0;
                        9'd27  : DAC_code = 16'h2E78;
                        9'd28  : DAC_code = 16'h3010;
                        9'd29  : DAC_code = 16'h31A0;
                        9'd30  : DAC_code = 16'h3330;
                        9'd31  : DAC_code = 16'h34B8;
                        9'd32  : DAC_code = 16'h3640;
                        9'd33  : DAC_code = 16'h37C0;
                        9'd34  : DAC_code = 16'h3940;
                        9'd35  : DAC_code = 16'h3AB8;
                        9'd36  : DAC_code = 16'h3C2C;
                        9'd37  : DAC_code = 16'h3D9C;
                        9'd38  : DAC_code = 16'h3F08;
                        9'd39  : DAC_code = 16'h406C;
                        9'd40  : DAC_code = 16'h41D0;
                        9'd41  : DAC_code = 16'h432C;
                        9'd42  : DAC_code = 16'h4480;
                        9'd43  : DAC_code = 16'h45D0;
                        9'd44  : DAC_code = 16'h471C;
                        9'd45  : DAC_code = 16'h4864;
                        9'd46  : DAC_code = 16'h49A4;
                        9'd47  : DAC_code = 16'h4AE0;
                        9'd48  : DAC_code = 16'h4C14;
                        9'd49  : DAC_code = 16'h4D44;
                        9'd50  : DAC_code = 16'h4E6C;
                        9'd51  : DAC_code = 16'h4F90;
                        9'd52  : DAC_code = 16'h50AC;
                        9'd53  : DAC_code = 16'h51C4;
                        9'd54  : DAC_code = 16'h52D4;
                        9'd55  : DAC_code = 16'h53DC;
                        9'd56  : DAC_code = 16'h54E0;
                        9'd57  : DAC_code = 16'h55DC;
                        9'd58  : DAC_code = 16'h56D4;
                        9'd59  : DAC_code = 16'h57C0;
                        9'd60  : DAC_code = 16'h58A8;
                        9'd61  : DAC_code = 16'h598C;
                        9'd62  : DAC_code = 16'h5A64;
                        9'd63  : DAC_code = 16'h5B38;
                        9'd64  : DAC_code = 16'h5C04;
                        9'd65  : DAC_code = 16'h5CC8;
                        9'd66  : DAC_code = 16'h5D88;
                        9'd67  : DAC_code = 16'h5E3C;
                        9'd68  : DAC_code = 16'h5EEC;
                        9'd69  : DAC_code = 16'h5F94;
                        9'd70  : DAC_code = 16'h6034;
                        9'd71  : DAC_code = 16'h60CC;
                        9'd72  : DAC_code = 16'h6160;
                        9'd73  : DAC_code = 16'h61E8;
                        9'd74  : DAC_code = 16'h6268;
                        9'd75  : DAC_code = 16'h62E4;
                        9'd76  : DAC_code = 16'h6358;
                        9'd77  : DAC_code = 16'h63C0;
                        9'd78  : DAC_code = 16'h6424;
                        9'd79  : DAC_code = 16'h6480;
                        9'd80  : DAC_code = 16'h64D4;
                        9'd81  : DAC_code = 16'h6520;
                        9'd82  : DAC_code = 16'h6564;
                        9'd83  : DAC_code = 16'h659C;
                        9'd84  : DAC_code = 16'h65D0;
                        9'd85  : DAC_code = 16'h65FC;
                        9'd86  : DAC_code = 16'h6620;
                        9'd87  : DAC_code = 16'h663C;
                        9'd88  : DAC_code = 16'h6650;
                        9'd89  : DAC_code = 16'h665C;
                        9'd90  : DAC_code = 16'h6660;
                        9'd91  : DAC_code = 16'h665C;
                        9'd92  : DAC_code = 16'h6650;
                        9'd93  : DAC_code = 16'h663C;
                        9'd94  : DAC_code = 16'h6620;
                        9'd95  : DAC_code = 16'h65FC;
                        9'd96  : DAC_code = 16'h65D0;
                        9'd97  : DAC_code = 16'h659C;
                        9'd98  : DAC_code = 16'h6564;
                        9'd99  : DAC_code = 16'h6520;
                        9'd100 : DAC_code = 16'h64D4;
                        9'd101 : DAC_code = 16'h6480;
                        9'd102 : DAC_code = 16'h6424;
                        9'd103 : DAC_code = 16'h63C0;
                        9'd104 : DAC_code = 16'h6358;
                        9'd105 : DAC_code = 16'h62E4;
                        9'd106 : DAC_code = 16'h6268;
                        9'd107 : DAC_code = 16'h61E8;
                        9'd108 : DAC_code = 16'h6160;
                        9'd109 : DAC_code = 16'h60CC;
                        9'd110 : DAC_code = 16'h6034;
                        9'd111 : DAC_code = 16'h5F94;
                        9'd112 : DAC_code = 16'h5EEC;
                        9'd113 : DAC_code = 16'h5E3C;
                        9'd114 : DAC_code = 16'h5D88;
                        9'd115 : DAC_code = 16'h5CC8;
                        9'd116 : DAC_code = 16'h5C04;
                        9'd117 : DAC_code = 16'h5B38;
                        9'd118 : DAC_code = 16'h5A64;
                        9'd119 : DAC_code = 16'h598C;
                        9'd120 : DAC_code = 16'h58A8;
                        9'd121 : DAC_code = 16'h57C0;
                        9'd122 : DAC_code = 16'h56D4;
                        9'd123 : DAC_code = 16'h55DC;
                        9'd124 : DAC_code = 16'h54E0;
                        9'd125 : DAC_code = 16'h53DC;
                        9'd126 : DAC_code = 16'h52D4;
                        9'd127 : DAC_code = 16'h51C4;
                        9'd128 : DAC_code = 16'h50AC;
                        9'd129 : DAC_code = 16'h4F90;
                        9'd130 : DAC_code = 16'h4E6C;
                        9'd131 : DAC_code = 16'h4D44;
                        9'd132 : DAC_code = 16'h4C14;
                        9'd133 : DAC_code = 16'h4AE0;
                        9'd134 : DAC_code = 16'h49A4;
                        9'd135 : DAC_code = 16'h4864;
                        9'd136 : DAC_code = 16'h471C;
                        9'd137 : DAC_code = 16'h45D0;
                        9'd138 : DAC_code = 16'h4480;
                        9'd139 : DAC_code = 16'h432C;
                        9'd140 : DAC_code = 16'h41D0;
                        9'd141 : DAC_code = 16'h406C;
                        9'd142 : DAC_code = 16'h3F08;
                        9'd143 : DAC_code = 16'h3D9C;
                        9'd144 : DAC_code = 16'h3C2C;
                        9'd145 : DAC_code = 16'h3AB8;
                        9'd146 : DAC_code = 16'h3940;
                        9'd147 : DAC_code = 16'h37C0;
                        9'd148 : DAC_code = 16'h3640;
                        9'd149 : DAC_code = 16'h34B8;
                        9'd150 : DAC_code = 16'h3330;
                        9'd151 : DAC_code = 16'h31A0;
                        9'd152 : DAC_code = 16'h3010;
                        9'd153 : DAC_code = 16'h2E78;
                        9'd154 : DAC_code = 16'h2CE0;
                        9'd155 : DAC_code = 16'h2B44;
                        9'd156 : DAC_code = 16'h29A4;
                        9'd157 : DAC_code = 16'h2800;
                        9'd158 : DAC_code = 16'h2658;
                        9'd159 : DAC_code = 16'h24B0;
                        9'd160 : DAC_code = 16'h2304;
                        9'd161 : DAC_code = 16'h2154;
                        9'd162 : DAC_code = 16'h1FA0;
                        9'd163 : DAC_code = 16'h1DEC;
                        9'd164 : DAC_code = 16'h1C38;
                        9'd165 : DAC_code = 16'h1A7C;
                        9'd166 : DAC_code = 16'h18C4;
                        9'd167 : DAC_code = 16'h1708;
                        9'd168 : DAC_code = 16'h1548;
                        9'd169 : DAC_code = 16'h1388;
                        9'd170 : DAC_code = 16'h11C4;
                        9'd171 : DAC_code = 16'h1004;
                        9'd172 : DAC_code = 16'h0E3C;
                        9'd173 : DAC_code = 16'h0C78;
                        9'd174 : DAC_code = 16'h0AB0;
                        9'd175 : DAC_code = 16'h08EC;
                        9'd176 : DAC_code = 16'h0724;
                        9'd177 : DAC_code = 16'h0558;
                        9'd178 : DAC_code = 16'h0390;
                        9'd179 : DAC_code = 16'h01C8;
                        9'd180 : DAC_code = 16'h0000;
                        9'd181 : DAC_code = 16'hFE37;
                        9'd182 : DAC_code = 16'hFC6F;
                        9'd183 : DAC_code = 16'hFAA7;
                        9'd184 : DAC_code = 16'hF8DB;
                        9'd185 : DAC_code = 16'hF713;
                        9'd186 : DAC_code = 16'hF54F;
                        9'd187 : DAC_code = 16'hF387;
                        9'd188 : DAC_code = 16'hF1C3;
                        9'd189 : DAC_code = 16'hEFFB;
                        9'd190 : DAC_code = 16'hEE3B;
                        9'd191 : DAC_code = 16'hEC77;
                        9'd192 : DAC_code = 16'hEAB7;
                        9'd193 : DAC_code = 16'hE8F7;
                        9'd194 : DAC_code = 16'hE73B;
                        9'd195 : DAC_code = 16'hE583;
                        9'd196 : DAC_code = 16'hE3C7;
                        9'd197 : DAC_code = 16'hE213;
                        9'd198 : DAC_code = 16'hE05F;
                        9'd199 : DAC_code = 16'hDEAB;
                        9'd200 : DAC_code = 16'hDCFB;
                        9'd201 : DAC_code = 16'hDB4F;
                        9'd202 : DAC_code = 16'hD9A7;
                        9'd203 : DAC_code = 16'hD7FF;
                        9'd204 : DAC_code = 16'hD65B;
                        9'd205 : DAC_code = 16'hD4BB;
                        9'd206 : DAC_code = 16'hD31F;
                        9'd207 : DAC_code = 16'hD187;
                        9'd208 : DAC_code = 16'hCFEF;
                        9'd209 : DAC_code = 16'hCE5F;
                        9'd210 : DAC_code = 16'hCCCF;
                        9'd211 : DAC_code = 16'hCB47;
                        9'd212 : DAC_code = 16'hC9BF;
                        9'd213 : DAC_code = 16'hC83F;
                        9'd214 : DAC_code = 16'hC6BF;
                        9'd215 : DAC_code = 16'hC547;
                        9'd216 : DAC_code = 16'hC3D3;
                        9'd217 : DAC_code = 16'hC263;
                        9'd218 : DAC_code = 16'hC0F7;
                        9'd219 : DAC_code = 16'hBF93;
                        9'd220 : DAC_code = 16'hBE2F;
                        9'd221 : DAC_code = 16'hBCD3;
                        9'd222 : DAC_code = 16'hBB7F;
                        9'd223 : DAC_code = 16'hBA2F;
                        9'd224 : DAC_code = 16'hB8E3;
                        9'd225 : DAC_code = 16'hB79B;
                        9'd226 : DAC_code = 16'hB65B;
                        9'd227 : DAC_code = 16'hB51F;
                        9'd228 : DAC_code = 16'hB3EB;
                        9'd229 : DAC_code = 16'hB2BB;
                        9'd230 : DAC_code = 16'hB193;
                        9'd231 : DAC_code = 16'hB06F;
                        9'd232 : DAC_code = 16'hAF53;
                        9'd233 : DAC_code = 16'hAE3B;
                        9'd234 : DAC_code = 16'hAD2B;
                        9'd235 : DAC_code = 16'hAC23;
                        9'd236 : DAC_code = 16'hAB1F;
                        9'd237 : DAC_code = 16'hAA23;
                        9'd238 : DAC_code = 16'hA92B;
                        9'd239 : DAC_code = 16'hA83F;
                        9'd240 : DAC_code = 16'hA757;
                        9'd241 : DAC_code = 16'hA673;
                        9'd242 : DAC_code = 16'hA59B;
                        9'd243 : DAC_code = 16'hA4C7;
                        9'd244 : DAC_code = 16'hA3FB;
                        9'd245 : DAC_code = 16'hA337;
                        9'd246 : DAC_code = 16'hA277;
                        9'd247 : DAC_code = 16'hA1C3;
                        9'd248 : DAC_code = 16'hA113;
                        9'd249 : DAC_code = 16'hA06B;
                        9'd250 : DAC_code = 16'h9FCB;
                        9'd251 : DAC_code = 16'h9F33;
                        9'd252 : DAC_code = 16'h9E9F;
                        9'd253 : DAC_code = 16'h9E17;
                        9'd254 : DAC_code = 16'h9D97;
                        9'd255 : DAC_code = 16'h9D1B;
                        9'd256 : DAC_code = 16'h9CA7;
                        9'd257 : DAC_code = 16'h9C3F;
                        9'd258 : DAC_code = 16'h9BDB;
                        9'd259 : DAC_code = 16'h9B7F;
                        9'd260 : DAC_code = 16'h9B2B;
                        9'd261 : DAC_code = 16'h9ADF;
                        9'd262 : DAC_code = 16'h9A9B;
                        9'd263 : DAC_code = 16'h9A63;
                        9'd264 : DAC_code = 16'h9A2F;
                        9'd265 : DAC_code = 16'h9A03;
                        9'd266 : DAC_code = 16'h99DF;
                        9'd267 : DAC_code = 16'h99C3;
                        9'd268 : DAC_code = 16'h99AF;
                        9'd269 : DAC_code = 16'h99A3;
                        9'd270 : DAC_code = 16'h999F;
                        9'd271 : DAC_code = 16'h99A3;
                        9'd272 : DAC_code = 16'h99AF;
                        9'd273 : DAC_code = 16'h99C3;
                        9'd274 : DAC_code = 16'h99DF;
                        9'd275 : DAC_code = 16'h9A03;
                        9'd276 : DAC_code = 16'h9A2F;
                        9'd277 : DAC_code = 16'h9A63;
                        9'd278 : DAC_code = 16'h9A9B;
                        9'd279 : DAC_code = 16'h9ADF;
                        9'd280 : DAC_code = 16'h9B2B;
                        9'd281 : DAC_code = 16'h9B7F;
                        9'd282 : DAC_code = 16'h9BDB;
                        9'd283 : DAC_code = 16'h9C3F;
                        9'd284 : DAC_code = 16'h9CA7;
                        9'd285 : DAC_code = 16'h9D1B;
                        9'd286 : DAC_code = 16'h9D97;
                        9'd287 : DAC_code = 16'h9E17;
                        9'd288 : DAC_code = 16'h9E9F;
                        9'd289 : DAC_code = 16'h9F33;
                        9'd290 : DAC_code = 16'h9FCB;
                        9'd291 : DAC_code = 16'hA06B;
                        9'd292 : DAC_code = 16'hA113;
                        9'd293 : DAC_code = 16'hA1C3;
                        9'd294 : DAC_code = 16'hA277;
                        9'd295 : DAC_code = 16'hA337;
                        9'd296 : DAC_code = 16'hA3FB;
                        9'd297 : DAC_code = 16'hA4C7;
                        9'd298 : DAC_code = 16'hA59B;
                        9'd299 : DAC_code = 16'hA673;
                        9'd300 : DAC_code = 16'hA757;
                        9'd301 : DAC_code = 16'hA83F;
                        9'd302 : DAC_code = 16'hA92B;
                        9'd303 : DAC_code = 16'hAA23;
                        9'd304 : DAC_code = 16'hAB1F;
                        9'd305 : DAC_code = 16'hAC23;
                        9'd306 : DAC_code = 16'hAD2B;
                        9'd307 : DAC_code = 16'hAE3B;
                        9'd308 : DAC_code = 16'hAF53;
                        9'd309 : DAC_code = 16'hB06F;
                        9'd310 : DAC_code = 16'hB193;
                        9'd311 : DAC_code = 16'hB2BB;
                        9'd312 : DAC_code = 16'hB3EB;
                        9'd313 : DAC_code = 16'hB51F;
                        9'd314 : DAC_code = 16'hB65B;
                        9'd315 : DAC_code = 16'hB79B;
                        9'd316 : DAC_code = 16'hB8E3;
                        9'd317 : DAC_code = 16'hBA2F;
                        9'd318 : DAC_code = 16'hBB7F;
                        9'd319 : DAC_code = 16'hBCD3;
                        9'd320 : DAC_code = 16'hBE2F;
                        9'd321 : DAC_code = 16'hBF93;
                        9'd322 : DAC_code = 16'hC0F7;
                        9'd323 : DAC_code = 16'hC263;
                        9'd324 : DAC_code = 16'hC3D3;
                        9'd325 : DAC_code = 16'hC547;
                        9'd326 : DAC_code = 16'hC6BF;
                        9'd327 : DAC_code = 16'hC83F;
                        9'd328 : DAC_code = 16'hC9BF;
                        9'd329 : DAC_code = 16'hCB47;
                        9'd330 : DAC_code = 16'hCCCF;
                        9'd331 : DAC_code = 16'hCE5F;
                        9'd332 : DAC_code = 16'hCFEF;
                        9'd333 : DAC_code = 16'hD187;
                        9'd334 : DAC_code = 16'hD31F;
                        9'd335 : DAC_code = 16'hD4BB;
                        9'd336 : DAC_code = 16'hD65B;
                        9'd337 : DAC_code = 16'hD7FF;
                        9'd338 : DAC_code = 16'hD9A7;
                        9'd339 : DAC_code = 16'hDB4F;
                        9'd340 : DAC_code = 16'hDCFB;
                        9'd341 : DAC_code = 16'hDEAB;
                        9'd342 : DAC_code = 16'hE05F;
                        9'd343 : DAC_code = 16'hE213;
                        9'd344 : DAC_code = 16'hE3C7;
                        9'd345 : DAC_code = 16'hE583;
                        9'd346 : DAC_code = 16'hE73B;
                        9'd347 : DAC_code = 16'hE8F7;
                        9'd348 : DAC_code = 16'hEAB7;
                        9'd349 : DAC_code = 16'hEC77;
                        9'd350 : DAC_code = 16'hEE3B;
                        9'd351 : DAC_code = 16'hEFFB;
                        9'd352 : DAC_code = 16'hF1C3;
                        9'd353 : DAC_code = 16'hF387;
                        9'd354 : DAC_code = 16'hF54F;
                        9'd355 : DAC_code = 16'hF713;
                        9'd356 : DAC_code = 16'hF8DB;
                        9'd357 : DAC_code = 16'hFAA7;
                        9'd358 : DAC_code = 16'hFC6F;
                        9'd359 : DAC_code = 16'hFE37;
                        9'd360 : DAC_code = 16'h0000;
                        default : DAC_code = 16'h0000;
                    endcase
                end
        end
    
endmodule

由于 sin LUT 的 case 语句中的选择值是正弦波单位圆的每个 360 度值,因此计数器从 0 到 360 递增的速度最终设置了输出正弦波的频率。

sin LUT 上方的逻辑中需要三个计数器:一个计数器用于对 sin LUT 选择从 0 到 359 的度数进行计数,一个计数器用于计算频率 0 的增量之间的延迟,以及一个计数器用于计算频率 0 的增量之间的延迟。频率 1.

always @ (posedge clk)
    begin 
        if (rst == 1'b0)
            begin
                degree_cntr <= 9'd0;
                degree_cntr_done <= 1'b0; 
            end
        else if (incr_degree_cntr == 1'b1)
            begin
                if (degree_cntr < unit_circle_deg)
                    begin
                        degree_cntr <= degree_cntr + 1;
                        degree_cntr_done <= 1'b0;
                    end
                else
                    begin
                        degree_cntr <= 9'd0;
                        degree_cntr_done <= 1'b1;
                    end
            end
        else
            begin
                degree_cntr <= degree_cntr;
            end
    end 

always @ (posedge clk)
    begin 
        if (rst == 1'b0)
            begin
                incr_degree_cntr = 1'b0;
                period_cntr <= 3'd0;
            end
        else
            begin
                if (period_cntr == period)
                    begin
                        incr_degree_cntr = 1'b1;
                        period_cntr <= 3'd0;
                    end
                else
                    begin 
                        incr_degree_cntr = 1'b0;
                        period_cntr <= period_cntr + 1;
                    end 
            end
    end 

always @ (posedge clk)
    begin 
        if (rst == 1'b0)
            begin
                tdata_sel_cntr <= 5'd0;
            end 
        else 
            begin
                if (degree_cntr_done == 1'b1)
                    begin
                        tdata_sel_cntr <= tdata_sel_cntr + 1;
                    end
                else
                    begin
                        tdata_sel_cntr <= tdata_sel_cntr;
                    end
            end 
    end

还需要一个并行到串行转换器,通过 MM2S 传输从 DDR 发出的数据包的 AXI Stream 接口获取 32 位数据,并将其串行化,可以通过 MM2S 传输输出该位各自频率的一个周期。 DAC一次。这就是 2-FSK 的局限性暴露出来的地方:一次只能传输一位。

always @ (tdata_sel_cntr)
    begin 
        case (tdata_sel_cntr) 
            32'd0   : 
                begin
                    current_tx_bit <= tdata[0];
                    tx_pkt_done <= 1'b0;
                end 
            32'd1   : 
                begin
                     current_tx_bit <= tdata[1];
                     tx_pkt_done <= 1'b0;
                end 
            32'd2   : 
                begin
                     current_tx_bit <= tdata[2];
                     tx_pkt_done <= 1'b0;
                end 
            32'd3   : 
                begin
                     current_tx_bit <= tdata[3];
                     tx_pkt_done <= 1'b0;
                end 
            32'd4   : 
                begin
                     current_tx_bit <= tdata[4];
                     tx_pkt_done <= 1'b0;
                end 
            32'd5   : 
                begin
                     current_tx_bit <= tdata[5];
                     tx_pkt_done <= 1'b0;
                end 
            32'd6   : 
                begin
                     current_tx_bit <= tdata[6];
                     tx_pkt_done <= 1'b0;
                end 
            32'd7   : 
                begin
                     current_tx_bit <= tdata[7];
                     tx_pkt_done <= 1'b0;
                end 
            32'd8   : 
                begin
                     current_tx_bit <= tdata[8];
                     tx_pkt_done <= 1'b0;
                end 
            32'd9   : 
                begin
                     current_tx_bit <= tdata[9];
                     tx_pkt_done <= 1'b0;
                end 
            32'd10  : 
                begin
                     current_tx_bit <= tdata[10];
                     tx_pkt_done <= 1'b0;
                end 
            32'd11  : 
                begin
                     current_tx_bit <= tdata[11];
                     tx_pkt_done <= 1'b0;
                end 
            32'd12  : 
                begin
                     current_tx_bit <= tdata[12];
                     tx_pkt_done <= 1'b0;
                end 
            32'd13  : 
                begin
                     current_tx_bit <= tdata[13];
                     tx_pkt_done <= 1'b0;
                end 
            32'd14  : 
                begin
                     current_tx_bit <= tdata[14];
                     tx_pkt_done <= 1'b0;
                end 
            32'd15  : 
                begin
                     current_tx_bit <= tdata[15];
                     tx_pkt_done <= 1'b0;
                end 
            32'd16  : 
                begin
                     current_tx_bit <= tdata[16];
                     tx_pkt_done <= 1'b0;
                end 
            32'd17  : 
                begin
                     current_tx_bit <= tdata[17];
                     tx_pkt_done <= 1'b0;
                end 
            32'd18  : 
                begin
                     current_tx_bit <= tdata[18];
                     tx_pkt_done <= 1'b0;
                end 
            32'd19  : 
                begin
                     current_tx_bit <= tdata[19];
                     tx_pkt_done <= 1'b0;
                end 
            32'd20  : 
                begin
                     current_tx_bit <= tdata[20];
                     tx_pkt_done <= 1'b0;
                end 
            32'd21  : 
                begin
                     current_tx_bit <= tdata[21];
                     tx_pkt_done <= 1'b0;
                end 
            32'd22  : 
                begin
                     current_tx_bit <= tdata[22];
                     tx_pkt_done <= 1'b0;
                end 
            32'd23  : 
                begin
                     current_tx_bit <= tdata[23];
                     tx_pkt_done <= 1'b0;
                end 
            32'd24  : 
                begin
                     current_tx_bit <= tdata[24];
                     tx_pkt_done <= 1'b0;
                end 
            32'd25  : 
                begin
                     current_tx_bit <= tdata[25];
                     tx_pkt_done <= 1'b0;
                end 
            32'd26  : 
                begin
                     current_tx_bit <= tdata[26];
                     tx_pkt_done <= 1'b0;
                end 
            32'd27  : 
                begin
                     current_tx_bit <= tdata[27];
                     tx_pkt_done <= 1'b0;
                end 
            32'd28  : 
                begin
                     current_tx_bit <= tdata[28];
                     tx_pkt_done <= 1'b0;
                end 
            32'd29  : 
                begin
                     current_tx_bit <= tdata[29];
                     tx_pkt_done <= 1'b0;
                end 
            32'd30  : 
                begin
                     current_tx_bit <= tdata[30];
                     tx_pkt_done <= 1'b0;
                end 
            32'd31  : 
                begin
                     current_tx_bit <= tdata[31];
                     tx_pkt_done <= 1'b1;
                end 
            default : 
                begin
                    current_tx_bit <= 1'b0;
                    tx_pkt_done <= 1'b0;
                end
        endcase 
    end

always @ (posedge clk)
    begin 
        if (current_tx_bit == 1'b1)
            period <= T1_period;
        else
            period <= T0_period;
    end

最后,AXI Stream 接口只需要围绕上述逻辑,使用从接口接收来自 AXIS FIFO 的数据,并使用主接口将数据输出到 DAC 控制器。

`timescale 1ns / 1ps

module sin_axis(
    input clk,
    input reset,
    input [31:0] s_axis_tdata,
    input [3:0] s_axis_tkeep,
    input s_axis_tlast,
    output reg s_axis_tready,
    input s_axis_tvalid,
    output reg [31:0] m_axis_tdata,
    output reg [3:0] m_axis_tkeep,
    output reg m_axis_tlast,
    input m_axis_tready,
    output reg m_axis_tvalid, 
    output [2:0] state_reg
    );
    
    sin_sm sin_sm_i(
        .clk(clk),
        .rst(reset),
        .tdata_slave(tdata_slave),
        .tdata_master(tdata_master),
        .tx_pkt_done(tx_pkt_done)
    );
    
    
    reg tlast;
    reg [2:0] state_reg;
    
    wire tx_pkt_done;
    wire [31:0] tdata_master;
    reg [31:0] tdata_slave;
    
    
    parameter init               = 3'd0;
    parameter SetSlaveTready     = 3'd1;
    parameter CheckSlaveTvalid   = 3'd2;
    parameter ProcessTdata       = 3'd3;
    parameter CheckTlast         = 3'd4;
    
    always @ (posedge clk)
        begin
   // Default outputs            
   m_axis_tvalid <= 1'b0;
            
            if (reset == 1'b0)
                begin
                    tlast <= 1'b0;
                    tdata_slave[31:0] <= 32'd0;
                    s_axis_tready <= 1'b0;
                    m_axis_tdata[31:0] <= 32'd0;
                    m_axis_tkeep <= 4'h0;
                    m_axis_tlast <= 1'b0;
                    state_reg <= init;
                end
            else
                begin
                
                    case(state_reg) 
                        init : // 0 
                            begin
                                tlast <= 1'b0;
                                tdata_slave[31:0] <= 32'd0;
                                s_axis_tready <= 1'b0;
                                m_axis_tdata[31:0] <= 32'd0;
                                m_axis_tkeep <= 4'h0;
                                m_axis_tlast <= 1'b0;
                                state_reg <= SetSlaveTready;
                            end 
                            
                        SetSlaveTready : // 1
                            begin
                                s_axis_tready <= 1'b1;
                                state_reg <= CheckSlaveTvalid;
                            end 
                            
                        CheckSlaveTvalid : // 2
                            begin
                                if (s_axis_tkeep == 4'hf && s_axis_tvalid == 1'b1)
                                    begin
                                        s_axis_tready <= 1'b0;
                                        tlast <= s_axis_tlast;
                                        tdata_slave[31:0] <= s_axis_tdata[31:0];
                                        state_reg <= ProcessTdata;
                                    end
                                else
                                    begin 
                                        tdata_slave[31:0] <= 32'd0;
                                        state_reg <= CheckSlaveTvalid;
                                    end 
                            end
                            
                        ProcessTdata : // 3
                            begin 
                                m_axis_tkeep <= 4'hf;
                                m_axis_tlast <= tlast;
                                m_axis_tvalid <= 1'b1;
                                m_axis_tdata[31:0] <= tdata_master[31:0];
                                
                                if (m_axis_tready == 1'b1 && tx_pkt_done == 1'b1)
                                    begin 
                                        state_reg <= CheckTlast;
                                    end 
                                else
                                    begin 
                                        state_reg <= ProcessTdata;
                                    end 
                            end
                            
                        CheckTlast : // 4
                            begin 
                                if (m_axis_tlast == 1'b1)
                                    begin    
                                        state_reg <= init;
                                    end
                                else if (m_axis_tready == 1'b1)
                                    begin
                                        state_reg <= SetSlaveTready;
                                    end
                                else 
                                    begin 
                                        state_reg <= CheckTlast;
                                    end 
                            end 
                            
                    endcase 
                end
        end
endmodule

完整的代码见最后。

Vitis 软件

由于生成正弦波的所有逻辑都是在 Verilog 的 HDL 中处理的,因此 C 代码中唯一剩下的就是控制 MM2S 传输(源文件也附在下面):

int main()
{
    init_platform();

    XAxiDma_Config *CfgPtr; //DMA configuration pointer
    int Status, Index;
    u8 *TxBufferPtr;

    TxBufferPtr = (u8 *)TX_BUFFER_BASE;

    for(Index = 0; Index < MAX_PKT_LEN; Index ++){
        TxBufferPtr[Index] = 0x00;
    }

    CfgPtr = XAxiDma_LookupConfig(DMA_DEV_ID);
    if (!CfgPtr) {
        xil_printf("No config found for %d\r\n", DMA_DEV_ID);
        return XST_FAILURE;
    }

    Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
    if (Status != XST_SUCCESS) {
        xil_printf("Initialization failed %d\r\n", Status);
        return XST_FAILURE;
    }

    XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE);

    TxBufferPtr[0] = 0xef;

    Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);
    XAxiDma_Reset(&AxiDma);

    Status = XAxiDma_MM2Stransfer(&AxiDma,(UINTPTR) TxBufferPtr, MAX_PKT_LEN);
    if (Status != XST_SUCCESS){
        xil_printf("XAXIDMA_DMA_TO_DEVICE transfer failed...\r\n");
 return XST_FAILURE;
    }

    cleanup_platform();
    return 0;
}
ZYNQ上的简单 FSK 基带发射器,fpga开发

测试设备

为了验证模拟输出,将其通道 1 连接到示波器通道 1,并在主机 PC 上启动 WaveForms 来查看它。

然后,在 Vitis 中启动 C 应用程序的调试,并在 MM2S 传输开始之前设置了断点:

ZYNQ上的简单 FSK 基带发射器,fpga开发

由于将DAC设置为低增益模式,因此峰值输出值约为 1.0v。在 WaveForms 的 Scope 选项卡中,为超过 100mV 的上升沿设置电平触发器,然后单击Run 。

得到 1 和 0 两个不同频率值的清晰输出:

ZYNQ上的简单 FSK 基带发射器,fpga开发

正如我上面提到的,这只是符号映射器的一个非常简化的版本,目的是为了以更实用、更实际的方式克服 SDR 设计入门的困难。两个不同频率的周期计数器是查看输出结果的良好起点。

代码

https://github.com/Digilent/vivado-boards

https://github.com/suisuisi/FPGATechnologyGroup/tree/main/simple_2_fsk文章来源地址https://www.toymoban.com/news/detail-696991.html

到了这里,关于ZYNQ上的简单 FSK 基带发射器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 基于FPGA的OFDM基带发射机的设计与实现

    文章目录 前言 一、OFDM描述 二、本系统的实现参照 1.IEEE 802.11a协议主要参数 2.不同调制方式与速率  3. IFFT映射关系 4. IEEE 802.11a物理层规范 5. PPDU帧格式 三、设计与实现 1.扰码 2.卷积编码与删余 3.数据交织 4.符号调制 5.导频插入 6.IFFT变换  7.循环前缀加窗 8.训练序列生成 9.发

    2024年02月06日
    浏览(47)
  • FSK解调技术的FPGA实现

    本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 一、FSK信号的解调原理 FSK信号的解调也有非相干和相干两种,FSK信号可以看作是用两个频率源交替传输得到的,所以FSK的接收机由两个并联的ASK接收机组成。 (1)相干解调 相干解

    2024年02月09日
    浏览(56)
  • 基于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)
  • 基于FPGA的2ASK、2FSK、2PSK的调制解调

    本次设计是基于FPGA的调制解调器的设计。涉及到2ASK、2FSK、2PSK的调制解调,利用Verilog HDL进行底层设计,顶层为了直观用的原理图方法。这里没有用modelsim仿真,直接上板子用的signalTap II 观测的波型 该总体框图包括分频器、载波生成模块、m序列生成模块、调制解调模块和选

    2024年02月14日
    浏览(44)
  • STM32-2FSK解调 一种简单的C语言包络提取方法

    效果如图,其中方波为基带信号,原始信号为2FSK经过一路带通滤波器后的理想输出结果。 程序对原始信号的绝对值信号进行包络提取。可以看到提取出的包络信号与方波信号相差无几。  代码如下: 可以看出阈值的设置相当重要,建议对输入的信号求平均值,以平均值作为

    2024年02月12日
    浏览(41)
  • 【TES641】基于VU13P FPGA的4路FMC接口基带信号处理平台

    板卡概述 TES641是一款基于Virtex UltraScale+系列FPGA的高性能4路FMC接口基带信号处理平台,该平台采用1片Xilinx的Virtex UltraScale+系列FPGA XCVU13P作为信号实时处理单元,该板卡具有4个FMC子卡接口(其中有2个为FMC+接口),各个节点之间通过高速串行总线进行互联,该FPGA支持最大32Gb

    2024年02月19日
    浏览(39)
  • Unity 实现简单的发射子弹功能

    前言:对于射击类游戏,相信大家并不陌生。那么想要实现这一功能,我们通常会使用两种方法: 1.射线追踪。  2.子弹实例化。 今天,我们就通过第二种方式去实现发射的功能。 一、首先,我们准备好一把枪的模型,将其放到场景中,调整好位置。  二、 我们在枪口前面

    2024年02月11日
    浏览(97)
  • Zynq和FPGA区别——快速认识Zynq开发

    ZYNQ包含了2个部分,双核的ARM和FPGA。根据Xilinx提供的手册,用ARM实现的模块被称为PS,而用FPGA实现的模块被称为PL。简单的说FPA更偏向于逻辑,不跑系统。 ZYNQ内部包含PS和PL两部分,ZYNQ开发有一下四种方式: ZYNQ是赛灵思公司(Xilinx)推出的新一代全可编程片上系统,它将处

    2024年02月16日
    浏览(55)
  • ZYNQ之FPGA学习----Vivado功能仿真

    阅读本文需先学习: FPGA学习----Vivado软件使用 典型的FPGA设计流程,如图所示: 图片来自《领航者ZYNQ之FPGA开发指南》 Vivado 设计套件内部 集成了仿真器 Vivado Simulator ,能够在设计流程的不同阶段运行设计的功能仿真和时序仿真,结果可以在 Vivado IDE 集成的波形查看器中显示。

    2023年04月18日
    浏览(51)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包