ZYNQ上的简单FSK基带发射器

FPGA技术江湖 2023-09-20 06:39

绪论

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

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

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

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

数字调制

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

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

Vivado 中的逻辑设计

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

代码如下:


`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;
}

测试设备

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

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

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

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

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

代码

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

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


- -THE END- -


往期精选 

 
 

【免费】FPGA工程师人才招聘平台

FPGA人才招聘,企业HR,看过来!

系统设计精选 | 基于FPGA的实时图像边缘检测系统设计(附代码)

基于原语的千兆以太网RGMII接口设计

时序分析理论和timequest使用_中文电子版

求职面试 | FPGA或IC面试题最新汇总篇

FPGA图像处理专题课新增Vivado部分内容,线上线下均可报名

FPGA时序分析及约束专题课新增Vivado部分内容,线上线下均可报名

资料汇总|FPGA软件安装包、书籍、源码、技术文档…(2023.07.09更新)

FPGA就业班,2023.09.12开班,系统性学习FPGA,高薪就业,线上线下同步!

FPGA技术江湖广发江湖帖

无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有,QQ微信双选,FPGA技术江湖打造最纯净最专业的技术交流学习平台。


FPGA技术江湖微信交流群

加群主微信,备注姓名+学校/公司+专业/岗位进群


FPGA技术江湖QQ交流群

备注姓名+学校/公司+专业/岗位进群

FPGA技术江湖 任何技术的学习就好比一个江湖,对于每一位侠客都需要不断的历练,从初入江湖的小白到归隐山林的隐世高人,需要不断的自我感悟自己修炼,让我们一起仗剑闯FPGA乃至更大的江湖。
评论
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 145浏览
  • 随着市场需求不断的变化,各行各业对CPU的要求越来越高,特别是近几年流行的 AIOT,为了有更好的用户体验,CPU的算力就要求更高了。今天为大家推荐由米尔基于瑞芯微RK3576处理器推出的MYC-LR3576核心板及开发板。关于RK3576处理器国产CPU,是这些年的骄傲,华为手机全国产化,国人一片呼声,再也不用卡脖子了。RK3576处理器,就是一款由国产是厂商瑞芯微,今年第二季推出的全新通用型的高性能SOC芯片,这款CPU到底有多么的高性能,下面看看它的几个特性:8核心6 TOPS超强算力双千
    米尔电子嵌入式 2025-01-03 17:04 55浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 68浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 85浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 116浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 100浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 170浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 75浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 80浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 104浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 127浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 44浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦