前言:

最近做調製解調系統,在網上找了不少教程,雖然確實有很大的參考意義,但是問題也很明顯:

過於簡單,無法實用。例如一些教程直接用方波作為載波,代替正弦波。

功能單一,不夠系統。大部分解調教程只完成了波形復現,沒有完全復現數字訊號。

解調方面的資料少。

已經實現了最簡單的基礎功能,把思路分享出來供大家參考。原始碼暫時只提供頂層檔案,子模組可以根據功能描述自行設計,感謝理解。以後會開源。

非通訊科班出身,難免會出現不少錯誤,歡迎大佬批評指正。

未經允許請勿轉載。

發射端電路:

FPGA實現2fsk數字調製解調(verilog)

電路原理:

l_clk

產生100Hz訊號,其週期10ms是天線發射一個碼元對應的時間(取的比較長是方便用示波器直觀地看出來)。

jsq5

模5計數器,即50ms為一幀。後續電路會根據cnt的值完成不同工作。

read

cnt=0時讀取info_s,cnt=1-4時發射相應位的二進位制數。

code

編碼,其實就是最簡單的並串轉換。

clk_wiz_0

ip核,產生讀取rom所需的時鐘,這裡頻率分別是1024×11k和1024×22k。

rom

ip核,儲存正弦訊號。

da_wave_send

讀取rom。

行為級模擬結果:

FPGA實現2fsk數字調製解調(verilog)

55ms-105ms是完整的一幀

55ms時讀取info_s,即要發射的資料。55-65ms部分不發射任何訊號,這裡是方便接收端進行同步(根據這段空白識別舊一幀的結束和新一幀的開始)。

65-105ms部分為調製後的載波訊號。22kHz表示“0”、11kHz表示“1”。0110正好對應55ms時info_s的值“6”。

頂層程式碼:

module

num_4_communication

input

s_clk

//系統時鐘

input

s_rst

//系統復位,低電平有效

input

4

-

1

0

info_s

output

da_clk

//DA 取樣時鐘

output

9

0

da_data

//DA 取樣資料

);

wire

10

-

1

0

rd_addr

wire

10

-

1

0

rd_data

wire

4

-

1

0

info

wire

3

-

1

0

cnt

wire

l_clk_10

wire

modu

wire

en

wire

clk_out1

wire

clk_out2

//時鐘模組(ip核)

clk_wiz_0

u_clk_wiz_0

clk_in1

s_clk

),

clk_out1

clk_out1

),

clk_out2

clk_out2

);

//時鐘模組(low)

l_clk

u_l_clk

s_clk

s_clk

),

s_rst

s_rst

),

l_clk_10

l_clk_10

);

//資料讀取

read

u_read

l_clk_10

l_clk_10

),

s_rst

s_rst

),

info_s

info_s

),

cnt

cnt

),

info

info

);

//JSQ

jsq_5

u_jsq_5

l_clk_10

l_clk_10

),

s_rst

s_rst

),

cnt

cnt

);

//編碼

code

u_code

l_clk_10

l_clk_10

),

s_rst

s_rst

),

cnt

cnt

),

info

info

),

modu

modu

),

en

en

);

//調製

modulation

u_modulation

modu

modu

),

clk_out1

clk_out1

),

clk_out2

clk_out2

),

clk

clk

);

//DA傳送1

da_wave_send

u1_da_wave_send

clk

clk

),

s_rst

s_rst

),

en

en

),

rd_data

rd_data

),

rd_addr

rd_addr

),

da_data

da_data

),

da_clk

da_clk

);

//rom

rom

u_rom

addra

rd_addr

),

clka

da_clk

),

douta

rd_data

);

endmodule

接收端電路

解調採用比較簡單的非相干解調,包絡檢波法。使用兩個通帶頻率分別為11k、22k的帶通濾波器,透過簡單的

帶通濾波-整流-低通濾波

即可檢測接收訊號中相應頻率訊號的功率。

對兩個低通濾波器的輸出做減法運算,求出11k和22k分量的差值。當該差值足夠大時,即可認為接收到了可信的“0”或“1”,否則認為此時沒有訊號。

如果接收端的狀態從“認為此時沒有訊號”變為“認為此時接收到了可到的訊號”,則對應發射端的狀態為一幀載波訊號的開始。signal_en的上升沿可以表述這一變化,利用這一特性可以實現同步。

FPGA實現2fsk數字調製解調(verilog)

電路原理:

fir_11k、fir_22k、lowpass

數字濾波器ip核,實現帶通濾波和低通濾波。

rectify

整流,就是取絕對值。

dem

根據差值的正負判斷接收到的訊號是“0”或“1”。

bit_judge

差值位寬判斷。

avg

求每32個取樣週期得到的差值位寬的平均值。

signal_enable

根據上述均值,判斷該段時間內的訊號是否可信。

judgment

同步、判決、串並轉換、輸出資料。

行為級模擬結果:

FPGA實現2fsk數字調製解調(verilog)

info_judge即接收端最終還原出的4bit資料。

其中wave_s和modu由testbench產生。

wave_11k_dc、wave22kdc 、differencebitavg、signal_en都是電路內部訊號,實際不需輸出。

sum_over下降沿輸出訊號穩定,可以作為讀取指令。

info_prob為“1”時表示該位資料雖然有輸出,但不可靠。

頂層程式碼:

module

num_4_receive

input

clk

//200kHz系統時鐘

input

rst

input

9

0

wave_s

//AD訊號輸入

output

3

0

info_judge

//復原訊號

output

3

0

info_prob

//可靠性判斷

output

sum_over

//並行資料接收指示,上升沿處理資料,下降沿時info_judge穩定

);

// 10位輸入轉為16位

wire

15

0

fir_in

assign

fir_in

15

6

=

wave_s

assign

fir_in

5

0

=

6

‘d0000

//濾波器35位輸出擷取為16位

wire

signed

39

0

data1

wire

signed

39

0

data2

wire

signed

15

0

wave_11k

wire

signed

15

0

wave_22k

assign

wave_11k

=

data1

34

19

];

assign

wave_22k

=

data2

34

19

];

//整流後的波形

wire

15

0

wave_11k_abs

wire

15

0

wave_22k_abs

//低通濾波器輸出取16位

wire

signed

39

0

data1_dc40

wire

signed

39

0

data2_dc40

wire

signed

15

0

wave_11k_dc

wire

signed

15

0

wave_22k_dc

assign

wave_11k_dc

=

data1_dc40

35

20

];

assign

wave_22k_dc

=

data2_dc40

35

20

];

wire

info

//差值估值 判斷訊號有無

wire

signed

15

0

demode

wire

15

0

difference_abs

wire

3

0

difference_bit

wire

3

0

noise_bit

=

4

’b0000

wire

clk_avg

//64倍時鐘 每計算完32次取樣均值變化一次

wire

clk_avg_1

//比clk_avg略有延遲

wire

4

0

difference_bit_avg

//訊號差值估算

wire

signal_en

//接收到的訊號有效

//wire [3:0] info_judge; //最終並行資料

//wire [3:0] info_prob; //問題報警訊號

//wire sum_over; //並行資料接收指示

//過帶通濾波器

fir_11k

u_fir_11k

aclk

clk

),

s_axis_data_tvalid

1

‘b1

),

s_axis_data_tready

(),

s_axis_data_tdata

fir_in

),

m_axis_data_tvalid

(),

m_axis_data_tdata

data1

);

fir_22k

u_fir_22k

aclk

clk

),

s_axis_data_tvalid

1

’b1

),

s_axis_data_tready

(),

s_axis_data_tdata

fir_in

),

m_axis_data_tvalid

(),

m_axis_data_tdata

data2

);

//整流1

rectify

u1_rectify

wave

wave_11k

),

wave_abs

wave_11k_abs

);

rectify

u2_rectify

wave

wave_22k

),

wave_abs

wave_22k_abs

);

//低通濾波器

lowpass

u1_lowpass

aclk

clk

),

s_axis_data_tvalid

1

‘b1

),

s_axis_data_tready

(),

s_axis_data_tdata

wave_11k_abs

),

m_axis_data_tvalid

(),

m_axis_data_tdata

data1_dc40

);

lowpass

u2_lowpass

aclk

clk

),

s_axis_data_tvalid

1

’b1

),

s_axis_data_tready

(),

s_axis_data_tdata

wave_22k_abs

),

m_axis_data_tvalid

(),

m_axis_data_tdata

data2_dc40

);

//解調

dem

u_dem

clk

clk

),

rst

rst

),

wave_11k_dc

wave_11k_dc

),

wave_22k_dc

wave_22k_dc

),

info

info

),

demode

demode

);

//差值訊號過整流

rectify

u3_rectify

wave

demode

),

wave_abs

difference_abs

);

//差值位寬判斷

bit_judge

bit_judge

clk

clk

),

rst

rst

),

difference_abs

difference_abs

),

difference_bit

difference_bit

);

//每32位取樣資料取平均值

avg

avg

clk

clk

),

rst

rst

),

difference_bit

difference_bit

),

clk_avg

clk_avg

),

clk_avg_1

clk_avg_1

),

difference_bit_avg

difference_bit_avg

);

//判斷是否接收到訊號

signal_enable

signal_enable

clk_avg_1

clk_avg_1

),

rst

rst

),

difference_bit_avg

difference_bit_avg

),

noise_bit

noise_bit

),

signal_en

signal_en

);

//同步 判決 輸出訊號

judgment

judgment

clk

clk

),

rst

rst

),

info

info

),

signal_en

signal_en

),

// 訊號有效性判斷

clk_avg

clk_avg

),

//

info_judge

info_judge

),

//復原訊號

info_prob

info_prob

),

//可靠性判斷

sum_over

sum_over

);

endmodule

總結

幼兒玩具水平的系統,不過幫助理解了一些基礎知識。

後續會對速率、抗噪聲等進行改進,也會做一些其他調製方法的。最終實現實用的OFDM。

任何問題可以私信交流、共同學習。感謝!