1. 拿到板子在,做工很好,属于GX系列,GX应该是高速收发器
2. 去探究下GX是什么用途,大约有6个型号,这个板子是5CGXFX5,有77 LE逻辑单元,这个收发器不知道是什么?6个 3.125G Transceivers收发器。
3. 进去下载的资料发现有个ADC的例程,打算研究下ADC的例程
4. 这个板子有个配套的上位机ControlPanel软件,猜测是通过电脑的下载接口USB Blaser给板子下发指令,让板子去执行相应的操作。这个软件的操作就不说了。参考C5G_User_Manual.pdf第二章
5. 正式开始ADC的学习,板子试用ADC是LTC2308,看下它的介绍,8通道,12位的ADC,SPI接口
The LTC2308 is a low noise, 500ksps, 8-channel, 12-bit ADC with an SPI/MICROWIRE compatible serial interface. The internal conversion clock allows the external serial output data clock (SCK) to operate at any frequency up to 40MHz.
6. 看下接口图,正板子上有Arduino的接口
7. 看下原理图,U17,FPGA的电平难道是1.2V的?74AVC4T774电平转换,LTC2308和FPGA有4根线,标准的SPI接口
8. 通信的时序图
9. 打开工程看一下,本次还是用NIOS系统
1 module C5G_ADC(
2
3 //////////// CLOCK //////////
4 CLOCK_125_p,
5 CLOCK_50_B5B,
6 CLOCK_50_B6A,
7 CLOCK_50_B7A,
8 CLOCK_50_B8A,
9
10 //////////// LED //////////
11 LEDG,
12 LEDR,
13
14 //////////// KEY //////////
15 CPU_RESET_n,
16 KEY,
17
18 //////////// SW //////////
19 SW,
20
21 //////////// ADC SPI //////////
22 ADC_CONVST,
23 ADC_SCK,
24 ADC_SDI,
25 ADC_SDO,
26
27 //////////// GPIO, GPIO connect to GPIO Default //////////
28 GPIO
29 );
30 input CLOCK_125_p;
31 input CLOCK_50_B5B;
32 input CLOCK_50_B6A;
33 input CLOCK_50_B7A;
34 input CLOCK_50_B8A;
35
36 //////////// LED //////////
37 output [7:0] LEDG;
38 output [9:0] LEDR;
39
40 //////////// KEY //////////
41 input CPU_RESET_n;
42 input [3:0] KEY;
43
44 //////////// SW //////////
45 input [9:0] SW;
46
47 //////////// ADC SPI //////////
48 output ADC_CONVST;
49 output ADC_SCK;
50 output ADC_SDI;
51 input ADC_SDO;
52 //////////// GPIO, GPIO connect to GPIO Default //////////
53 inout [35:0] GPIO;
54
55 wire ADC_SCK_DELAY;
56 C5G_QSYS u0 (
57 .clk_clk (CLOCK_50_B5B), // clk.clk
58 .reset_reset_n (CPU_RESET_n), // reset.reset_n
59 .sw_external_connection_export (SW), // sw_external_connection.export
60 .adc_ltc2308_conduit_end_CONVST (ADC_CONVST), // adc_ltc2308_conduit_end.CONVST
61 .adc_ltc2308_conduit_end_SCK (ADC_SCK), // .SCK
62 .adc_ltc2308_conduit_end_SDI (ADC_SDI), // .SDI
63 .adc_ltc2308_conduit_end_SDO (ADC_SDO), // .SDO
64 .adc_ltc2308_conduit_end_SCK_DELAY (ADC_SCK_DELAY) // .SCK_DELAY
65 );
66 assign GPIO[0] = ADC_SCK;
67 assign GPIO[1] = ADC_SCK_DELAY;
68 assign GPIO[2] = ADC_SDI;
69 assign GPIO[3] = ADC_SDO;
70 signaltap_pll u_sig_pll(
71 .refclk(CLOCK_50_B7A), // refclk.clk
72 .rst(1'b0), // reset.reset
73 .outclk_0(), // 200MHz for signaltap sample clock.
74 .locked() // locked.export
75 );
76 endmodule
10. 不明白上面的GPIO是什么用途?
11. 搞完这些,需要用C语言去开发上层了,估计要用到EDS软件。
12. NIOS II EDS是用来搞NIOS软核处理器的开发软件,是Quartus自带的软件。还有个SOC EDS软件,是搞Cyclone V系列,带ARM内核的,需要另外安装
13. 打开NIOS II EDS软件,选择工作空间的时候,选择E:FPGAcyclone_v_gxDemonstrationsC5G_ADCsoftware,这个路径,直接就添加了工程,有2个工程,一个是库BSP,类似于底层的。一个是我们自己写的工程,其中HAL库这个很重要,包括了很多需要用到的库函数。
14. 研究下mian.c代码
1 #include <stdio.h>
2 #include <io.h>
3 #include <unistd.h>
4
5 #include "system.h"
6
7 void main(void){
8 int ch = 0;
9 const int nReadNum = 10; // max 1024
10 int i, Value, nIndex=0;
11
12 printf("ADC Demo
");
13 while(1){
14 ch = IORD(SW_BASE, 0x00) & 0x0F;
15
16 printf("======================= %d, ch=%d
", nIndex++, ch);
17 // set measure number for ADC convert
18 IOWR(ADC_LTC2308_BASE, 0x01, nReadNum);
19
20
21 // start measure
22 IOWR(ADC_LTC2308_BASE, 0x00, (ch << 1) | 0x00);
23 IOWR(ADC_LTC2308_BASE, 0x00, (ch << 1) | 0x01);
24 IOWR(ADC_LTC2308_BASE, 0x00, (ch << 1) | 0x00);
25 usleep(1);
26
27 // wait measure done
28 while ((IORD(ADC_LTC2308_BASE,0x00) & 0x01) == 0x00);
29
30 // read adc value
31 for(i=0;i<nReadNum;i++){
32 Value = IORD(ADC_LTC2308_BASE, 0x01);
33 printf("CH%d=%.3fV (0x%04x)
", ch, (float)Value/1000.0, Value);
34 }
35
36 usleep(200*1000);
37 } // while
38 }
15. 先下载FPGA工程,插上USB线,USB BLASTER接口,驱动正确识别。拨码开关SW11到RUN模式。
16. 编程EDS下载测试。需要修改环境变量,和包含的头文件路径,编译工程。
17. 下载运行,先点菜单栏的RUM -> RUN configuration,选择目标连接Target Connection,点击Refresh刷新一下,看到板子,然后点击Run按钮。
18. 看到Nios II Console有输出
19. 这次剩下的疑问,ADC_LTC2308_BASE这个地址的寄存器是什么样子的?在C语言实现的原理是什么?
比如下面的代码,设置ADC的测量精度,0x01代表什么?如果是寄存器,那么每个寄存器的位的说明文档在哪里?如果不是寄存器,那是什么?
1 // set measure number for ADC convert
2 IOWR(ADC_LTC2308_BASE, 0x01, nReadNum);