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乃至更大的江湖。
评论 (0)
  • REACH和RoHS欧盟两项重要的环保法规有什么区别?适用范围有哪些?如何办理?REACH和RoHS是欧盟两项重要的环保法规,主要区别如下:一、核心定义与目标RoHS全称为《关于限制在电子电器设备中使用某些有害成分的指令》,旨在限制电子电器产品中的铅(Pb)、汞(Hg)、镉(Cd)、六价铬(Cr6+)、多溴联苯(PBBs)和多溴二苯醚(PBDEs)共6种物质,通过限制特定材料使用保障健康和环境安全REACH全称为《化学品的注册、评估、授权和限制》,覆盖欧盟市场所有化学品(食品和药品除外),通过登
    张工13144450251 2025-03-31 21:18 63浏览
  • 据先科电子官方信息,其产品包装标签将于2024年5月1日进行全面升级。作为电子元器件行业资讯平台,大鱼芯城为您梳理本次变更的核心内容及影响:一、标签变更核心要点标签整合与环保优化变更前:卷盘、内盒及外箱需分别粘贴2张标签(含独立环保标识)。变更后:环保标识(RoHS/HAF/PbF)整合至单张标签,减少重复贴标流程。标签尺寸调整卷盘/内盒标签:尺寸由5030mm升级至**8040mm**,信息展示更清晰。外箱标签:尺寸统一为8040mm(原7040mm),提升一致性。关键信息新增新增LOT批次编
    大鱼芯城 2025-04-01 15:02 95浏览
  • 提到“质量”这两个字,我们不会忘记那些奠定基础的大师们:休哈特、戴明、朱兰、克劳士比、费根堡姆、石川馨、田口玄一……正是他们的思想和实践,构筑了现代质量管理的核心体系,也深远影响了无数企业和管理者。今天,就让我们一同致敬这些质量管理的先驱!(最近流行『吉卜力风格』AI插图,我们也来玩玩用『吉卜力风格』重绘质量大师画象)1. 休哈特:统计质量控制的奠基者沃尔特·A·休哈特,美国工程师、统计学家,被誉为“统计质量控制之父”。1924年,他提出世界上第一张控制图,并于1931年出版《产品制造质量的经济
    优思学院 2025-04-01 14:02 66浏览
  • 北京贞光科技有限公司作为紫光同芯产品的官方代理商,为客户提供车规安全芯片的硬件、软件SDK销售及专业技术服务,并且可以安排技术人员现场支持客户的选型和定制需求。在全球汽车电子市场竞争日益激烈的背景下,中国芯片厂商正通过与国际领先企业的深度合作,加速融入全球技术生态体系。近日,紫光同芯与德国HighTec达成的战略合作标志着国产高端车规芯片在国际化道路上迈出了关键一步,为中国汽车电子产业的发展注入了新的活力。全栈技术融合:打造国际化开发平台紫光同芯与HighTec共同宣布,HighTec汽车级编译
    贞光科技 2025-03-31 14:44 75浏览
  • 引言在语音芯片设计中,输出电路的设计直接影响音频质量与系统稳定性。WT588系列语音芯片(如WT588F02B、WT588F02A/04A/08A等),因其高集成度与灵活性被广泛应用于智能设备。然而,不同型号在硬件设计上存在关键差异,尤其是DAC加功放输出电路的配置要求。本文将从硬件架构、电路设计要点及选型建议三方面,解析WT588F02B与F02A/04A/08A的核心区别,帮助开发者高效完成产品设计。一、核心硬件差异对比WT588F02B与F02A/04A/08A系列芯片均支持PWM直推喇叭
    广州唯创电子 2025-04-01 08:53 105浏览
  • Shinco音响拆解 一年一次的面包板社区的拆解活动拉开帷幕了。板友们开始大显身手了,拆解各种闲置的宝贝。把各自的设计原理和拆解的感悟一一向电子爱好者展示。产品使用了什么方案,用了什么芯片,能否有更优的方案等等。不仅让拆解的人员了解和深入探索在其中。还可以让网友们学习电子方面的相关知识。今天我也向各位拆解一个产品--- Shinco音响(如下图)。 当产品连接上电脑的耳机孔和USB孔时,它会发出“开机,音频输入模式”的语音播报,。告诉用户它已经进入音响外放模式。3.5mm耳机扣接收电脑音频信号。
    zhusx123 2025-03-30 15:42 107浏览
  • 一、温度计不准的原因温度计不准可能由多种原因导致,如温度计本身的质量问题、使用环境的变化、长时间未进行校准等。为了确保温度计的准确性,需要定期进行校准。二、校准前准备工作在进行温度计校准之前,需要做好以下准备工作:1. 选择合适的校准方法和设备,根据温度计的型号和使用需求来确定。2. 确保校准环境稳定,避免外部因素对校准结果产生影响。3. 熟悉温度计的使用说明书和校准流程,以便正确操作。三、温度计校准方法温度计校准方法一般分为以下几步:1. 将温度计放置在
    锦正茂科技 2025-03-31 10:27 43浏览
  • 引言随着物联网和智能设备的快速发展,语音交互技术逐渐成为提升用户体验的核心功能之一。在此背景下,WT588E02B-8S语音芯片,凭借其创新的远程更新(OTA)功能、灵活定制能力及高集成度设计,成为智能设备语音方案的优选。本文将从技术特性、远程更新机制及典型应用场景三方面,解析该芯片的技术优势与实际应用价值。一、WT588E02B-8S语音芯片的核心技术特性高性能硬件架构WT588E02B-8S采用16位DSP内核,内部振荡频率达32MHz,支持16位PWM/DAC输出,可直接驱动8Ω/0.5W
    广州唯创电子 2025-04-01 08:38 87浏览
  •        在“软件定义汽车”的时代浪潮下,车载软件的重要性日益凸显,软件在整车成本中的比重逐步攀升,已成为汽车智能化、网联化、电动化发展的核心驱动力。车载软件的质量直接关系到车辆的安全性、可靠性以及用户体验,因此,构建一套科学、严谨、高效的车载软件研发流程,确保软件质量的稳定性和可控性,已成为行业共识和迫切需求。       作为汽车电子系统领域的杰出企业,经纬恒润深刻理解车载软件研发的复杂性和挑战性,致力于为O
    经纬恒润 2025-03-31 16:48 51浏览
  • 升职这件事,说到底不是单纯靠“干得多”或者“喊得响”。你可能也看过不少人,能力一般,甚至没你努力,却升得飞快;而你,日复一日地拼命干活,升职这两个字却始终离你有点远。这种“不公平”的感觉,其实在很多职场人心里都曾经出现过。但你有没有想过,问题可能就藏在一些你“没当回事”的小细节里?今天,我们就来聊聊你升职总是比别人慢,可能是因为这三个被你忽略的小细节。第一:你做得多,但说得少你可能是那种“默默付出型”的员工。项目来了接着干,困难来了顶上去,别人不愿意做的事情你都做了。但问题是,这些事情你做了,却
    优思学院 2025-03-31 14:58 73浏览
  • 在环保与经济挑战交织的当下,企业如何在提升绩效的同时,也为地球尽一份力?普渡大学理工学院教授 查德·劳克斯(Chad Laux),和来自 Maryville 大学、俄亥俄州立大学及 Trine 大学的三位学者,联合撰写了《精益可持续性:迈向循环经济之路(Lean Sustainability: Creating a Sustainable Future through Lean Thinking)》一书,为这一问题提供了深刻的答案。这本书也荣获了 国际精益六西格玛研究所(IL
    优思学院 2025-03-31 11:15 60浏览
  • 在不久前发布的《技术实战 | OK3588-C开发板上部署DeepSeek-R1大模型的完整指南》一文中,小编为大家介绍了DeepSeek-R1在飞凌嵌入式OK3588-C开发板上的移植部署、效果展示以及性能评测,本篇文章不仅将继续为大家带来关于DeepSeek-R1的干货知识,还会深入探讨多种平台的移植方式,并介绍更为丰富的交互方式,帮助大家更好地应用大语言模型。1、移植过程1.1 使用RKLLM-Toolkit部署至NPURKLLM-Toolkit是瑞芯微为大语言模型(LLM)专门开发的转换
    飞凌嵌入式 2025-03-31 11:22 134浏览
  • 在智能家居领域,无线门铃正朝着高集成度、低功耗、强抗干扰的方向发展。 WTN6040F 和 WT588F02B 两款语音芯片,凭借其 内置EV1527编解码协议 和 免MCU设计 的独特优势,为无线门铃开发提供了革命性解决方案。本文将深入解析这两款芯片的技术特性、应用场景及落地价值。一、无线门铃市场痛点与芯片方案优势1.1 行业核心痛点系统复杂:传统方案需MCU+射频模块+语音芯片组合,BOM成本高功耗瓶颈:待机电流
    广州唯创电子 2025-03-31 09:06 147浏览
  • 在智能语音交互设备开发中,系统响应速度直接影响用户体验。WT588F系列语音芯片凭借其灵活的架构设计,在响应效率方面表现出色。本文将深入解析该芯片从接收指令到音频输出的全过程,并揭示不同工作模式下的时间性能差异。一、核心处理流程与时序分解1.1 典型指令执行路径指令接收 → 协议解析 → 存储寻址 → 数据读取 → 数模转换 → 音频输出1.2 关键阶段时间分布(典型值)处理阶段PWM模式耗时DAC模式耗时外挂Flash模式耗时指令解析2-3ms2-3ms3-5ms存储寻址1ms1ms5-10m
    广州唯创电子 2025-03-31 09:26 180浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦