ZYNQ上的简单 FSK 基带发射器

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 / 1psmodule sin_lut(input clk,input rst,input [8:0] sel,output [15:0] DAC_code);reg [15:0] DAC_code;always @ (posedge clk)beginif (rst == 1'b0)begin endelse begincase (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;endcaseendendendmodule

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

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

always @ (posedge clk)begin if (rst == 1'b0)begindegree_cntr <= 9'd0;degree_cntr_done <= 1'b0; endelse if (incr_degree_cntr == 1'b1)beginif (degree_cntr < unit_circle_deg)begindegree_cntr <= degree_cntr + 1;degree_cntr_done <= 1'b0;endelsebegindegree_cntr <= 9'd0;degree_cntr_done <= 1'b1;endendelsebegindegree_cntr <= degree_cntr;endend always @ (posedge clk)begin if (rst == 1'b0)beginincr_degree_cntr = 1'b0;period_cntr <= 3'd0;endelsebeginif (period_cntr == period)beginincr_degree_cntr = 1'b1;period_cntr <= 3'd0;endelsebegin incr_degree_cntr = 1'b0;period_cntr <= period_cntr + 1;end endend always @ (posedge clk)begin if (rst == 1'b0)begintdata_sel_cntr <= 5'd0;end else beginif (degree_cntr_done == 1'b1)begintdata_sel_cntr <= tdata_sel_cntr + 1;endelsebegintdata_sel_cntr <= tdata_sel_cntr;endend end

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

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

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

`timescale 1ns / 1psmodule 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)begintlast <= 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;endelsebegincase(state_reg) init : // 0 begintlast <= 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 : // 1begins_axis_tready <= 1'b1;state_reg <= CheckSlaveTvalid;end CheckSlaveTvalid : // 2beginif (s_axis_tkeep == 4'hf && s_axis_tvalid == 1'b1)begins_axis_tready <= 1'b0;tlast <= s_axis_tlast;tdata_slave[31:0] <= s_axis_tdata[31:0];state_reg <= ProcessTdata;endelsebegin tdata_slave[31:0] <= 32'd0;state_reg <= CheckSlaveTvalid;end endProcessTdata : // 3begin 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 elsebegin state_reg <= ProcessTdata;end endCheckTlast : // 4begin if (m_axis_tlast == 1'b1)begin    state_reg <= init;endelse if (m_axis_tready == 1'b1)beginstate_reg <= SetSlaveTready;endelse begin state_reg <= CheckTlast;end end endcase endend
endmodule

完整的代码见最后。

Vitis 软件

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

int main()
{init_platform();XAxiDma_Config *CfgPtr; //DMA configuration pointerint 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.rhkb.cn/news/123216.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT QToolBox控件使用详解

本文详细的介绍了QToolBox控件的各种操作&#xff0c;例如&#xff1a;新建界面、添加页签、索引设置当前项、获取当前项的索引、获取当前项窗口、获取索引值是int的窗口、移除索引值项、获取项的数量、获取指定索引值、设置索引项是否激活、获取索引值项是否激活、设置项的图标…

vue+antd——table组件实现动态列+表头下拉选择功能——技能提升

Table 表格 展示行列数据。 何时使用 当有大量结构化的数据需要展现时&#xff1b; 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。 最近在写vueantd的框架&#xff0c;遇到一个需求&#xff1a;就是要实现table表格的动态列&#xff0c;并且相应的表头要实现下拉…

el-date-picker 禁止选择当前年之前或者之后的年份

<el-date-picker v-model"ruleForm.years" type"year" :disabled-date"pickerOptions"placeholder"请选择获奖年度" class"wih-650p" value-format"YYYY" />之前 const disabledDateFun (time: any) >…

用户案例 | 蜀海供应链基于 Apache DolphinScheduler 的数据表血缘探索与跨大版本升级经验

导读 蜀海供应链是集销售、研发、采购、生产、品保、仓储、运输、信息、金融为一体的餐饮供应链服务企业。2021年初&#xff0c;蜀海信息技术中心大数据技术研发团队开始测试用DolphinScheduler作为数据中台和各业务产品项目的任务调度系统工具。本文主要分享了蜀海供应链在海…

YOLO目标检测——火焰检测数据集+已标注xml和txt格式标签下载分享

实际项目应用&#xff1a;火灾预警系统、智能监控系统、工业安全管理、森林火灾监测以及城市规划和消防设计等应用场景中具有广泛的应用潜力&#xff0c;可以提高火灾检测的准确性和效率&#xff0c;保障人员和财产的安全。数据集说明&#xff1a;YOLO火焰目标检测数据集&#…

Python接口自动化封装导出excel方法和读写excel数据

一、首先需要思考&#xff0c;我们在页面导出excel&#xff0c;用python导出如何写入文件的 封装前需要确认python导出excel接口返回的是一个什么样的数据类型 如下&#xff1a;我们先看下不对返回结果做处理&#xff0c;直接接收数据类型是一个对象&#xff0c;无法获取返回值…

Java“牵手”微店商品列表数据,关键词搜索微店商品数据接口,微店API申请指南

微店商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取微店商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问微店商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

【位运算】leetcode371:两整数之和

一.题目描述 两整数之和 二.思路分析 题目要求我们实现两整数相加&#xff0c;但是不能使用加号&#xff0c;应该立马想到是用位运算来解决问题。之前说过&#xff0c;异或就是“无进位相加”&#xff0c;故本题可以先将两数异或&#xff0c;然后想办法让得到的结果进位即可。…

Xubuntu16.04系统中解决无法识别exFAT格式的U盘

问题描述 将exFAT格式的U盘插入到Xubuntu16.04系统中&#xff0c;发现系统可以识别到此U盘&#xff0c;但是打不开&#xff0c;查询后发现需要安装exfat-utils库才行。 解决方案&#xff1a; 1.设备有网络的情况下 apt-get install exfat-utils直接安装exfat-utils库即可 2.设备…

任天堂开发全新独立VR设备,或为下一代主机?将提供混合现实体验

根据爆料人Nash Weedle在X平台上的发文&#xff0c;我们得知任天堂正在秘密开发一款全新的独立VR设备&#xff0c;该设备将拥有一块MicroLED屏幕&#xff0c;并且独立于任天堂传闻中的下一代主机。与此同时&#xff0c;谷歌也参与了这款VR产品的研发工作。 这一新的VR设备被设计…

iTunes备份文件在哪?苹果手机怎么恢复iTunes备份?

iTunes是苹果手机的一个常见应用&#xff0c;很多小伙伴都使用它来备份手机上的重要数据。通过iTunes备份数据到电脑后还可以进行随时管理和查看。itunes备份文件在哪&#xff1f;手机数据丢失怎么恢复iTunes备份&#xff1f;接下来&#xff0c;本文将给大家介绍一下&#xff0…

vue 脚手架新手入门(vue cli 3)

文章目录 1、vue中的 “:” 绑定和 “” 监听1.1、v-model 双向绑定 2、if 、else 、for3、computed 计算属性4、生命周期&#xff08;属性加载顺序&#xff09;5、watch 侦听器6、 components 组件6.1、props 从父组件获取收据6.2、emits 向父组件触发事件6.3、slots插槽&…

Agisoft/PhotoScan手动对齐照片

所以我到网上查了一下资料&#xff0c;了解了如何通过添加标记的方式&#xff0c;手动对齐照片。参考文档是PhotoScan的用户手册(http://www.agisoft.com/pdf/photoscan-pro_1_4_en.pdf)。 手动对齐照片&#xff0c;需要在未对齐照片上添加四个及以上标记&#xff0c;并在已对…

前端开发从 0 到 1 掌握 docker

文章目录 前端从 0 到 1 掌握 docker一、docker 的一些基础概念概念定义question&#xff1a;什么是docker&#xff1f; 为什么要使用docker&#xff1f; 二、实战操作 (墙裂建议读者实操一遍)Part1 - Linux CentOS 服务安装 DockerPart2 - 启动、使用、查看等命令Part3 - 示例…

羊城杯2023 部分wp

目录 D0nt pl4y g4m3!!!(php7.4.21源码泄露&pop链构造) Serpent(pickle反序列化&python提权) ArkNights(环境变量泄露) Ez_misc(win10sinpping_tools恢复) D0nt pl4y g4m3!!!(php7.4.21源码泄露&pop链构造) 访问/p0p.php 跳转到了游戏界面 应该是存在302跳转…

stable diffusion实践操作-随机种子seed

系列文章目录 stable diffusion实践操作 文章目录 系列文章目录前言一、seed是什么&#xff1f;二、使用步骤1.多批次随机生成多张图片2.提取图片seed3. 根据seed 再次培养4 seed使用4.1 复原别人图4.1 轻微修改4.2 固定某个人物-修改背景 三、差异随机种子1. webUI位置2. 什么…

Nebula数据库安装

1、什么是nebula NebulaGraph是一款开源的、分布式的、易扩展的原生图数据库&#xff0c;能够承载包含数千亿个点和数万亿条边的超大规模数据集&#xff0c;并且提供毫秒级查询。 2、利用docker-compose安装Nebula数据库 1、前提条件 主机中安装了docker主机中安装了Docke…

Linux上安装FTP

1、登录FTP&#xff0c;执行安装命令 yum -y install vsftpd 2、启动FTP服务器&#xff0c;设置开启自启动 systemctl enable vsftpd.service systemctl start vsftpd.service systemctl status vsftpd.service #查看状态, 显示active说明FTP启动成功 3、修改FTP配置文件/et…

Docker资源控制cgroups

文章目录 一、docker资源控制1、资源控制工具2、Cgroups四大功能 二、CPU 资源控制1、设置CPU使用率上限2、CPU压力测试3、Cgroups限制cpu使用率4、设置CPU资源占用比&#xff08;设置多个容器时才有效&#xff09;5、设置容器绑定指定的CPU 三、对内存使用的限制四、对磁盘IO配…

【网络层】网络基础 -- IP协议

引入IP协议头格式网段划分特殊的IP地址IP地址的数量限制 私有IP地址和公网IP地址分片与组装如何分片与组装&#xff1f; 引入 我们前面学习了传输层的相关知识&#xff0c;难道真的就是直接传送吗&#xff1f;当然不是&#xff0c;那TCP究竟做了什么&#xff1f;IP又扮演什么角…