緒論
由于某種需求需要生成正弦波,因此使用 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。
代碼如下:
`timescale1ns/1ps modulesin_lut( inputclk, inputrst, input[8:0]sel, output[15:0]DAC_code ); reg[15:0]DAC_code; always@(posedgeclk) 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@(posedgeclk) 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?
還需要一個并行到串行轉換器,通過 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 控制器。
`timescale1ns/1ps modulesin_axis( inputclk, inputreset, input[31:0]s_axis_tdata, input[3:0]s_axis_tkeep, inputs_axis_tlast, outputregs_axis_tready, inputs_axis_tvalid, outputreg[31:0]m_axis_tdata, outputreg[3:0]m_axis_tkeep, outputregm_axis_tlast, inputm_axis_tready, outputregm_axis_tvalid, output[2:0]state_reg ); sin_smsin_sm_i( .clk(clk), .rst(reset), .tdata_slave(tdata_slave), .tdata_master(tdata_master), .tx_pkt_done(tx_pkt_done) ); regtlast; reg[2:0]state_reg; wiretx_pkt_done; wire[31:0]tdata_master; reg[31:0]tdata_slave; parameterinit=3'd0; parameterSetSlaveTready=3'd1; parameterCheckSlaveTvalid=3'd2; parameterProcessTdata=3'd3; parameterCheckTlast=3'd4; always@(posedgeclk) begin //Defaultoutputs 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 傳輸(源文件也附在下面):
intmain() { init_platform(); XAxiDma_Config*CfgPtr;//DMAconfigurationpointer intStatus,Index; u8*TxBufferPtr; TxBufferPtr=(u8*)TX_BUFFER_BASE; for(Index=0;Index
測試設備
為了驗證模擬輸出,將其通道 1 連接到示波器通道 1,并在主機 PC 上啟動 WaveForms 來查看它。
然后,在 Vitis 中啟動 C 應用程序的調試,并在 MM2S 傳輸開始之前設置了斷點:
由于將DAC設置為低增益模式,因此峰值輸出值約為 1.0v。在 WaveForms 的 Scope 選項卡中,為超過 100mV 的上升沿設置電平觸發器,然后單擊Run 。
得到 1 和 0 兩個不同頻率值的清晰輸出:
正如我上面提到的,這只是符號映射器的一個非常簡化的版本,目的是為了以更實用、更實際的方式克服 SDR 設計入門的困難。兩個不同頻率的周期計數器是查看輸出結果的良好起點。
審核編輯:劉清
-
發射器
+關注
關注
6文章
849瀏覽量
53473 -
FSK
+關注
關注
14文章
114瀏覽量
58394 -
SDR
+關注
關注
7文章
233瀏覽量
50485 -
基帶
+關注
關注
4文章
159瀏覽量
30874 -
數字調制
+關注
關注
0文章
46瀏覽量
13013 -
Zynq
+關注
關注
10文章
609瀏覽量
47182 -
Zynq芯片
+關注
關注
0文章
3瀏覽量
1721
原文標題:ZYNQ上的簡單 FSK 基帶發射器
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論