正点原子mini板原理图_正点原子开拓者FPGA开发板资料连载第四十八章板对板音频互传实验...

1)实验平台:正点原子开拓者FPGA 开发板

2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子

3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html

6542b7de3543064333e77a8284cf8b80.png

第四十八章 基于以太网的板对板音频互传实验

在音频环回实验中,我们成功地在开发板上实现音频的采集与播放功能;在以太网通信实

验中,我们通过网口调试助手成功地和开发板完成了以太网通信的功能。本章我们将使用以太

网接口实现两块FPGA开发板之间的音频互传与播放功能。

本章包括以下几个部分:

48.1 板对板音频互传简介

48.2 实验任务

48.3 硬件设计

48.4 程序设计

48.5 下载验证

板对板音频互传简介

音频板对板互传实验是基于以太网来传输音频数据的,我们在“以太网通信实验”章节中

对以太网的协议、MII时序等内容作了详细的介绍,如果大家对这部分内容不是很熟悉的话,

请参考“以太网通信实验”中的以太网简介部分。

从“音频环回实验”章节中可以知道,WM8978音频芯片的采样率最大为48Khz,在数据位

宽 为 32 位 数 据 格 式 下 , 每 秒 钟 传 输 的 数 据 量 为 48000*32*2 ( 左 右 两 个 声 道 ) =

3072000bit≈2.930Mbit。我们FPGA开发板上的PHY芯片类型为百兆以太网,理论上最大传输速

率为 100Mbit/s,即使加上帧头、CRC校验以及帧间隙带来的额外开销,对于实时传输音频数

据来说也是毫无压力的。我们知道,以太网通信是以数据包为单位进行数据传输,单包数据除

以太网帧头与CRC校验之外,以太网数据至少为46个有效字节,对于不足46个字节的数据要在

数据的后面补充任意值。如果我们使用以太网通信单包只传输一个32位的音频数据,那么会极

大的浪费以太网的高速传输能力,因此我们先将收到的音频数据使用fifo缓存下来,待数据量

达到预设值之后,再通过以太网发送出去。

实验任务

本节实验任务是使用以太网接口实现两块FPGA开发板之间的音频互传与播放功能。首先开

发板A对WM8978芯片进行音频数据采集,并将采集的数据通过以太网接口发送给开发板B,开发

板B将收到的数据通过WM8978芯片进行播放;开发板B同样对WM8978芯片进行音频数据采集,并

将采集的数据通过以太网接口发送给开发板A,开发板A将收到的数据通过WM8978芯片进行播放,

从而实现两块FPGA开发板之间的音频互传与播放功能。

硬件设计

WM8978音频芯片及音频接口原理图与“音频环回实验”完全相同,请参考“音频环回实验”

的硬件设计部分。以太网接口部分的硬件设计请参考“以太网通信实验”中的硬件设计部分。

由于以太网接口和WM8978音频引脚数目较多且在前面相应的章节中已经给出它们的管脚

列表,这里不再列出管脚分配。

程序设计

图 48.4.1是根据本章实验任务画出的系统框图。PLL时钟模块为WM8978音频芯片提供主时

钟,而UDP模块的驱动时钟是由开发板上的PHY芯片提供;WM8978配置模块用于初始化WM8978音

频芯片,使其能够在预设的工作模式下工作;音频接收模块用于接收来自WM8978的音频数据,将WM8978串行输入的1位数据转换成32位的并行数据;音频缓存发送控制模块用于缓存32位的

音频数据,当缓存的数据量达到预设值之后,控制以太网发送模块开始发送音频数据。以太网

接收模块负责接收另一块开发板传输的音频数据,并将接收到的数据写入音频缓存接收控制模

块,音频缓存接收控制模块负责缓存以太网接收到的音频数据,将数据存入fifo模块等待被音

频发送模块读取,音频发送模块发送音频数据,将并行输入的32位数据转成1位串行数据发送

出去。

板对板音频互传实验系统框图如下图所示:

a7ed6bc9ced8b7c30ee1bd9edd87ef1d.png

图 48.4.1 基于以太网的板对板音频互传系统框图

顶层模块的原理图如下图所示:

132b0af06f6de172641ae427323c756f.png

图 48.4.2 顶层模块原理图

由上图可知,FPGA顶层模块(eth_audio_transmit)例化了以下五个模块:PLL时钟模块

(pll_clk)、WM8978控制模块(wm8978_ctrl)、音频缓存发送控制模块(audio_cache_tx_ctrl)、

UDP模块(udp)和音频缓存接收控制模块(audio_cache_rx_ctrl)。

PLL时钟模块(pll_clk):PLL时钟模块通过调用锁相环(PLL)IP核来实现,输出1个频

率为12Mhz的时钟,作为WM8978的主时钟MCLK。

WM8978控制模块(wm8978_config):WM8978控制模块完成了WM8978的初始化配置、音频

数据采集和音频数据发送的功能,该模块例化了WM8978配置模块(wm8978_config)、音频接

收模块(audio_receive)、音频发送模块(audio_send),其中WM8978配置模块例化了IIC配

置模块(i2c_reg_cfg)和IIC驱动模块(i2c_dri)。有关该模块的详细介绍请大家参考“音

频环回实验”章节。

音频缓存发送控制(audio_cache_tx_ctrl):音频缓存发送控制模块用于缓存32位的音

频数据,当缓存的数据量达到预设值之后,控制以太网发送模块开始发送音频数据。

UDP模块(udp):UDP模块实现以太网通信的收发功能,该模块内部例化了以太网接收模

块(ip_receive)、以太网发送模块(ip_send)和CRC32校验模块(crc32_d4)。有关该模块

的详细介绍请大家参考“以太网通信实验”章节。

音频缓存接收控制(audio_cache_rx_ctrl):音频缓存接收控制模块负责缓存以太网接

收到的音频数据,将数据存入fifo模块等待被WM8978控制模块读取。

顶层模块代码如下:

1 module eth_audio_transmit(

2 input sys_clk , //系统时钟

3 input sys_rst_n , //系统复位信号,低电平有效

4 //以太网接口

5 input eth_rx_clk , //MII接收数据时钟

6 input eth_rxdv , //MII输入数据有效信号

7 input eth_tx_clk , //MII发送数据时钟

8 input [3:0] eth_rx_data , //MII输入数据

9 output eth_tx_en , //MII输出数据有效信号

10 output [3:0] eth_tx_data , //MII输出数据

11 output eth_rst_n , //以太网芯片复位信号,低电平有效

12 //wm8978 interface

13 //audio interface(master mode)

14 input aud_bclk , // WM8978位时钟

15 input aud_lrc , // 对齐信号

16 input aud_adcdat , // 音频输入

17 output aud_mclk , // WM8978的主时钟(最大为12.288MHz)

18 output aud_dacdat , // 音频输出

19 //control interface

20 output aud_scl , // WM8978的SCL信号

21 inout aud_sda // WM8978的SDA信号

22 );

23

24 //parameter define

25 //这里DES_IP=BOARD_IP,这样两块开发板可以用同一个程序实现互传音频播放

26 //开发板MAC地址 00-11-22-33-44-55

27 parameter BOARD_MAC = 48'h00_11_22_33_44_55;

28 //开发板IP地址 192.168.1.123

29 parameter BOARD_IP = {8'd192,8'd168,8'd1,8'd123};

30 //目的MAC地址 ff_ff_ff_ff_ff_ff

31 parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;

32 //目的IP地址 192.168.1.102

33 parameter DES_IP = {8'd192,8'd168,8'd1,8'd123};

34 //wire define

35 wire rst_n ;

36 wire locked ;

37

38 wire aud_rx_done ; //音频数据接收完成信号

39 wire [31:0] adc_data ; //接收到的音频数据

40 wire udp_tx_start_en ; //以太网开始发送信号

41 wire [15:0] udp_tx_byte_num ; //以太网发送的有效字节数

42 wire [31:0] udp_tx_data ; //以太网发送的数据

43 wire udp_rec_pkt_done; //以太网单包数据接收完成信号

44 wire udp_rec_en ; //以太网接收使能信号

45 wire [31:0] udp_rec_data ; //以太网接收到的数据

46 wire udp_tx_req ; //以太网发送请求数据信号

47 wire udp_tx_done ; //以太网发送完成信号

48 wire aud_tx_done ; //音频发送完成信号

49 wire [31:0] dac_data ; //音频dac数据

50

51 //*****************************************************

52 //** main code

53 //*****************************************************

54

55 assign rst_n = sys_rst_n & locked;

56

57 //锁相环

58 pll_clk u_pll_clk(

59 .inclk0 (sys_clk),

60 .areset (~sys_rst_n),

61 .c0 (aud_mclk),

62 .locked (locked)

63 );

64

65 //WM89878模块

66 wm8978_ctrl

67 #(

68 .WL (6'd32 ) //word length音频字长定义

69 )

70 u_wm8978_ctrl(

71 //system clock

72 .clk (sys_clk ),

73 .rst_n (rst_n ),

74 //wm8978 interface

75 //audio interface(master mode)

76 .aud_bclk (aud_bclk ),

77 .aud_lrc (aud_lrc ),

78 .aud_adcdat (aud_adcdat ),

79 .aud_dacdat (aud_dacdat ),

80 //control interface

81 .aud_scl (aud_scl ),

82 .aud_sda (aud_sda ),

83 //user interface

84 .dac_data (dac_data ),

85 .adc_data (adc_data ),

86 .rx_done (aud_rx_done),

87 .tx_done (aud_tx_done)

88 );

89

90 //音频缓存发送控制

91 audio_cache_tx_ctrl u_audio_cache_tx_ctrl(

92 .aud_bclk (aud_bclk),

93 .rst_n (rst_n),

94 .aud_rx_done (aud_rx_done),

95 .aud_adc_data (adc_data),

96 .eth_tx_clk (eth_tx_clk),

97 .udp_tx_req (udp_tx_req),

98 .udp_tx_done (udp_tx_done),

99 .udp_tx_start_en (udp_tx_start_en),

100 .udp_tx_byte_num (udp_tx_byte_num),

101 .udp_tx_data (udp_tx_data)

102 );

103

104 //UDP模块

105 udp

106 #(

107 .BOARD_MAC (BOARD_MAC), //参数例化

108 .BOARD_IP (BOARD_IP ),

109 .DES_MAC (DES_MAC ),

110 .DES_IP (DES_IP )

111 )

112 u_udp(

113 .eth_rx_clk (eth_rx_clk ),

114 .rst_n (rst_n ),

115 .eth_rxdv (eth_rxdv ),

116 .eth_rx_data (eth_rx_data),

117 .eth_tx_clk (eth_tx_clk ),

118 .tx_start_en (udp_tx_start_en),

119 .tx_data (udp_tx_data),

120 .tx_byte_num (udp_tx_byte_num),

121 .tx_done (udp_tx_done),

122 .tx_req (udp_tx_req ),

123 .rec_pkt_done (udp_rec_pkt_done),

124 .rec_en (udp_rec_en),

125 .rec_data (udp_rec_data),

126 .rec_byte_num (),

127 .eth_tx_en (eth_tx_en ),

128 .eth_tx_data (eth_tx_data),

129 .eth_rst_n (eth_rst_n )

130 );

131

132 //音频缓存接收控制

133 audio_cache_rx_ctrl u_audio_cache_rx_ctrl(

134 .eth_rx_clk (eth_rx_clk),

135 .rst_n (rst_n),

136 .udp_rec_pkt_done (udp_rec_pkt_done),

137 .udp_rec_en (udp_rec_en),

138 .udp_rec_data (udp_rec_data),

139 .aud_bclk (aud_bclk),

140 .aud_dac_req (aud_tx_done),

141 .dac_data (dac_data)

142 );

143

144 endmodule

在代码的第25至第33行定义了四个参量:开发板MAC地址BOARD_MAC、开发板IP地址

BOARD_IP、目的MAC地址DES_MAC和目的IP地址DES_IP。需要注意的是,如果目的IP地址和开发

板IP地址不一致或者目的MAC(公共MAC地址除外)地址和开发板MAC地址不一致的话,以太网

接收模块会直接丢掉数据,导致接收音频数据失败。因此目的MAC地址这里写的是公共MAC地址

(48'hff_ff_ff_ff_ff_ff),目的IP地址写的是和开发板IP地址相同的值,目的是为了让同

一程序可以下载在两个开发板中。

在代码的第85至第86行代码中,aud_rx_done(音频数据接收完成信号)和adc_data(接

收到的音频数据)写入音频缓存发送控制模块,该模块输出的udp_tx_start_en(以太网开始

发送信号)用于控制以太网发送模块开始传输音频数据。UDP模块输出的udp_rec_en(以太网

接收数据有效信号)和udp_rec_data(以太网接收到的数据)写入音频缓存接收控制模块。

WM8978控制模块输出的aud_tx_done(音频数据发送完成)信号作为音频缓存接收控制模块的

读请求信号,并将读取后的数据dac_data通过引脚aud_dacdat引脚发送出去。

音频缓存发送控制模块用于缓存32位的音频数据,当缓存的数据量达到预设值之后,控制

以太网发送模块开始发送音频数据。该模块代码如下所示:

1 module audio_cache_tx_ctrl(

2 input aud_bclk , //WM8978位时钟

3 input rst_n , //复位信号,低电平有效

4 input aud_rx_done , //音频数据接收完成信号

5 input [31:0] aud_adc_data , //32位音频数据

6

7 input eth_tx_clk , //以太网发送时钟

8 input udp_tx_req , //以太网发送请求数据信号

9 input udp_tx_done , //以太网发送完成信号

10 output reg udp_tx_start_en, //以太网开始发送信号

11 output [15:0] udp_tx_byte_num, //以太网发送的字节数

12 output [31:0] udp_tx_data //以太网发送的数据

13 );

14

15 //parameter define

16 //fifo缓存的数量大于等于此值时控制udp开始发送数据

17 parameter AUDIO_TX_NUM = 9'd256;

18

19 //reg define

20 reg udp_tx_flag ; //udp正在发送数据的标志

21

22 //wire define

23 wire [8:0] data_cnt; //fifo中缓存的个数

24

25 //*****************************************************

26 //** main code

27 //*****************************************************

28

29 //以太网发送的字节数(1个32位音频数据 = 4个字节),即udp_tx_byte_num = AUDIO_TX_NUM * 4

30 assign udp_tx_byte_num = {AUDIO_TX_NUM,2'd0};

31

32 //判断fifo中缓存的个数,超过预设值控制udp开始发送数据

33 always @(posedge eth_tx_clk or negedge rst_n) begin

34 if(rst_n == 1'b0) begin

35 udp_tx_flag <= 1'b0;

36 udp_tx_start_en <= 1'b0;

37 end

38 else begin

39 udp_tx_start_en <= 1'b0;

40 //只有当udp没有发送数据时才判断fifo大小是否满足发送条件

41 if(udp_tx_flag == 1'b0) begin

42 if(data_cnt >= AUDIO_TX_NUM) begin

43 udp_tx_flag <= 1'b1;

44 udp_tx_start_en <= 1'b1; //udp开始发送信号

45 end

46 end

47 else if(udp_tx_done) //udp发送完成后,将udp发送标志清零

48 udp_tx_flag <= 1'b0;

49 end

50 end

51

52 //异步fifo

53 async_fifo_512x32b u_async_fifo(

54 .aclr (~rst_n),

55 .data (aud_adc_data),

56 .rdclk (eth_tx_clk),

57 .rdreq (udp_tx_req),

58 .wrclk (aud_bclk),

59 .wrreq (aud_rx_done),

60 .q (udp_tx_data),

61 .rdempty (),

62 //注意rdusedw为读时钟下的计数,如果需要在写时钟下读取数据时,在建立fifo时选择wrusedw

63 .rdusedw (data_cnt), //fifo缓存的个数

64 .wrfull ()

65 );

66

67 endmodule

在代码的第17行定义了参数AUDIO_TX_NUM(单包发送音频数据个数),当以太网没有在发

送数据时,判断data_cnt(fifo中缓存的个数)的值是否大于等于AUDIO_TX_NUM值,当大于等

于此值时,开始通知以太网发送数据,发送的字节数为AUDIO_TX_NUM的4倍(32bit=4个字节)。

AUDIO_TX_NUM的值在这里设置为256,设置成其它值也是可以的。需要注意的是不建议单

包发送的音频数据个数太小或者太大,单包发送音频数据量太小传输效率低,太大会造成音频

传输的延时。需要注意的是,如果单包发送的数据量增加,fifo的深度也要根据缓存量相应增

加,否则fifo写满溢出,导致音频数据丢失。

图 48.4.3为音频缓存发送模块SignalTap抓取的波形图,当rdusedw(fifo中缓存的个数,

同data_cnt)计数达到256之后,udp_tx_start_en(以太网开始发送信号)开始输出一个脉冲

信号,发送的有效字节个数为1024(256*4)个字节。

b64c414f2853751cad5eb6cfdec0b6f9.png

图 48.4.3 音频缓存发送模块SignalTap波形图

音频缓存接收控制模块负责缓存以太网接收到的音频数据,将数据存入fifo模块等待被音

频发送模块读取。该模块代码如下所示:

1 module audio_cache_rx_ctrl(

2 input eth_rx_clk , //以太网接收时钟

3 input rst_n , //复位信号,低电平有效

4 input udp_rec_pkt_done, //以太网单包数据接收完成信号

5 input udp_rec_en , //以太网接收数据使能信号

6 input [31:0] udp_rec_data , //以太网接收到的数据

7

8 input aud_bclk , //WM8978位时钟

9 input aud_dac_req , //dac数据请求信号

10 output [31:0] dac_data //dac值

11 );

12

13 //reg define

14 reg rec_done_flag ; //单包数据接收完成后给出标志

15 reg rec_done_flag_d0; //异步信号打拍处理

16 reg rec_done_flag_d1; //异步信号打拍处理

17

18 wire fifo_rd_req ; //fifo读请求信号

19

20 //*****************************************************

21 //** main code

22 //*****************************************************

23

24 //接收完单包数据后再开始读fifo,防止fifo为空时被读取

25 assign fifo_rd_req = aud_dac_req & rec_done_flag_d1;

26

27 //接收完单包数据后给出标志

28 always @(posedge eth_rx_clk or negedge rst_n) begin

29 if(rst_n == 1'b0)

30 rec_done_flag <= 1'b0;

31 else if(udp_rec_pkt_done)

32 rec_done_flag <= 1'b1;

33 end

34

35 //异步信号打拍处理

36 always @(posedge aud_bclk or negedge rst_n) begin

37 if(rst_n == 1'b0) begin

38 rec_done_flag_d0 <= 1'b0;

39 rec_done_flag_d1 <= 1'b0;

40 end

41 else begin

42 rec_done_flag_d0 <= rec_done_flag;

43 rec_done_flag_d1 <= rec_done_flag_d0;

44 end

45 end

46

47 //异步fifo

48 async_fifo_512x32b u_async_fifo(

49 .aclr (~rst_n),

50 .data (udp_rec_data),

51 .rdclk (aud_bclk),

52 .rdreq (fifo_rd_req),

53 .wrclk (eth_rx_clk),

54 .wrreq (udp_rec_en),

55 .q (dac_data),

56 .rdempty (),

57 .rdusedw (),

58 .wrfull ()

59 );

60

61 endmodule

在代码的第27行开始的always语句块中,当接收完单包数据之后,rec_done_flag(单包

数据接收完成后给出的标志)信号拉高;由于rec_done_flag信号对于aud_bclk时钟来说是异

步信号,因此该信号通过延时打拍的方式同步到aud_bclk时钟下。在代码的第25行,fifo必须

在rec_done_flag_d1为高电平之后,即接收完单包数据之后才开始读取数据,防止在fifo为空

时进行读操作。

下载验证

首先我们打开基于以太网的板对板音频互传实验工程,在工程所在的路径下打开

eth_audio_transmit/par文件夹,在里面找到“eth_audio_transmit.qpf”并双击打开。注意

工程所在的路径名只能由字母、数字以及下划线组成,不能出现中文、空格以及特殊字符等。

工程打开后如图 48.5.1所示:

ea76645d8d595a2f88903616255fc63c.png

图 48.5.1 基于以太网的板对板音频互传实验工程

然后将下载器一端连电脑,另一端与开发板上对应端口连接;将音频连接线的一端连接至电脑或手机的音频输出端口,另一端连接至其中一块开发板的WM8978的LINE_IN接口,并将耳

机连接至另一开发板的PHONE接口;网线的两端分别接在两个开发板上的以太网接口,最后连

接电源线并打开电源开关。

接下来我们下载程序,验证音频互传与播放的功能。工程打开后通过点击工具栏中的

“Programmer” 图 标 打 开 下 载 界 面 , 通 过 “Add File” 按钮选择

eth_audio_transmit/par/output_files目录下的“eth_audio_transmit.sof”文件。开发板

电源打开后,在程序下载界面点击“Hardware Setup”,在弹出的对话框中选择当前的硬件连

接为“USB-Blaster[USB-0]”。然后点击“Start”将工程编译完成后得到的sof文件下载到开

发板中,如图 48.5.所示:

702d17a777449875507924c9602f43ed.png

图 48.5.2 程序下载完成界面

程序下载完成后并且硬件连接无误的话,我们可以看到两块开发板上以太网接口的灯会不

停地闪烁,说明此时两块开发板正在互传音频。如果音频连接线的另一端已经连接至电脑或手

机的音频输出端口,此时打开音乐,就可以听到另一块开发板上喇叭播放的音乐。戴上耳机,

也能听到耳机播放的音乐,说明音频互传实验验证成功。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最新正点原子FPGA开发板及外围电路模块protel99原理图库PCB封装库+AD集成库, 3.5TFTLCD封装库.IntLib ATK-4.3' TFTLCD电容触摸屏模块_V1.2.IntLib ATK-4342 4.3寸RGB屏模块封装库.IntLib ATK-7016&7084 7寸RGB屏模块封装库.IntLib ATK-NEO-6M-V2.3.IntLib ATK-OV2640摄像头模块.IntLib ATK-OV5640摄像头模块封装库.IntLib ATK-SIM900A GSM模块封装库.IntLib MP3模块封装库.IntLib OLED模块封装库.IntLib PIONEER PIONEER.IntLib Library Component Count : 56 Name Description ---------------------------------------------------------------------------------------------------- 24C256 AMS1117 AP3216C ALS+PS Sensor AR101 单路电容触摸芯片 ATK-HC05 ATK-HC05 BAT BAT54C 双肖特基二极管 BEEP BUTTON C CAP CH340G USB2UART D 1N4148 DB9 DHT11 数字温湿度传感器 EP4CE6F17C8 Cyclone IV Family FPGA, 2V Core, 179 I/O Pins, 2 PLLs, 256-Pin FBGA, Speed Grade 8, Commercial Grade FPC-40 FPC-40P-0.5mm HEAD2 HR911105 HS0038 Header 16 Header, 16-Pin Header 24X2 Header, 24-Pin, Dual row Header 2X2 Header, 2-Pin, Dual row Header 3X2 Header, 3-Pin, Dual row Header 4 Header, 4-Pin Header 9X2 Header, 9-Pin, Dual row IS42S16160B 32MB SDRAM JTAG-10-FPGA KEY_M LED LEDSEG030-6 6位数码管,0.3寸,共阴,41*11*5.8mm L_SOP M25P16 16 Mb (x1) Automotive Serial NOR Flash Memory, 75 MHz, 2.7 to 3.6 V, 8-pin SO8 MAX3232 MAX3485 MIC MP2359 DC DC Step Down IC NRF24L01 PCF8563 时钟芯片 PCF8591 4路AD+1路DA芯片. PHONE_M PNP POW R RTL8201CP ETH PHY SMBJ TVS SN65HVD230D TEST-POINT 测试点 TFT_LCD TPAD ALIENTEK TPAD USB5 VGA WM8978 24bit ADC&DAC XTAL 普通晶振 XTAL_S 有源晶振 sd card
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值