Transmisor de banda base FSK simple en ZYNQ

e98c9b0b6c14bbaffd3d561402760dcb.png

introducción

Dado que algunos requisitos requieren generar una onda sinusoidal, la función sin() en la aplicación C se usa para calcular el valor de amplitud del círculo unitario y luego convertir ese valor de amplitud al código DAC apropiado para el AD9717 (convirtiendo cada valor de ángulo a radianes por supuesto).

69aab3dc24e3805f83ee23c1b154e767.png

Al poder generar ondas sinusoidales simples usando un DAC, la siguiente idea es usar modulación de frecuencia en SDR (Software Defined Radio).

La mayoría de los diseños de SDR tienen 3 frecuencias operativas internas diferentes: una frecuencia de banda base baja para procesar los datos del ADC/DAC; una o más frecuencias intermedias a las que se eleva el flujo de datos de banda base final como paso intermedio; y finalmente la entrada de RF /salida la frecuencia de salida de la antena. Obviamente, el lugar más fácil para comenzar es la banda base, ya que es la frecuencia más baja y es donde el flujo de datos analógicos real se combina/extrae de los bits de datos digitales individuales. Para reducirlo aún más, los puntos exactos en los que los bits digitales de 1 y 0 se relacionan con alguna forma de onda analógica relevante se denominan mapeador de símbolos, que es el componente básico de SDR mencionado anteriormente.

Por lo tanto, este proyecto será un mapeador de símbolos de banda base muy simplificado para el extremo de transmisión de la cadena (digital a analógica) del esquema de modulación digital FSK.

modulación digital

La manipulación por desplazamiento de frecuencia (FSK) es un tipo de modulación digital que cambia la frecuencia para representar diferentes bits/símbolos en un flujo de datos. En su forma más básica, se usa una frecuencia para representar un 1 binario y otra frecuencia para representar un 0 binario. Esta forma de FSK se llama FSK binaria o 2-FSK.

ae0d6b10412307dab564095b94bd8138.png

Como se puede ver en lo anterior, un bit 1 está representado por aproximadamente el doble de la frecuencia de un bit 0. Para ZYNQ+SDR, esto significa que debe poder generar dos frecuencias diferentes con fases continuas. En otras palabras: la sincronización es importante aquí para garantizar que la fase de una frecuencia ocurra exactamente donde se detuvo la fase de la última frecuencia. Cada bit también completa un ciclo completo de cada frecuencia.

Diseño lógico en Vivado.

Dado que en esta demostración solo el lado del transmisor es de interés, para manejar la contrapresión que la lógica del mapeador de símbolos puede imponer en el flujo de datos de la memoria DDR en la lectura del MM2S, se coloca una LUT sin con el mapeador de símbolos FSK en los datos de AXIS FIFO y entre la IP del controlador DAC. De esta manera, FIFO puede completar la transferencia MM2S desde la memoria y AXI DMA no se bloqueará en tdata mientras la lógica del asignador de símbolos genera el valor de frecuencia correspondiente durante un ciclo por bit.

d7cf6459b8847f5bb7e23230e5c96a88.png

El código se muestra a continuación:

`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

Dado que los valores seleccionados en la declaración de caso de sin LUT son para cada 360 grados del círculo unitario de la onda sinusoidal, la velocidad a la que el contador aumenta de 0 a 360 finalmente establece la frecuencia de la onda sinusoidal de salida.

Se requieren tres contadores en la lógica encima de sin LUT: uno para contar los grados que la sin LUT selecciona de 0 a 359, uno para contar el retraso entre incrementos de frecuencia 0 y otro para contar el retraso de frecuencia entre incrementos de 0. Frecuencia 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

También se necesita un conversor paralelo a serie para obtener los datos de 32 bits a través de la interfaz AXI Stream del paquete de datos enviado desde el DDR a través de la transmisión MM2S y serializarlo. Se puede realizar un ciclo de la frecuencia respectiva del bit. salida a través de la transmisión MM2S. DAC una vez. Aquí es donde entran en juego las limitaciones del 2-FSK: sólo se puede transmitir un bit a la vez.

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

Al final, la interfaz AXI Stream solo necesita seguir la lógica anterior, utilizando la interfaz esclava para recibir datos del AXIS FIFO y la interfaz maestra para enviar los datos al controlador 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

Vea el código completo al final.

software vitis

Dado que toda la lógica para generar la onda sinusoidal se maneja en HDL en Verilog, lo único que queda en el código C es controlar la transmisión MM2S (el archivo fuente también se adjunta a continuación):

int main()
{
    init_platform();

    XAxiDma_Config *CfgPtr; //DMA configuration pointer
    int Status, Index;
    u8 *TxBufferPtr;

    TxBufferPtr = (u8 *)TX_BUFFER_BASE;

    for(Index = 0; Index < MAX_PKT_LEN; Index ++){
        TxBufferPtr[Index] = 0x00;
    }

    CfgPtr = XAxiDma_LookupConfig(DMA_DEV_ID);
    if (!CfgPtr) {
        xil_printf("No config found for %d\r\n", DMA_DEV_ID);
        return XST_FAILURE;
    }

    Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
    if (Status != XST_SUCCESS) {
        xil_printf("Initialization failed %d\r\n", Status);
        return XST_FAILURE;
    }

    XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE);

    TxBufferPtr[0] = 0xef;

    Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);
    XAxiDma_Reset(&AxiDma);

    Status = XAxiDma_MM2Stransfer(&AxiDma,(UINTPTR) TxBufferPtr, MAX_PKT_LEN);
    if (Status != XST_SUCCESS){
        xil_printf("XAXIDMA_DMA_TO_DEVICE transfer failed...\r\n");
 return XST_FAILURE;
    }

    cleanup_platform();
    return 0;
}
1840c4e4a752672229b04809c58d60c7.png

Equipo de prueba

Para verificar la salida analógica, conecte su canal 1 al canal 1 del osciloscopio e inicie WaveForms en la PC host para verlo.

Luego, se inició la depuración de la aplicación C en Vitis y se estableció un punto de interrupción antes de que comenzara la transferencia MM2S:

79ee256334f6ad022f0b9868356b23af.png

Dado que el DAC está configurado en modo de ganancia baja, el valor máximo de salida es de aproximadamente 1,0 V. En la pestaña Alcance de WaveForms, configure el disparador de nivel para flancos ascendentes por encima de 100 mV y haga clic en Ejecutar.

Obtenga una salida clara de dos valores de frecuencia diferentes 1 y 0:

adb1d214826706c50685e0612e619b7f.png

Como mencioné anteriormente, esta es solo una versión muy simplificada del mapeador de símbolos para superar las dificultades de comenzar con el diseño SDR de una manera más práctica y práctica. Dos contadores de períodos con diferentes frecuencias son un buen punto de partida para ver el resultado.

código

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

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

Supongo que te gusta

Origin blog.csdn.net/Pieces_thinking/article/details/132680536
Recomendado
Clasificación