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乃至更大的江湖。
评论
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2024-12-02 10:40 107浏览
  • 11-29学习笔记11-29学习笔记习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-02 23:58 54浏览
  • 戴上XR眼镜去“追龙”是种什么体验?2024年11月30日,由上海自然博物馆(上海科技馆分馆)与三湘印象联合出品、三湘印象旗下观印象艺术发展有限公司(下简称“观印象”)承制的《又见恐龙》XR嘉年华在上海自然博物馆重磅开幕。该体验项目将于12月1日正式对公众开放,持续至2025年3月30日。双向奔赴,恐龙IP撞上元宇宙不久前,上海市经济和信息化委员会等部门联合印发了《上海市超高清视听产业发展行动方案》,特别提到“支持博物馆、主题乐园等场所推动超高清视听技术应用,丰富线下文旅消费体验”。作为上海自然
    电子与消费 2024-11-30 22:03 90浏览
  • 学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&
    youyeye 2024-11-30 14:30 74浏览
  •         温度传感器的精度受哪些因素影响,要先看所用的温度传感器输出哪种信号,不同信号输出的温度传感器影响精度的因素也不同。        现在常用的温度传感器输出信号有以下几种:电阻信号、电流信号、电压信号、数字信号等。以输出电阻信号的温度传感器为例,还细分为正温度系数温度传感器和负温度系数温度传感器,常用的铂电阻PT100/1000温度传感器就是正温度系数,就是说随着温度的升高,输出的电阻值会增大。对于输出
    锦正茂科技 2024-12-03 11:50 86浏览
  • 作为优秀工程师的你,已身经百战、阅板无数!请先醒醒,新的项目来了,这是一个既要、又要、还要的产品需求,ARM核心板中一个处理器怎么能实现这么丰富的外围接口?踌躇之际,你偶阅此文。于是,“潘多拉”的魔盒打开了!没错,USB资源就是你打开新世界得钥匙,它能做哪些扩展呢?1.1  USB扩网口通用ARM处理器大多带两路网口,如果项目中有多路网路接口的需求,一般会选择在主板外部加交换机/路由器。当然,出于成本考虑,也可以将Switch芯片集成到ARM核心板或底板上,如KSZ9897、
    万象奥科 2024-12-03 10:24 46浏览
  • RDDI-DAP错误通常与调试接口相关,特别是在使用CMSIS-DAP协议进行嵌入式系统开发时。以下是一些可能的原因和解决方法: 1. 硬件连接问题:     检查调试器(如ST-Link)与目标板之间的连接是否牢固。     确保所有必要的引脚都已正确连接,没有松动或短路。 2. 电源问题:     确保目标板和调试器都有足够的电源供应。     检查电源电压是否符合目标板的规格要求。 3. 固件问题: &n
    丙丁先生 2024-12-01 17:37 90浏览
  • 《高速PCB设计经验规则应用实践》+PCB绘制学习与验证读书首先看目录,我感兴趣的是这一节;作者在书中列举了一条经典规则,然后进行详细分析,通过公式推导图表列举说明了传统的这一规则是受到电容加工特点影响的,在使用了MLCC陶瓷电容后这一条规则已经不再实用了。图书还列举了高速PCB设计需要的专业工具和仿真软件,当然由于篇幅所限,只是介绍了一点点设计步骤;我最感兴趣的部分还是元件布局的经验规则,在这里列举如下:在这里,演示一下,我根据书本知识进行电机驱动的布局:这也算知行合一吧。对于布局书中有一句:
    wuyu2009 2024-11-30 20:30 109浏览
  • 艾迈斯欧司朗全新“样片申请”小程序,逾160种LED、传感器、多芯片组合等产品样片一触即达。轻松3步完成申请,境内免费包邮到家!本期热荐性能显著提升的OSLON® Optimal,GF CSSRML.24ams OSRAM 基于最新芯片技术推出全新LED产品OSLON® Optimal系列,实现了显著的性能升级。该系列提供五种不同颜色的光源选项,包括Hyper Red(660 nm,PDN)、Red(640 nm)、Deep Blue(450 nm,PDN)、Far Red(730 nm)及Ho
    艾迈斯欧司朗 2024-11-29 16:55 172浏览
  • 遇到部分串口工具不支持1500000波特率,这时候就需要进行修改,本文以触觉智能RK3562开发板修改系统波特率为115200为例,介绍瑞芯微方案主板Linux修改系统串口波特率教程。温馨提示:瑞芯微方案主板/开发板串口波特率只支持115200或1500000。修改Loader打印波特率查看对应芯片的MINIALL.ini确定要修改的bin文件#查看对应芯片的MINIALL.ini cat rkbin/RKBOOT/RK3562MINIALL.ini修改uart baudrate参数修改以下目
    Industio_触觉智能 2024-12-03 11:28 54浏览
  • 最近几年,新能源汽车愈发受到消费者的青睐,其销量也是一路走高。据中汽协公布的数据显示,2024年10月,新能源汽车产销分别完成146.3万辆和143万辆,同比分别增长48%和49.6%。而结合各家新能源车企所公布的销量数据来看,比亚迪再度夺得了销冠宝座,其10月新能源汽车销量达到了502657辆,同比增长66.53%。众所周知,比亚迪是新能源汽车领域的重要参与者,其一举一动向来为外界所关注。日前,比亚迪汽车旗下品牌方程豹汽车推出了新车方程豹豹8,该款车型一上市就迅速吸引了消费者的目光,成为SUV
    刘旷 2024-12-02 09:32 104浏览
  • 概述 说明(三)探讨的是比较器一般带有滞回(Hysteresis)功能,为了解决输入信号转换速率不够的问题。前文还提到,即便使能滞回(Hysteresis)功能,还是无法解决SiPM读出测试系统需要解决的问题。本文在说明(三)的基础上,继续探讨为SiPM读出测试系统寻求合适的模拟脉冲检出方案。前四代SiPM使用的高速比较器指标缺陷 由于前端模拟信号属于典型的指数脉冲,所以下降沿转换速率(Slew Rate)过慢,导致比较器检出出现不必要的问题。尽管比较器可以使能滞回(Hysteresis)模块功
    coyoo 2024-12-03 12:20 78浏览
  • 国产光耦合器正以其创新性和多样性引领行业发展。凭借强大的研发能力,国内制造商推出了适应汽车、电信等领域独特需求的专业化光耦合器,为各行业的技术进步提供了重要支持。本文将重点探讨国产光耦合器的技术创新与产品多样性,以及它们在推动产业升级中的重要作用。国产光耦合器创新的作用满足现代需求的创新模式新设计正在满足不断变化的市场需求。例如,高速光耦合器满足了电信和数据处理系统中快速信号传输的需求。同时,栅极驱动光耦合器支持电动汽车(EV)和工业电机驱动器等大功率应用中的精确高效控制。先进材料和设计将碳化硅
    克里雅半导体科技 2024-11-29 16:18 172浏览
  • 当前,智能汽车产业迎来重大变局,随着人工智能、5G、大数据等新一代信息技术的迅猛发展,智能网联汽车正呈现强劲发展势头。11月26日,在2024紫光展锐全球合作伙伴大会汽车电子生态论坛上,紫光展锐与上汽海外出行联合发布搭载紫光展锐A7870的上汽海外MG量产车型,并发布A7710系列UWB数字钥匙解决方案平台,可应用于数字钥匙、活体检测、脚踢雷达、自动泊车等多种智能汽车场景。 联合发布量产车型,推动汽车智能化出海紫光展锐与上汽海外出行达成战略合作,联合发布搭载紫光展锐A7870的量产车型
    紫光展锐 2024-12-03 11:38 77浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦