ZYNQ上的简单 FSK 基带发射器

news2024/9/19 10:44:25

e98c9b0b6c14bbaffd3d561402760dcb.png

绪论

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

69aab3dc24e3805f83ee23c1b154e767.png

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

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

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

数字调制

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

ae0d6b10412307dab564095b94bd8138.png

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

Vivado 中的逻辑设计

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

d7cf6459b8847f5bb7e23230e5c96a88.png

代码如下:

`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;
}
1840c4e4a752672229b04809c58d60c7.png

测试设备

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

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

79ee256334f6ad022f0b9868356b23af.png

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

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

adb1d214826706c50685e0612e619b7f.png

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

代码

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

https://github.com/suisuisi/FPGATechnologyGroup/tree/main/simple_2_fsk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/977887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MSYS2 介绍、下载与安装、Pacman常用命令

一、MSYS2 介绍 MSYS2 官网&#xff1a;MSYS2 MSYS2&#xff08;Minimal SYStem 2&#xff09;是一个集成了大量的GNU工具链、工具和库的开源软件包集合。它提供了一个类似于Linux的shell环境&#xff0c;可以在Windows系统中编译和运行许多Linux应用程序和工具。 MSYS2基于…

GPT转换工具:轻松将MBR转换为GPT磁盘

为什么需要将MBR转换为GPT&#xff1f; 众所周知&#xff0c;Windows 11已经发布很长时间了。在此期间&#xff0c;许多老用户已经从Windows 10升级到Windows 11。但有些用户仍在运行Windows 10。对于那些想要升级到Win 11的用户来说&#xff0c;他们可能不确定Win 11应该使…

【初阶C语言】操作符1--对二进制的操作

前言&#xff1a;本节内容介绍的操作符&#xff0c;操作的对象是二进制位。所以前面先介绍整数的二进制位 一、二进制位介绍 1.二进制介绍 &#xff08;1&#xff09;整数的二进制表示形式有三种&#xff1a;原码、反码和补码。 &#xff08;2&#xff09;原码、反码和补码的…

TPS-MIS-DSS

TPS-MIS-DSS 业务处理系统TPS管理信息系统MIS决策支持系统DSS 业务处理系统TPS 最初级的信息系统&#xff0c;管理具体的事务 TPS是其他类型信息系统的信息产生器 处于企业系统的边界 管理信息系统MIS 对企业整体的信息进行处理 使用信息进行预测&#xff0c;控制&#xff0c;计…

一些重要的硬件概念总结

电路噪声 区分噪声和干扰 对于电子线路中所称的噪声&#xff0c;可以概括地认为&#xff0c;它是对目的信号以外所有信号的一个总称。 最初人们把造成收音机这类音响设备所发出的那些电子信号称为噪声。但是&#xff0c;一些非目的的电子信号对电子线路造成的后果并非都和声音有…

【LeetCode每日一题合集】2023.8.28-2023.9.3(到家的最少跳跃次数)

文章目录 57. 插入区间823. 带因子的二叉树解法——递推 1654. 到家的最少跳跃次数(BFS&#xff0c;&#x1f6b9;最远距离上界的证明)1761. 一个图中连通三元组的最小度数2240. 买钢笔和铅笔的方案数解法1——完全背包解法2——枚举买了几支钢笔&#xff08;推荐解法&#xff…

华为云云服务器评测|使用云耀云服务器L实例部署Portainer工具

华为云云服务器评测&#xff5c;使用云耀云服务器L实例部署Portainer工具 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点1.3 云耀云服务器L实例使用场景 二、本次实践介绍2.1 本次实践简介2.2 Portainer简介 三、购买云耀云服务器L实例3.1 登录…

java八股文面试[数据库]——主键的类型自增还是UUID

auto_increment的优点&#xff1a; 字段长度较uuid小很多&#xff0c;可以是bigint甚至是int类型&#xff0c;这对检索的性能会有所影响。 在写的方面&#xff0c;因为是自增的&#xff0c;所以主键是趋势自增的&#xff0c;也就是说新增的数据永远在后面&#xff0c;这点对于…

QT—基于http协议的网络文件下载

1.常用到的类 QNetworkAccessManager类用于协调网络操作&#xff0c;负责发送网络请求&#xff0c;创建网络响应 QNetworkReply类表示网络请求的响应。在QNetworkAccessManager发送一个网络请求后创建一个网络响应。它提供了以下信号&#xff1a; finished()&#xff1a;完成…

Rider 中C#单元测试

使用NUnit.Framework这个包&#xff0c;没有的话可以用nuget去搜索下载。简单的进行单元测试&#xff0c;想要单元测试好像还给需要static函数&#xff0c;慢慢学学C# using System; using NUnit.Framework;namespace client {public class test{[Test]public static void test…

(二十二)大数据实战——Flume数据采集之故障转移案例实战

前言 本节内容我们完成Flume数据采集的故障转移案例&#xff0c;使用三台服务器&#xff0c;一台服务器负责采集nc数据&#xff0c;通过使用failover模式的Sink处理器完成监控数据的故障转移&#xff0c;使用Avro的方式完成flume之间采集数据的传输。整体架构如下&#xff1a;…

纯css实现奥运五环、3D平移与旋转

文章目录 前言效果图htmlcss 前言 1、不是真正的五环&#xff0c;因为通过形变得来。 2、不同电脑显示器的像素不同&#xff0c;显现的效果不同。 3、不推荐使用此方法。 4、主要通过旋转加平移的方式实现。 效果图 html <div class"olympic_rings"><span …

pt23django教程

Django的框架设计模式 MVC 设计模式 MVC 代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。作用: **降低模块间的耦合度**(解耦) - M 模型层(Model), 主要用于对数据库层的封装 - V 视图层(View), 用于向用户展示结果 - C 控制(Controller &#x…

达梦数据库和mysql数据库获取两个坐标之间的距离

91、达梦数据库和mysql数据库获取两个坐标之间的距离 参考&#xff1a;参考 mysql 数据库&#xff1a; select st_distance_sphere(POINT(经度1,纬度1), POINT(经度2,纬度2))达梦数据库没有内置函数&#xff0c;需要自己手动创建函数 CREATE OR REPLACE FUNCTION "模式…

自然语言处理 微调ChatGLM-6B大模型

自然语言处理 微调ChatGLM-6B大模型 1、GLM设计原理2、大模型微调原理1、P-tuning v2方案2、LORA方案 1、GLM设计原理 bert的主要任务是随机的去除掉某个单词&#xff0c;使用上下文将其预测出来&#xff08;相当于完形填空任务&#xff09;&#xff1b; GPT的主要任务是根据前…

【精品】NLP自然语言处理学习路线(知识体系)

当前&#xff0c;大规模预训练语言模型的强大对话问答、文本生成能力&#xff0c;将自然语言处理&#xff08;NLP&#xff09;的研究和应用推向了新一轮的热潮。NLP是计算机科学、人工智能和语言学等学科交叉的前沿领域。NLP的应用和研究范围非常的广泛&#xff0c;个人是没有找…

react-grapesjs——开源代码学习与修改(初出茅庐)

文章目录 ⭐前言⭐grapesjs初始化过程&#x1f496; 渲染大体流程&#x1f496; Editor对象 创建&#x1f496; EditorModel 对象创建&#x1f496; load modules 加载定义的目录模块Module&#x1f496; StyleManager渲染过程 ⭐修改grapesjs配置项⭐总结⭐ 如何修改开源代码⭐…

英诺森 “供应链智能数据平台”荣获“科技进步奖”

近日&#xff0c;2023年中国物流与采购联合会科学技术奖正式公布&#xff0c;该奖项经国家科技部批准&#xff0c;在国家科学技术奖励工作办公室登记备案&#xff0c;是我国物流行业最具影响力的奖项之一。 英诺森联合客户申报的科技项目“英诺森供应链智能数据平台”&#xf…

如何查找GNU C语言参考手册

快捷通道 标准C/C参考手册 GNU C参考手册HTML版 GNU C参考手册PDF版本 HTML版本部分目录预览 从GNU官网找那个GNU C参考手册 访问gnu.org 点击软件 下滑找到gnu-c-manual或者在这个页面Ctrl-f搜索"manual" 点进去即可看到HTML版本和PDF版本

slog实战:文件日志、轮转与kafka集成

《slog正式版来了&#xff1a;Go日志记录新选择&#xff01;[1]》一文发布后&#xff0c;收到了很多读者的反馈&#xff0c;意见集中在以下几点&#xff1a; 基于slog如何将日志写入文件slog是否支持log轮转(rotation)&#xff0c;如果slog不支持&#xff0c;是否有好的log轮转…