一天一个设计实例-基于FPGA的模数转换器应用设计
基于FPGA的模数转换器应用设计
1.1.1八通道AD7606应用设计
7.3.1.1 AD7606简介
AD7606 是一款集成式 8 通道数据采集系统,片内集成输入放大器、过压保护电路、二阶模拟抗混叠滤波器、模拟多路复用器、 16 位 200 kSPS SAR ADC和一个数字滤波器。
图7‑10所示电路包括两个AD7606 器件,可以配置为使用 2.5 V内部基准电压源或 2.5 V外部基准电压源ADR421。如果REF SELECT引脚接逻辑高电平,则选择内部基准电压源。如果REF SELECT引脚接逻辑低电平,则选择外部基准电压源。
在电力线路测量和保护系统中,需要对多相输配电网络的大量电流和电压通道进行同步采样。这些应用中,通道数量从6 个到 64 个以上不等。AD7606 8 通道数据采集系统(DAS)集成 16 位双极性同步采样SAR ADC和片内过压保护功能,可大大简化信号调理电路,并减少器件数量、电路板面积和测量保护板的成本。高集成度使得每个AD7606 只需 9 个低值陶瓷去耦电容就能工作。
在测量和保护系统中,为了保持多相电力线网络的电流和电压通道之间的相位信息,必须具备同步采样能力。AD7606具有宽动态范围, 是捕获欠压/欠流和过压/过流状况的理想器件。输入电压范围可以通过引脚编程设置为±5 V 或±10 V。此电路笔记详细介绍针对采用多个AD7606 器件应用而推荐的印刷电路板(PCB)布局。该布局在通道间匹配和器件间匹配方面进行了优化,有助于简化高通道数系统的校准程序。当通道间匹配非常重要时,此电路可以使用 2.5 V内部基准电压源AD7606;而对于要求出色绝对精度的高通道数应用,此电路可以使用外部精密基准电压源ADR421,它具有高精度(B级:最大值±1 mV)、低漂移(B级:最大值 3 ppm/°C)、低噪声(典型值 1.75 μV p-p, 0.1 Hz至 10 Hz)等特性。低噪声及出色的稳定性和精度特性使得ADR421非常适合高精度转换应用。这两个器件相结合,能够实现业界前所未有的集成度、通道密度和精度。
图7‑10采用两个AD7606 8 通道DAS的 16 通道、 16 位数据采集系统
图7‑11 AD7606功能框图
图7‑12 引脚配置图
图7‑13 AD7606时序图
况的理想器件。输入电压范围可以通过引脚编程设置为±5 V 或±10 V。此电路笔记详细介绍针对采用多个AD7606 器件应用而推荐的印刷电路板(PCB)布局。该布局在通道间匹配和器件间匹配方面进行了优化,有助于简化高通道数系统的校准程序。当通道间匹配非常重要时,此电路可以使用 2.5 V内部基准电压源AD7606;而对于要求出色绝对精度的高通道数应用,此电路可以使用外部精密基准电压源ADR421,它具有高精度(B级:最大值±1 mV)、低漂移(B级:最大值 3 ppm/°C)、低噪声(典型值 1.75 μV p-p, 0.1 Hz至 10 Hz)等特性。低噪声及出色的稳定性和精度特性使得ADR421非常适合高精度转换应用。这两个器件相结合,能够实现业界前所未有的集成度、通道密度和精度。
AD7606 可以对所有 8 路的模拟输入通道进行同步采样。当两个 CONVST引脚(CONVSTA 和 CONVSTB)连在一起时, 所有通道同步采样。此共用CONVST 信号的上升沿启动对所有模拟输入通道的同步采样(V1 至 V8)。
AD7606 内置一个片内振荡器用于转换。所有 ADC 通道的转换时间为tCONV。BUSY 信号告知用户正在进行转换, 因此当施加 CONVST 上升沿时,BUSY 变为逻辑高电平, 在整个转换过程结束时变成低电平。BUSY 信号下降沿用来使所有八个采样保持放大器返回跟踪模式。BUSY 下降沿还表示,现在可以从并行总线 DB[15:0]读取 8 个通道的数据。
7.3.1.2 AD7606配置
在 AN706 8 通道的 AD 模块硬件电路设计中,我们对 AD7606 的 3 个配置Pin 脚通过加上拉或下拉电阻来设置 AD7606 的工作模式。
1. AD7606 这款芯片支持外部基准电压输入或内部基准电压。如果使用外部基准电压,芯片的 REFIN/REFOUT 需要外接一个 2.5V 的基准源。如果使用内部的基准电压。REFIN/REFOUT 引脚为 2.5V 的内部基准电压输出。REFSELECT 引脚用于选择内部基准电压或外部基准电压。在本模块中, 因为考虑到 AD7606 的内部基准电压的精度也非常高( 2.49V~2.505V),所以电路设计选择使用了内部的基准电压。
表7‑1 REF SELECT 引脚设置
Pin 脚名 |
设置电平 |
说明 |
REF SELECT |
高电平 |
使用内部的基准电压 2.5V |
2. AD7606 的 AD 转换数据采集可以采用并行模式或者串行模式,用户可以通过设置 PAR/SER/BYTE SEL 引脚电平来设置通信的模式。我们在设计的时候,选择并行模式读取 AD7606 的 AD 数据。
表7‑2 PAR/SER/BYTE SEL 引脚设置
Pin 脚名 |
设置电平 |
说明 |
PAR/SER/BYTE SEL |
低电平 |
选择并行接口 |
3. AD7606 的 AD 模拟信号的输入范围可以设置为±5V 或者是±10V,当设置± 5V 输入范围时,1LSB=152.58uV;当设置 ±10V 输入范围时,1LSB=305.175uV。用户可以通过设置 RANGE 引脚电平来设置模拟输入电压的范围。我们在设计的时候,选择±5V 的模拟电压输入范围。
表7‑3 模拟信号输入范围选择设置
Pin 脚名 |
设置电平 |
说明 |
RANGE |
低电平 |
模拟信号输入范围选择:±5V |
4. AD7606 内置一个可选的数字一阶 sinc 滤波器,在使用较低吞吐率或需要更高信噪比的应用中,应使用滤波器。数字滤波器的过采样倍率由过采样引脚 OS[2:0]控制。下表提供了用来选择不同过采样倍率的过采样位解码。
表7‑4 过采样位解码设置
在 AN706 模块的硬件设计中, OS[2:0] 已经引到外部的接口中,FPGA 或CPU 可以通过控制 OS[2:0]的管脚电平来选择是否使用滤波器,以达到更高的测量精度。
7.3.1.3 AD7606 AD转换
AD7606 的输出编码方式为二进制补码。所设计的码转换在连续 LSB 整数的中间(既 1/2LSB 和 3/2LSB)进行。AD7606 的 LSB 大小为 FSR/65536。
AD7606 的理想传递特性如下图所示:
图7‑14 理想传递特性
7.3.1.4 基于FPGA的AD7606应用设计
图7‑15 基于FPGA的AD7606应用设计建模图
上图中:
1. AD 数据采集程序:AD7606采集模块
根据 AD7606 的时序, 采样 8 路模拟信号 AD 转换后的 16bit 的数据。程序先发送 CONVSTAB 信号给 AD7606 启动 AD 数据转换,等待 Busy 信号为低后依次读取 AD 通道 1 到通道 8 的数据。
2. AD 数据的电压转换程序:电压转换模块
程序把从 ad7606.v 采集来的 16bit 的数据, Bit[15]转换为正负符号,Bit[14:0]先通过以下的公式转换成电压值,再把十六进制的电压值转换成 20 位BCD 码。
AD 电压换算(1 LSB) = 5V / 32758 = 0.15mV
3. 串口发送程序:串口发送模块
定时通过 uart 发送 8 路的电压数据到 PC, 串口的发送时钟通过 50Mhz 的分频得到,发送的波特率为 9600bps。
代码7‑1 AD 数据采集程序
1.`timescale 1ns / 1ps 2.////////////////////////////////////////////////////////////////////////////////// 3.// Module Name: ad7606 4.////////////////////////////////////////////////////////////////////////////////// 5.module ad7606( 6. input clk, //50mhz 7. input rst_n, 8. 9. input [15:0] ad_data, //ad7606 采样数据 10. input ad_busy, //ad7606 忙标志位 11. input first_data, //ad7606 第一个数据标志位 12. output [2:0] ad_os, //ad7606 过采样倍率选择 13. output reg ad_cs, //ad7606 AD cs 14. output reg ad_rd, //ad7606 AD data read 15. output reg ad_reset, //ad7606 AD reset 16. output reg ad_convstab, //ad7606 AD convert start 17. 18. output reg [15:0] ad_ch1, //AD第1通道的数据 19. output reg [15:0] ad_ch2, //AD第2通道的数据 20. output reg [15:0] ad_ch3, //AD第3通道的数据 21. output reg [15:0] ad_ch4, //AD第4通道的数据 22. output reg [15:0] ad_ch5, //AD第5通道的数据 23. output reg [15:0] ad_ch6, //AD第6通道的数据 24. output reg [15:0] ad_ch7, //AD第7通道的数据 25. output reg [15:0] ad_ch8 //AD第8通道的数据 26. 27. 28. 29. ); 30. 31. 32. 33.reg [15:0] cnt; 34.reg [5:0] i; 35.reg [3:0] state; 36. 37.parameter IDLE=4'd0; 38.parameter AD_CONV=4'd1; 39.parameter Wait_1=4'd2; 40.parameter Wait_busy=4'd3; 41.parameter READ_CH1=4'd4; 42.parameter READ_CH2=4'd5; 43.parameter READ_CH3=4'd6; 44.parameter READ_CH4=4'd7; 45.parameter READ_CH5=4'd8; 46.parameter READ_CH6=4'd9; 47.parameter READ_CH7=4'd10; 48.parameter READ_CH8=4'd11; 49.parameter READ_DONE=4'd12; 50. 51.assign ad_os=3'b000; 52. 53.//AD 复位电路 54.always@(posedge clk) 55. begin 56. if(cnt<16'hffff) begin 57. cnt<=cnt+1; 58. ad_reset<=1'b1; 59. end 60. else 61. ad_reset<=1'b0; 62. end 63. 64.always @(posedge clk) 65. begin 66. if (ad_reset==1'b1) begin 67. state<=IDLE; 68. ad_ch1<=0; 69. ad_ch2<=0; 70. ad_ch3<=0; 71. ad_ch4<=0; 72. ad_ch5<=0; 73. ad_ch6<=0; 74. ad_ch7<=0; 75. ad_ch8<=0; 76. ad_cs<=1'b1; 77. ad_rd<=1'b1; 78. ad_convstab<=1'b1; 79. i<=0; 80. end 81. else begin 82. case(state) 83. IDLE: begin 84. ad_cs<=1'b1; 85. ad_rd<=1'b1; 86. ad_convstab<=1'b1; 87. if(i==20) begin 88. i<=0; 89. state<=AD_CONV; 90. end 91. else 92. i<=i+1'b1; 93. end 94. AD_CONV: begin 95. if(i==2) begin //等待2个clock 96. i<=0; 97. state<=Wait_1; 98. ad_convstab<=1'b1; 99. end 100. else begin 101. i<=i+1'b1; 102. ad_convstab<=1'b0; //启动AD转换 103. end 104. end 105. Wait_1: begin 106. if(i==5) begin //等待5个clock, 等待busy信号为高 107. i<=0; 108. state<=Wait_busy; 109. end 110. else 111. i<=i+1'b1; 112. end 113. Wait_busy: begin 114. if(ad_busy==1'b0) begin //等待busy信号为低 115. i<=0; 116. state<=READ_CH1; 117. end 118. end 119. READ_CH1: begin 120. ad_cs<=1'b0; //cs信号有效 121. if(i==3) begin 122. ad_rd<=1'b1; 123. i<=0; 124. ad_ch1<=ad_data; //读CH1 125. state<=READ_CH2; 126. end 127. else begin 128. ad_rd<=1'b0; 129. i<=i+1'b1; 130. end 131. end 132. READ_CH2: begin 133. if(i==3) begin 134. ad_rd<=1'b1; 135. i<=0; 136. ad_ch2<=ad_data; //读CH2 137. state<=READ_CH3; 138. end 139. else begin 140. ad_rd<=1'b0; 141. i<=i+1'b1; 142. end 143. end 144. READ_CH3: begin 145. if(i==3) begin 146. ad_rd<=1'b1; 147. i<=0; 148. ad_ch3<=ad_data; //读CH3 149. state<=READ_CH4; 150. end 151. else begin 152. ad_rd<=1'b0; 153. i<=i+1'b1; 154. end 155. end 156. READ_CH4: begin 157. if(i==3) begin 158. ad_rd<=1'b1; 159. i<=0; 160. ad_ch4<=ad_data; //读CH4 161. state<=READ_CH5; 162. end 163. else begin 164. ad_rd<=1'b0; 165. i<=i+1'b1; 166. end 167. end 168. READ_CH5: begin 169. if(i==3) begin 170. ad_rd<=1'b1; 171. i<=0; 172. ad_ch5<=ad_data; //读CH5 173. state<=READ_CH6; 174. end 175. else begin 176. ad_rd<=1'b0; 177. i<=i+1'b1; 178. end 179. end 180. READ_CH6: begin 181. if(i==3) begin 182. ad_rd<=1'b1; 183. i<=0; 184. ad_ch6<=ad_data; //读CH6 185. state<=READ_CH7; 186. end 187. else begin 188. ad_rd<=1'b0; 189. i<=i+1'b1; 190. end 191. end 192. READ_CH7: begin 193. if(i==3) begin 194. ad_rd<=1'b1; 195. i<=0; 196. ad_ch7<=ad_data; //读CH7 197. state<=READ_CH8; 198. end 199. else begin 200. ad_rd<=1'b0; 201. i<=i+1'b1; 202. end 203. end 204. READ_CH8: begin 205. if(i==3) begin 206. ad_rd<=1'b1; 207. i<=0; 208. ad_ch8<=ad_data; //读CH8 209. state<=READ_DONE; 210. end 211. else begin 212. ad_rd<=1'b0; 213. i<=i+1'b1; 214. end 215. end 216. READ_DONE:begin 217. ad_rd<=1'b1; 218. ad_cs<=1'b1; 219. state<=IDLE; 220. end 221. default: state<=IDLE; 222. endcase 223. end 224. 225. end 226. 227.endmodule |
代码7‑2 AD 数据的电压转换程序代码
1.`timescale 1ns / 1ps 2.////////////////////////////////////////////////////////////////////////////////// 3.// Module Name: volt_cal 4.////////////////////////////////////////////////////////////////////////////////// 5.module volt_cal( 6. input clk, //50mhz 7. input ad_reset, 8. 9. input [15:0] ad_ch1, //AD第1通道的数据 10. input [15:0] ad_ch2, //AD第2通道的数据 11. input [15:0] ad_ch3, //AD第3通道的数据 12. input [15:0] ad_ch4, //AD第4通道的数据 13. input [15:0] ad_ch5, //AD第5通道的数据 14. input [15:0] ad_ch6, //AD第6通道的数据 15. input [15:0] ad_ch7, //AD第7通道的数据 16. input [15:0] ad_ch8, //AD第8通道的数据 17. 18. 19. output [19:0] ch1_dec, //AD第1通道的十进制电压数据 20. output [19:0] ch2_dec, //AD第1通道的十进制电压数据 21. output [19:0] ch3_dec, //AD第1通道的十进制电压数据 22. output [19:0] ch4_dec, //AD第1通道的十进制电压数据 23. output [19:0] ch5_dec, //AD第1通道的十进制电压数据 24. output [19:0] ch6_dec, //AD第1通道的十进制电压数据 25. output [19:0] ch7_dec, //AD第1通道的十进制电压数据 26. output [19:0] ch8_dec, //AD第1通道的十进制电压数据 27. 28. output reg [7:0] ch1_sig, //AD第1通道的数据正负字符 29. output reg [7:0] ch2_sig, //AD第2通道的数据正负字符 30. output reg [7:0] ch3_sig, //AD第1通道的数据正负字符 31. output reg [7:0] ch4_sig, //AD第2通道的数据正负字符 32. output reg [7:0] ch5_sig, //AD第1通道的数据正负字符 33. output reg [7:0] ch6_sig, //AD第2通道的数据正负字符 34. output reg [7:0] ch7_sig, //AD第1通道的数据正负字符 35. output reg [7:0] ch8_sig //AD第2通道的数据正负字符 36. 37. 38. ); 39. 40. 41.reg [15:0] ch1_reg; 42.reg [15:0] ch2_reg; 43.reg [15:0] ch3_reg; 44.reg [15:0] ch4_reg; 45.reg [15:0] ch5_reg; 46.reg [15:0] ch6_reg; 47.reg [15:0] ch7_reg; 48.reg [15:0] ch8_reg; 49. 50.reg [31:0] ch1_data_reg; 51.reg [31:0] ch2_data_reg; 52.reg [31:0] ch3_data_reg; 53.reg [31:0] ch4_data_reg; 54.reg [31:0] ch5_data_reg; 55.reg [31:0] ch6_data_reg; 56.reg [31:0] ch7_data_reg; 57.reg [31:0] ch8_data_reg; 58. 59.reg [31:0] ch1_vol; 60.reg [31:0] ch2_vol; 61.reg [31:0] ch3_vol; 62.reg [31:0] ch4_vol; 63.reg [31:0] ch5_vol; 64.reg [31:0] ch6_vol; 65.reg [31:0] ch7_vol; 66.reg [31:0] ch8_vol; 67. 68. 69.//AD 电压换算 70.always @(posedge clk) 71.begin 72. if(ad_reset == 1'b1) begin 73. ch1_reg<=0; 74. ch2_reg<=0; 75. ch3_reg<=0; 76. ch4_reg<=0; 77. ch5_reg<=0; 78. ch6_reg<=0; 79. ch7_reg<=0; 80. ch8_reg<=0; 81. end 82. else begin 83. //////////CH1数据///////////// 84. if(ad_ch1[15]==1'b1) begin //如果是负电压 85. ch1_reg<=16< span="">'hffff-ad_ch1+1'b1; 86. ch1_sig <= 45; //'-' asic码 87. end 88. else begin 89. ch1_reg<=ad_ch1; 90. ch1_sig<=43; //'+' asic码 91. end 92. 93. //////////CH2数据///////////// 94. if(ad_ch2[15]==1'b1) begin //如果是负电压 95. ch2_reg<=16< span="">'hffff-ad_ch2+1'b1; 96. ch2_sig <= 45; //'-' asic码 97. end 98. else begin 99. ch2_reg<=ad_ch2; 100. ch2_sig<=43; //'+' asic码 101. end 102. 103. //////////CH3数据///////////// 104. if(ad_ch3[15]==1'b1) begin //如果是负电压 105. ch3_reg<=16< span="">'hffff-ad_ch3+1'b1; 106. ch3_sig <= 45; //'-' asic码 107. end 108. else begin 109. ch3_reg<=ad_ch3; 110. ch3_sig<=43; //'+' asic码 111. end 112. 113. //////////CH4数据///////////// 114. if(ad_ch4[15]==1'b1) begin //如果是负电压 115. ch4_reg<=16< span="">'hffff-ad_ch4+1'b1; 116. ch4_sig <= 45; //'-' asic码 117. end 118. else begin 119. ch4_reg<=ad_ch4; 120. ch4_sig<=43; //'+' asic码 121. end 122. 123. //////////CH5数据///////////// 124. if(ad_ch5[15]==1'b1) begin //如果是负电压 125. ch5_reg<=16< span="">'hffff-ad_ch5+1'b1; 126. ch5_sig <= 45; //'-' asic码 127. end 128. else begin 129. ch5_reg<=ad_ch5; 130. ch5_sig<=43; //'+' asic码 131. end 132. 133. //////////CH6数据///////////// 134. if(ad_ch6[15]==1'b1) begin //如果是负电压 135. ch6_reg<=16< span="">'hffff-ad_ch6+1'b1; 136. ch6_sig <= 45; //'-' asic码 137. end 138. else begin 139. ch6_reg<=ad_ch6; 140. ch6_sig<=43; //'+' asic码 141. end 142. 143. //////////CH7数据///////////// 144. if(ad_ch7[15]==1'b1) begin //如果是负电压 145. ch7_reg<=16< span="">'hffff-ad_ch7+1'b1; 146. ch7_sig <= 45; //'-' asic码 147. end 148. else begin 149. ch7_reg<=ad_ch7; 150. ch7_sig<=43; //'+' asic码 151. end 152. 153. //////////CH8数据///////////// 154. if(ad_ch8[15]==1'b1) begin //如果是负电压 155. ch8_reg<=16< span="">'hffff-ad_ch8+1'b1; 156. ch8_sig <= 45; //'-' asic码 157. end 158. else begin 159. ch8_reg<=ad_ch8; 160. ch8_sig<=43; //'+' asic码 161. end 162. 163. end 164.end 165. 166. 167.//AD 电压换算(1 LSB = 5V / 32758 = 0.15mV 168.always @(posedge clk) 169.begin 170. if(ad_reset == 1'b1) begin 171. ch1_data_reg<=0; 172. ch2_data_reg<=0; 173. ch3_data_reg<=0; 174. ch4_data_reg<=0; 175. ch5_data_reg<=0; 176. ch6_data_reg<=0; 177. ch7_data_reg<=0; 178. ch8_data_reg<=0; 179. ch1_vol<=0; 180. ch2_vol<=0; 181. ch3_vol<=0; 182. ch4_vol<=0; 183. ch5_vol<=0; 184. ch6_vol<=0; 185. ch7_vol<=0; 186. ch8_vol<=0; 187. end 188. else begin 189. ch1_data_reg<=ch1_reg * 50000; 190. ch2_data_reg<=ch2_reg * 50000; 191. ch3_data_reg<=ch3_reg * 50000; 192. ch4_data_reg<=ch4_reg * 50000; 193. ch5_data_reg<=ch5_reg * 50000; 194. ch6_data_reg<=ch6_reg * 50000; 195. ch7_data_reg<=ch7_reg * 50000; 196. ch8_data_reg<=ch8_reg * 50000; 197. 198. ch1_vol<=ch1_data_reg>>15; 199. ch2_vol<=ch2_data_reg>>15; 200. ch3_vol<=ch3_data_reg>>15; 201. ch4_vol<=ch4_data_reg>>15; 202. ch5_vol<=ch5_data_reg>>15; 203. ch6_vol<=ch6_data_reg>>15; 204. ch7_vol<=ch7_data_reg>>15; 205. ch8_vol<=ch8_data_reg>>15; 206. end 207. end 208. 209.//16进制转化为十进制的 210.bcd bcd1_ist( 211. .hex (ch1_vol[15:0]), 212. .dec (ch1_dec), 213. .clk (clk) 214. ); 215. 216.//16进制转化为十进制的 217.bcd bcd2_ist( 218. .hex (ch2_vol[15:0]), 219. .dec (ch2_dec), 220. .clk (clk) 221. ); 222. 223.//16进制转化为十进制的 224.bcd bcd3_ist( 225. .hex (ch3_vol[15:0]), 226. .dec (ch3_dec), 227. .clk (clk) 228. ); 229. 230.//16进制转化为十进制的 231.bcd bcd4_ist( 232. .hex (ch4_vol[15:0]), 233. .dec (ch4_dec), 234. .clk (clk) 235. ); 236. 237.//16进制转化为十进制的 238.bcd bcd5_ist( 239. .hex (ch5_vol[15:0]), 240. .dec (ch5_dec), 241. .clk (clk) 242. ); 243. 244.//16进制转化为十进制的 245.bcd bcd6_ist( 246. .hex (ch6_vol[15:0]), 247. .dec (ch6_dec), 248. .clk (clk) 249. ); 250. 251.//16进制转化为十进制的 252.bcd bcd7_ist( 253. .hex (ch7_vol[15:0]), 254. .dec (ch7_dec), 255. .clk (clk) 256. ); 257. 258.//16进制转化为十进制的 259.bcd bcd8_ist( 260. .hex (ch8_vol[15:0]), 261. .dec (ch8_dec), 262. .clk (clk) 263. ); 264. 265. 266.endmodule |
在这段代码中还调用了十六进制的电压值转换成 20 位BCD 码的《函数》。如下:
代码7‑3 十六进制的电压值转换成 20 位BCD 码代码
1.module bcd(clk, 2. hex, 3. dec); 4. 5.input clk; 6.input [16:0] hex; 7.output [19:0] dec; 8. 9.wire [15:0] rrhex; 10.reg [3:0] rhex[3:0]; 11. 12.reg [18:0] rhexd; 13.reg [13:0] rhexc; 14.reg [9:0] rhexb; 15.reg [3:0] rhexa; 16. 17.reg [5:0] resa,resb,resc,resd; 18.reg [3:0] rese; 19. 20.assign rrhex = hex[16] ? ~hex[15:0]+1'b1 : hex[15:0]; //去符号 21.assign dec = {rese,resd[3:0],resc[3:0],resb[3:0],resa[3:0]}; 22. 23.always@(posedge clk) //第一级寄存器 24.begin 25. rhex[3] <= rrhex[15:12]; 26. rhex[2] <= rrhex[11:8]; 27. rhex[1] <= rrhex[7:4]; 28. rhex[0] <= rrhex[3:0]; 29.end 30. 31.always@(posedge clk) //高4bit译码 32.begin 33. case(rhex[3]) 34. 4'h0: rhexd <= 19'h00000; 35. 4'h1: rhexd <= 19'h04096; //0x1000 -> 4096 (十进制) 36. 4'h2: rhexd <= 19'h08192; //0x2000 -> 8192 (十进制) 37. 4'h3: rhexd <= 19'h12288; //0x3000 -> 12288 (十进制) 38. 4'h4: rhexd <= 19'h16384; //0x4000 -> 16384 (十进制) 39. 4'h5: rhexd <= 19'h20480; //0x5000 -> 20480 (十进制) 40. 4'h6: rhexd <= 19'h24576; //0x6000 -> 24576 (十进制) 41. 4'h7: rhexd <= 19'h28672; //0x7000 -> 28672 (十进制) 42. 4'h8: rhexd <= 19'h32768; //0x8000 -> 32768 (十进制) 43. 4'h9: rhexd <= 19'h36864; //0x9000 -> 36864 (十进制) 44. 4'ha: rhexd <= 19'h40960; //0xa000 -> 40960 (十进制) 45. 4'hb: rhexd <= 19'h45056; //0xb000 -> 45056 (十进制) 46. 4'hc: rhexd <= 19'h49152; //0xc000 -> 49152 (十进制) 47. 4'hd: rhexd <= 19'h53248; //0xd000 -> 53248 (十进制) 48. 4'he: rhexd <= 19'h57344; //0xe000 -> 57344 (十进制) 49. 4'hf: rhexd <= 19'h61440; //0xf000 -> 61440 (十进制) 50. default: rhexd <= 19'h00000; 51. endcase 52.end 53. 54.always@(posedge clk) //次高4bit译码 55.begin 56. case(rhex[2]) 57. 4'h0: rhexc <= 14'h0000; 58. 4'h1: rhexc <= 14'h0256; //0x100 -> 256 (十进制) 59. 4'h2: rhexc <= 14'h0512; //0x200 -> 512 (十进制) 60. 4'h3: rhexc <= 14'h0768; //0x300 -> 768 (十进制) 61. 4'h4: rhexc <= 14'h1024; //0x400 -> 1024 (十进制) 62. 4'h5: rhexc <= 14'h1280; //0x500 -> 1280 (十进制) 63. 4'h6: rhexc <= 14'h1536; //0x600 -> 1536 (十进制) 64. 4'h7: rhexc <= 14'h1792; //0x700 -> 1792 (十进制) 65. 4'h8: rhexc <= 14'h2048; //0x800 -> 2048 (十进制) 66. 4'h9: rhexc <= 14'h2304; //0x900 -> 2304 (十进制) 67. 4'ha: rhexc <= 14'h2560; //0xA00 -> 2560 (十进制) 68. 4'hb: rhexc <= 14'h2816; //0xB00 -> 2816 (十进制) 69. 4'hc: rhexc <= 14'h3072; //0xC00 -> 3072 (十进制) 70. 4'hd: rhexc <= 14'h3328; //0xD00 -> 3328 (十进制) 71. 4'he: rhexc <= 14'h3584; //0xE00 -> 3584 (十进制) 72. 4'hf: rhexc <= 14'h3840; //0xF00 -> 3840 (十进制) 73. default: rhexc <= 14'h0000; 74. endcase 75.end 76. 77.always@(posedge clk) 78.begin 79. case(rhex[1]) 80. 4'h0: rhexb <= 10'h000; 81. 4'h1: rhexb <= 10'h016; 82. 4'h2: rhexb <= 10'h032; 83. 4'h3: rhexb <= 10'h048; 84. 4'h4: rhexb <= 10'h064; 85. 4'h5: rhexb <= 10'h080; 86. 4'h6: rhexb <= 10'h096; 87. 4'h7: rhexb <= 10'h112; 88. 4'h8: rhexb <= 10'h128; 89. 4'h9: rhexb <= 10'h144; 90. 4'ha: rhexb <= 10'h160; 91. 4'hb: rhexb <= 10'h176; 92. 4'hc: rhexb <= 10'h192; 93. 4'hd: rhexb <= 10'h208; 94. 4'he: rhexb <= 10'h224; 95. 4'hf: rhexb <= 10'h240; 96. default: rhexb <= 10'h000; 97. endcase 98.end 99. 100.always@(posedge clk) 101.begin 102. rhexa <= rhex[0]; 103.end 104. 105.always@(posedge clk) //每个结果按同级单个bcd码相加,高一级的bcd码要加上低一级的进位,也就是高出4位的部分 106.begin 107. resa = addbcd4(rhexa[3:0],rhexb[3:0],rhexc[3:0], rhexd[3:0]); 108. resb = addbcd4(resa[5:4], rhexb[7:4],rhexc[7:4], rhexd[7:4]); 109. resc = addbcd4(resb[5:4], rhexb[9:8],rhexc[11:8], rhexd[11:8]); 110. resd = addbcd4(resc[5:4], 4'h0, rhexc[13:12],rhexd[15:12]); 111. rese = resd[5:4] + rhexd[18:16]; 112.end 113. 114.function [5:0] addbcd4; 115.input [3:0] add1,add2,add3,add4; 116.begin 117. addbcd4 = add1 + add2 + add3 + add4; 118. if(addbcd4 > 6'h1d) //>29 最低有一个可能出现0xf,但由二进制转换而来的数在这里不会出现大于40的情况 119. addbcd4 = addbcd4 + 5'h12; 120. else if(addbcd4 > 5'h13) //>19对结果加12 121. addbcd4 = addbcd4 + 4'hc; 122. else if(addbcd4 > 4'h9) //>9对结果加6 123. addbcd4 = addbcd4 + 4'h6; 124.end 125.endfunction 126. 127. 128. 129. 130.endmodule |
代码7‑4 串口发送程序(一)
1.`timescale 1ns / 1ps 2.////////////////////////////////////////////////////////////////////////////////// 3.////////////////////////////////////////////////////////////////////////////////// 4.module uart( 5. input clk50, //50Mhz clock 6. input reset_n, 7. 8. input [19:0] ch1_dec, 9. input [19:0] ch2_dec, 10. input [19:0] ch3_dec, 11. input [19:0] ch4_dec, 12. input [19:0] ch5_dec, 13. input [19:0] ch6_dec, 14. input [19:0] ch7_dec, 15. input [19:0] ch8_dec, 16. 17. input [7:0] ch1_sig, 18. input [7:0] ch2_sig, 19. input [7:0] ch3_sig, 20. input [7:0] ch4_sig, 21. input [7:0] ch5_sig, 22. input [7:0] ch6_sig, 23. input [7:0] ch7_sig, 24. input [7:0] ch8_sig, 25. 26. 27. output tx 28. ); 29. 30. 31./********************************************/ 32.//存储待发送的串口信息 33./********************************************/ 34.reg [7:0] uart_ad [113:0]; //存储发送的ASIC字符 35. 36.always @(clk) 37.begin //定义发送的字符 38. if(uart_stat==3'b000) begin 39. uart_ad[0]<=65; //存储字符 A 40. uart_ad[1]<=68; //存储字符 D 41. uart_ad[2]<=49; //存储字符 1 42. uart_ad[3]<=58; //存储字符 : 43. uart_ad[4]<=ch1_sig; //存储字符 正负 44. uart_ad[5]<=ch1_dec[19:16] + 48; //存储字符 个位 45. uart_ad[6]<=46; //存储字符 . 46. uart_ad[7]<=ch1_dec[15:12] + 48; //存储字符 小数点后一位 47. uart_ad[8]<=ch1_dec[11:8] + 48; //存储字符 小数点后二位 48. uart_ad[9]<=ch1_dec[7:4] + 48; //存储字符 小数点后三位 49. uart_ad[10]<=ch1_dec[3:0] + 48; //存储字符 小数点后四位 50. uart_ad[11]<=86; //存储字符 V 51. uart_ad[12]<=32; //存储字符 空格 52. uart_ad[13]<=32; //存储字符 空格 53. 54. uart_ad[14]<=65; //存储字符 A 55. uart_ad[15]<=68; //存储字符 D 56. uart_ad[16]<=50; //存储字符 2 57. uart_ad[17]<=58; //存储字符 : 58. uart_ad[18]<=ch2_sig; //存储字符 正负 59. uart_ad[19]<=ch2_dec[19:16] + 48; //存储字符 个位 60. uart_ad[20]<=46; //存储字符 . 61. uart_ad[21]<=ch2_dec[15:12] + 48; //存储字符 小数点后一位 62. uart_ad[22]<=ch2_dec[11:8] + 48; //存储字符 小数点后二位 63. uart_ad[23]<=ch2_dec[7:4] + 48; //存储字符 小数点后三位 64. uart_ad[24]<=ch2_dec[3:0] + 48; //存储字符 小数点后四位 65. uart_ad[25]<=86; //存储字符 V 66. uart_ad[26]<=32; //存储字符 空格 67. uart_ad[27]<=32; //存储字符 空格 68. 69. uart_ad[28]<=65; //存储字符 A 70. uart_ad[29]<=68; //存储字符 D 71. uart_ad[30]<=51; //存储字符 3 72. uart_ad[31]<=58; //存储字符 : 73. uart_ad[32]<=ch3_sig; //存储字符 正负 74. uart_ad[33]<=ch3_dec[19:16] + 48; //存储字符 个位 75. uart_ad[34]<=46; //存储字符 . 76. uart_ad[35]<=ch3_dec[15:12] + 48; //存储字符 小数点后一位 77. uart_ad[36]<=ch3_dec[11:8] + 48; //存储字符 小数点后二位 78. uart_ad[37]<=ch3_dec[7:4] + 48; //存储字符 小数点后三位 79. uart_ad[38]<=ch3_dec[3:0] + 48; //存储字符 小数点后四位 80. uart_ad[39]<=86; //存储字符 V 81. uart_ad[40]<=32; //存储字符 空格 82. uart_ad[41]<=32; //存储字符 空格 83. 84. uart_ad[42]<=65; //存储字符 A 85. uart_ad[43]<=68; //存储字符 D 86. uart_ad[44]<=52; //存储字符 4 87. uart_ad[45]<=58; //存储字符 : 88. uart_ad[46]<=ch4_sig; //存储字符 正负 89. uart_ad[47]<=ch4_dec[19:16] + 48; //存储字符 个位 90. uart_ad[48]<=46; //存储字符 . 91. uart_ad[49]<=ch4_dec[15:12] + 48; //存储字符 小数点后一位 92. uart_ad[50]<=ch4_dec[11:8] + 48; //存储字符 小数点后二位 93. uart_ad[51]<=ch4_dec[7:4] + 48; //存储字符 小数点后三位 94. uart_ad[52]<=ch4_dec[3:0] + 48; //存储字符 小数点后四位 95. uart_ad[53]<=86; //存储字符 V 96. uart_ad[54]<=32; //存储字符 空格 97. uart_ad[55]<=32; //存储字符 空格 98. 99. uart_ad[56]<=65; //存储字符 A 100. uart_ad[57]<=68; //存储字符 D 101. uart_ad[58]<=53; //存储字符 5 102. uart_ad[59]<=58; //存储字符 : 103. uart_ad[60]<=ch5_sig; //存储字符 正负 104. uart_ad[61]<=ch5_dec[19:16] + 48; //存储字符 个位 105. uart_ad[62]<=46; //存储字符 . 106. uart_ad[63]<=ch5_dec[15:12] + 48; //存储字符 小数点后一位 107. uart_ad[64]<=ch5_dec[11:8] + 48; //存储字符 小数点后二位 108. uart_ad[65]<=ch5_dec[7:4] + 48; //存储字符 小数点后三位 109. uart_ad[66]<=ch5_dec[3:0] + 48; //存储字符 小数点后四位 110. uart_ad[67]<=86; //存储字符 V 111. uart_ad[68]<=32; //存储字符 空格 112. uart_ad[69]<=32; //存储字符 空格 113. 114. uart_ad[70]<=65; //存储字符 A 115. uart_ad[71]<=68; //存储字符 D 116. uart_ad[72]<=54; //存储字符 6 117. uart_ad[73]<=58; //存储字符 : 118. uart_ad[74]<=ch6_sig; //存储字符 正负 119. uart_ad[75]<=ch6_dec[19:16] + 48; //存储字符 个位 120. uart_ad[76]<=46; //存储字符 . 121. uart_ad[77]<=ch6_dec[15:12] + 48; //存储字符 小数点后一位 122. uart_ad[78]<=ch6_dec[11:8] + 48; //存储字符 小数点后二位 123. uart_ad[79]<=ch6_dec[7:4] + 48; //存储字符 小数点后三位 124. uart_ad[80]<=ch6_dec[3:0] + 48; //存储字符 小数点后四位 125. uart_ad[81]<=86; //存储字符 V 126. uart_ad[82]<=32; //存储字符 空格 127. uart_ad[83]<=32; //存储字符 空格 128. 129. uart_ad[84]<=65; //存储字符 A 130. uart_ad[85]<=68; //存储字符 D 131. uart_ad[86]<=55; //存储字符 7 132. uart_ad[87]<=58; //存储字符 : 133. uart_ad[88]<=ch7_sig; //存储字符 正负 134. uart_ad[89]<=ch7_dec[19:16] + 48; //存储字符 个位 135. uart_ad[90]<=46; //存储字符 . 136. uart_ad[91]<=ch7_dec[15:12] + 48; //存储字符 小数点后一位 137. uart_ad[92]<=ch7_dec[11:8] + 48; //存储字符 小数点后二位 138. uart_ad[93]<=ch7_dec[7:4] + 48; //存储字符 小数点后三位 139. uart_ad[94]<=ch7_dec[3:0] + 48; //存储字符 小数点后四位 140. uart_ad[95]<=86; //存储字符 V 141. uart_ad[96]<=32; //存储字符 空格 142. uart_ad[97]<=32; //存储字符 空格 143. 144. uart_ad[98]<=65; //存储字符 A 145. uart_ad[99]<=68; //存储字符 D 146. uart_ad[100]<=56; //存储字符 8 147. uart_ad[101]<=58; //存储字符 : 148. uart_ad[102]<=ch8_sig; //存储字符 正负 149. uart_ad[103]<=ch8_dec[19:16] + 48; //存储字符 个位 150. uart_ad[104]<=46; //存储字符 . 151. uart_ad[105]<=ch8_dec[15:12] + 48; //存储字符 小数点后一位 152. uart_ad[106]<=ch8_dec[11:8] + 48; //存储字符 小数点后二位 153. uart_ad[107]<=ch8_dec[7:4] + 48; //存储字符 小数点后三位 154. uart_ad[108]<=ch8_dec[3:0] + 48; //存储字符 小数点后四位 155. uart_ad[109]<=86; //存储字符 V 156. uart_ad[110]<=32; //存储字符 空格 157. uart_ad[111]<=32; //存储字符 空格 158. 159. uart_ad[112]<=10; //换行符 160. uart_ad[113]<=13; //回车符 161. end 162.end 163. 164./********************************************/ 165.//串口发送时间字符串 166./********************************************/ 167.reg [15:0] uart_cnt; 168.reg [2:0] uart_stat; 169. 170.reg [7:0] txdata; //串口发送字符 171.reg wrsig; //串口发送有效信号 172. 173.reg [8:0] k; 174. 175.reg [15:0] Time_wait; 176. 177.always @(posedge clk ) 178.begin 179. if(!reset_n) begin 180. uart_cnt<=0; 181. uart_stat<=3'b000; 182. k<=0; 183. end 184. else begin 185. case(uart_stat) 186. 3'b000: begin 187. if (Time_wait == 16'hffff) begin //如果秒数据有变化 188. uart_stat<=3'b001; 189. Time_wait<=0; 190. end 191. else begin 192. uart_stat<=3'b000; 193. Time_wait<=Time_wait + 1'b1; 194. end 195. end 196. 3'b001: begin 197. if (k == 113 ) begin //发送第112个字符 198. if(uart_cnt ==0) begin 199. txdata <= uart_ad[113]; 200. uart_cnt <= uart_cnt + 1'b1; 201. wrsig <= 1'b1; 202. end 203. else if(uart_cnt ==254) begin 204. uart_cnt <= 0; 205. wrsig <= 1'b0; 206. uart_stat <= 3'b010; 207. k <= 0; 208. end 209. else begin 210. uart_cnt <= uart_cnt + 1'b1; 211. wrsig <= 1'b0; 212. end 213. end 214. else begin //发送前111个字符 215. if(uart_cnt ==0) begin 216. txdata <= uart_ad[k]; 217. uart_cnt <= uart_cnt + 1'b1; 218. wrsig <= 1'b1; 219. end 220. else if(uart_cnt ==254) begin 221. uart_cnt <= 0; 222. wrsig <= 1'b0; 223. k <= k + 1'b1; 224. end 225. else begin 226. uart_cnt <= uart_cnt + 1'b1; 227. wrsig <= 1'b0; 228. end 229. end 230. end 231. 3'b010: begin //发送finish 232. uart_stat <= 3'b000; 233. end 234. default:uart_stat <= 3'b000; 235. endcase 236. end 237.end 238. 239./**********产生串口时钟***********/ 240.clkdiv u0 ( 241. .clk50 (clk50), 242. .clkout (clk) //串口发送时钟 243. ); 244. 245./*************串口发送程序************/ 246.uarttx u1 ( 247. .clk (clk), 248. .datain (txdata), 249. .wrsig (wrsig), 250. .idle (idle), 251. .tx (tx) 252. ); 253. 254. 255. 256.endmodule |
代码7‑5 串口发送程序(二)
1.`timescale 1ns / 1ps 2.////////////////////////////////////////////////////////////////////////////////// 3.// Module Name: uarttx // 4.////////////////////////////////////////////////////////////////////////////////// 5.module uarttx(clk, datain, wrsig, idle, tx); 6.input clk; //UART时钟 7.input [7:0] datain; //需要发送的数据 8.input wrsig; //发送命令,上升沿有效 9.output idle; //线路状态指示,高为线路忙,低为线路空闲 10.output tx; //发送数据信号 11.reg idle, tx; 12.reg send; 13.reg wrsigbuf, wrsigrise; 14.reg presult; 15.reg[7:0] cnt; //计数器 16.parameter paritymode = 1'b0; 17. 18.//检测发送命令是否有效 19.always @(posedge clk) 20.begin 21. wrsigbuf <= wrsig; 22. wrsigrise <= (~wrsigbuf) & wrsig; 23.end 24. 25.always @(posedge clk) 26.begin 27. if (wrsigrise && (~idle)) //当发送命令有效且线路为空闲时,启动新的数据发送进程 28. begin 29. send <= 1'b1; 30. end 31. else if(cnt == 8'd168) //一帧资料发送结束 32. begin 33. send <= 1'b0; 34. end 35.end 36. 37.always @(posedge clk) 38.begin 39. if(send == 1'b1) begin 40. case(cnt) //产生起始位 41. 8'd0: begin 42. tx <= 1'b0; 43. idle <= 1'b1; 44. cnt <= cnt + 8'd1; 45. end 46. 8'd16: begin 47. tx <= datain[0]; //发送数据0位 48. presult <= datain[0]^paritymode; 49. idle <= 1'b1; 50. cnt <= cnt + 8'd1; 51. end 52. 8'd32: begin 53. tx <= datain[1]; //发送数据1位 54. presult <= datain[1]^presult; 55. idle <= 1'b1; 56. cnt <= cnt + 8'd1; 57. end 58. 8'd48: begin 59. tx <= datain[2]; //发送数据2位 60. presult <= datain[2]^presult; 61. idle <= 1'b1; 62. cnt <= cnt + 8'd1; 63. end 64. 8'd64: begin 65. tx <= datain[3]; //发送数据3位 66. presult <= datain[3]^presult; 67. idle <= 1'b1; 68. cnt <= cnt + 8'd1; 69. end 70. 8'd80: begin 71. tx <= datain[4]; //发送数据4位 72. presult <= datain[4]^presult; 73. idle <= 1'b1; 74. cnt <= cnt + 8'd1; 75. end 76. 8'd96: begin 77. tx <= datain[5]; //发送数据5位 78. presult <= datain[5]^presult; 79. idle <= 1'b1; 80. cnt <= cnt + 8'd1; 81. end 82. 8'd112: begin 83. tx <= datain[6]; //发送数据6位 84. presult <= datain[6]^presult; 85. idle <= 1'b1; 86. cnt <= cnt + 8'd1; 87. end 88. 8'd128: begin 89. tx <= datain[7]; //发送数据7位 90. presult <= datain[7]^presult; 91. idle <= 1'b1; 92. cnt <= cnt + 8'd1; 93. end 94. 8'd144: begin 95. tx <= presult; //发送奇偶校验位 96. presult <= datain[0]^paritymode; 97. idle <= 1'b1; 98. cnt <= cnt + 8'd1; 99. end 100. 8'd160: begin 101. tx <= 1'b1; //发送停止位 102. idle <= 1'b1; 103. cnt <= cnt + 8'd1; 104. end 105. 8'd168: begin 106. tx <= 1'b1; 107. idle <= 1'b0; //一帧资料发送结束 108. cnt <= cnt + 8'd1; 109. end 110. default: begin 111. cnt <= cnt + 8'd1; 112. end 113. endcase 114. end 115. else begin 116. tx <= 1'b1; 117. cnt <= 8'd0; 118. idle <= 1'b0; 119. end 120.end 121.endmodule |
最后就是将上诉代码进行封装,封装后的程序如下:
代码7‑6 封装后的代码
1.`timescale 1ns / 1ps 2.////////////////////////////////////////////////////////////////////////////////// 3.// Module Name: ad706_test 4.////////////////////////////////////////////////////////////////////////////////// 5.module ad706_test( 6. input clk, //50mhz 7. //input rst_n, 8. 9. input [15:0] ad_data, //ad7606 采样数据 10. input ad_busy, //ad7606 忙标志位 11. input first_data, //ad7606 第一个数据标志位 12. output [2:0] ad_os, //ad7606 过采样倍率选择 13. output ad_cs, //ad7606 AD cs 14. output ad_rd, //ad7606 AD data read 15. output ad_reset, //ad7606 AD reset 16. output ad_convstab, //ad7606 AD convert start 17. 18. input rx, 19. output tx 20. 21. 22. ); 23. 24. 25.wire [15:0] ad_ch1; 26.wire [15:0] ad_ch2; 27.wire [15:0] ad_ch3; 28.wire [15:0] ad_ch4; 29.wire [15:0] ad_ch5; 30.wire [15:0] ad_ch6; 31.wire [15:0] ad_ch7; 32.wire [15:0] ad_ch8; 33. 34.wire [19:0] ch1_dec; 35.wire [19:0] ch2_dec; 36.wire [19:0] ch3_dec; 37.wire [19:0] ch4_dec; 38.wire [19:0] ch5_dec; 39.wire [19:0] ch6_dec; 40.wire [19:0] ch7_dec; 41.wire [19:0] ch8_dec; 42. 43.wire [7:0] ch1_sig; 44.wire [7:0] ch2_sig; 45.wire [7:0] ch3_sig; 46.wire [7:0] ch4_sig; 47.wire [7:0] ch5_sig; 48.wire [7:0] ch6_sig; 49.wire [7:0] ch7_sig; 50.wire [7:0] ch8_sig; 51. 52.wire rst_n=1'b1; 53. 54.ad7606 u1( 55. .clk (clk), 56. .rst_n (rst_n), 57. .ad_data (ad_data), 58. .ad_busy (ad_busy), 59. .first_data (first_data), 60. .ad_os (ad_os), 61. .ad_cs (ad_cs), 62. .ad_rd (ad_rd), 63. .ad_reset (ad_reset), 64. .ad_convstab (ad_convstab), 65. .ad_ch1 (ad_ch1), //ch1 ad data 16bit 66. .ad_ch2 (ad_ch2), //ch2 ad data 16bit 67. .ad_ch3 (ad_ch3), //ch3 ad data 16bit 68. .ad_ch4 (ad_ch4), //ch4 ad data 16bit 69. .ad_ch5 (ad_ch5), //ch5 ad data 16bit 70. .ad_ch6 (ad_ch6), //ch6 ad data 16bit 71. .ad_ch7 (ad_ch7), //ch7 ad data 16bit 72. .ad_ch8 (ad_ch8) //ch8 ad data 16bit 73. 74. 75. ); 76. 77./**********电压转换程序***********/ 78.volt_cal u2( 79. .clk (clk), 80. .ad_reset (ad_reset), 81. .ad_ch1 (ad_ch1), //ch1 ad data 16bit (input) 82. .ad_ch2 (ad_ch2), //ch2 ad data 16bit (input) 83. .ad_ch3 (ad_ch3), //ch3 ad data 16bit (input) 84. .ad_ch4 (ad_ch4), //ch4 ad data 16bit (input) 85. .ad_ch5 (ad_ch5), //ch5 ad data 16bit (input) 86. .ad_ch6 (ad_ch6), //ch6 ad data 16bit (input) 87. .ad_ch7 (ad_ch7), //ch7 ad data 16bit (input) 88. .ad_ch8 (ad_ch8), //ch8 ad data 16bit (input) 89. 90. .ch1_dec (ch1_dec), //ch1 ad voltage (output) 91. .ch2_dec (ch2_dec), //ch2 ad voltage (output) 92. .ch3_dec (ch3_dec), //ch3 ad voltage (output) 93. .ch4_dec (ch4_dec), //ch4 ad voltage (output) 94. .ch5_dec (ch5_dec), //ch5 ad voltage (output) 95. .ch6_dec (ch6_dec), //ch6 ad voltage (output) 96. .ch7_dec (ch7_dec), //ch7 ad voltage (output) 97. .ch8_dec (ch8_dec), //ch8 ad voltage (output) 98. 99. .ch1_sig (ch1_sig), //ch1 ad 正负 (output) 100. .ch2_sig (ch2_sig), //ch2 ad 正负 (output) 101. .ch3_sig (ch3_sig), //ch3 ad 正负 (output) 102. .ch4_sig (ch4_sig), //ch4 ad 正负 (output) 103. .ch5_sig (ch5_sig), //ch5 ad 正负 (output) 104. .ch6_sig (ch6_sig), //ch6 ad 正负 (output) 105. .ch7_sig (ch7_sig), //ch7 ad 正负 (output) 106. .ch8_sig (ch8_sig) //ch8 ad 正负 (output) 107. 108. ); 109. 110./**********AD数据Uart串口发送程序***********/ 111.uart u3( 112. .clk50 (clk), 113. .reset_n (rst_n), 114. 115. .ch1_dec (ch1_dec), //ad1 BCD voltage 116. .ch2_dec (ch2_dec), //ad2 BCD voltage 117. .ch3_dec (ch3_dec), //ad3 BCD voltage 118. .ch4_dec (ch4_dec), //ad4 BCD voltage 119. .ch5_dec (ch5_dec), //ad5 BCD voltage 120. .ch6_dec (ch6_dec), //ad6 BCD voltage 121. .ch7_dec (ch7_dec), //ad7 BCD voltage 122. .ch8_dec (ch8_dec), //ad8 BCD voltage 123. 124. .ch1_sig (ch1_sig), //ch1 ad 正负 125. .ch2_sig (ch2_sig), //ch2 ad 正负 126. .ch3_sig (ch3_sig), //ch3 ad 正负 127. .ch4_sig (ch4_sig), //ch4 ad 正负 128. .ch5_sig (ch5_sig), //ch5 ad 正负 129. .ch6_sig (ch6_sig), //ch6 ad 正负 130. .ch7_sig (ch7_sig), //ch7 ad 正负 131. .ch8_sig (ch8_sig), //ch8 ad 正负 132. 133. .tx (tx) 134. 135. 136. ); 137. 138. 139. 140.endmodule |
上诉代码在进行封装时,参考图7‑15,将上诉代码进行综合,综合后的电路如下:
图7‑16 综合后的RTL电路
将程序下载到 FPGA 中。打开串口调试助手工具,设置串口的通信波特率如下。
图7‑17 串口上位机设置
串口通信里会出现 AN706 AD 模块的8路信号输入的电压值。
图7‑18 串口助手接收的8通道数据
以上的数据为8路没有信号输入的数据,因为 AD 信号输入处于悬空的状态,AD 转换输出的数据为 1.75V 左右。
通过外加电压和高精度的电压表的测量比较, AD706 的实际测量精度在-5V~+5V电压输入范围之内高达 0.5mV 以内。
下表为我们8个通道对四个模拟电压的测试结果,第一列基准电压为高精度数字万用表测量的数据,后面8列为 AN706 的 AD 模块测量的结果。
表7‑5 测量精度对比
在本测试例程,尚未使用过采样倍率使能过滤器来提高 AD 的精度,对于想进一步提高采样的精度的用户而对采样的速度要求不高的情况下,可以在程序里采用设置过采样倍率的方法。