我用CPLD采集AD数据,利用XINTF接口将数据传输到DSP,CCS观察DSP地址数据。系统框图如下所示。
其中28335的XINTF采用16位数据总线连接。
GPIO端口设置如下
void InitGpio(void)
{
EALLOW;
GpioCtrlRegs.GPBMUX1.all = 0xFFFFFFF0;
GpioCtrlRegs.GPCMUX1.all = 0xFFFFFFFF;
GpioCtrlRegs.GPCMUX2.all = 0xFFFFFFFF;
GpioCtrlRegs.GPCDIR.all = 0x00000000;
GpioCtrlRegs.GPAPUD.all = 0x0100;
GpioCtrlRegs.GPBPUD.all = 0x0000;
GpioCtrlRegs.GPCPUD.all = 0x0000;
EDIS;
}
XINTF访问区域0地址
void InitXintf(void)
{
// 这显示了如何写XINTF寄存器。
// 这里使用了重置后的默认状态值。
// 不同的硬件需要不同的配置。
// 为INTF配置一个例子,在如下目录
// F28335 eZdsp, refer to the examples/run_from_xintf project.
// 任何更改XINTF配置只能从XINTF扩展之外的区域运行代码。
// 所有区域---------------------------------
// 所有区域的基准时间时钟为 XTIMCLK = 1/2 SYSCLKOUT
EALLOW
SysCtrlRegs.PCLKCR3.bit.XINTFENCLK = 1
XintfRegs.XINTCNF2.bit.XTIMCLK = 1
XintfRegs.XINTCNF2.bit.WRBUFF = 0
XintfRegs.XINTCNF2.bit.CLKOFF = 1
XintfRegs.XINTCNF2.bit.CLKMODE = 1
XintfRegs.XTIMING0.bit.XWRLEAD = 2
XintfRegs.XTIMING0.bit.XWRACTIVE = 5
XintfRegs.XTIMING0.bit.XWRTRAIL = 2
// Zone read timing
XintfRegs.XTIMING0.bit.XRDLEAD = 2
XintfRegs.XTIMING0.bit.XRDACTIVE = 5
XintfRegs.XTIMING0.bit.XRDTRAIL = 2
// double all Zone read/write lead/active/trail timing
XintfRegs.XTIMING0.bit.X2TIMING = 1
// Zone will sample XREADY signal
XintfRegs.XTIMING0.bit.USEREADY = 0
XintfRegs.XTIMING0.bit.READYMODE = 1
XintfRegs.XTIMING0.bit.XSIZE = 3
EDIS
}
CPLD与AD芯片之间采样时序如下
- 问题
从DSP外部中断1的中断函数内,读取CPLD地址数据,发现8路ADC数据错乱,给AD通道1电平变化,其他相邻地址位也出现数据变化,相互串扰。其中测试确保程序进入了外部中断函数中。
#define FPGA_BASE_ADDR 0X4000
#define HSAD_OUT_CUR_A1 (FPGA_BASE_ADDR + 0x0004))
#define HSAD_OUT_CUR_B1 (FPGA_BASE_ADDR + 0x0005))
#define HSAD_OUT_CUR_A2 (FPGA_BASE_ADDR + 0x0006))
#define HSAD_OUT_CUR_B2 (FPGA_BASE_ADDR + 0x0007))
#define HSAD_OUT_CUR_A3 (FPGA_BASE_ADDR + 0x0008))
#define HSAD_OUT_CUR_B3 (FPGA_BASE_ADDR + 0x0009))
#define HSAD_OUT_CUR_A4 (FPGA_BASE_ADDR + 0x000A))
#define HSAD_OUT_CUR_A5 (FPGA_BASE_ADDR + 0x000B))
interrupt void XINT1_ISR(void)
起初以为是CPLD与AD之间采样时序错误,造成CPLD本身地址上数据错乱,经XINTF传送后,DSP也接收到错乱数据,CPLD程序如下。
always@(posedge SYS_10M_CLK)
begin
cs_r[2] =(XA == BASE_AD_ZONE0 + 16'H0004) &(!rd_filter)&(!XZCS0_N);
cs_r[3] =(XA == BASE_AD_ZONE0 + 16'H0005) &(!rd_filter)&(!XZCS0_N);
cs_r[4] =(XA == BASE_AD_ZONE0 + 16'H0006) &(!rd_filter)&(!XZCS0_N);
cs_r[5] =(XA == BASE_AD_ZONE0 + 16'H0007) &(!rd_filter)&(!XZCS0_N);
cs_r[6] =(XA == BASE_AD_ZONE0 + 16'H0008) &(!rd_filter)&(!XZCS0_N);
cs_r[7] =(XA == BASE_AD_ZONE0 + 16'H0009) &(!rd_filter)&(!XZCS0_N);
cs_r[8] =(XA == BASE_AD_ZONE0 + 16'H000A) &(!rd_filter)&(!XZCS0_N);
cs_r[9] =(XA == BASE_AD_ZONE0 + 16'H000B) &(!rd_filter)&(!XZCS0_N);
end
always@(posedge SYS_10M_CLK)
case(cs_r)
15'b000_0000_0000_0100: begin dsp_dat_reg = ad1_dout[15:0]; end
15'b000_0000_0000_1000: begin dsp_dat_reg = ad1_dout[31:16]; end
15'b000_0000_0001_0000: begin dsp_dat_reg = ad1_dout[47:32]; end
15'b000_0000_0010_0000: begin dsp_dat_reg = ad1_dout[63:48]; end
15'b000_0000_0100_0000: begin dsp_dat_reg = ad1_dout[79:64]; end
15'b000_0000_1000_0000: begin dsp_dat_reg = ad1_dout[95:80]; end
15'b000_0001_0000_0000: begin dsp_dat_reg = ad2_dout[15:0]; end
15'b000_0010_0000_0000: begin dsp_dat_reg = ad2_dout[31:16]; end
default: begin dsp_dat_reg = dsp_dat_reg;end
endcase
因CPLD程序无法调试和观察变量,我将CPLD采集程序屏蔽到只剩下一路AD采样,然后再次观察DSP地址变量数据,发现数据正确,单独测试每一路均能正确接收数据,但将多路AD采样通道开启却出现错误,再次检查CPLD与AD芯片采样时序,确保AD采样时序符合最小时序要求,发现还是出现错误。最后将CPLD采样程序屏蔽,直接在地址位上赋常量,如下所示。
always@(posedge SYS_10M_CLK)
begin
cs_r[2] =(XA == BASE_AD_ZONE0 + 16'H0004) &(!rd_filter)&(!XZCS0_N);
cs_r[3] =(XA == BASE_AD_ZONE0 + 16'H0005) &(!rd_filter)&(!XZCS0_N);
cs_r[4] =(XA == BASE_AD_ZONE0 + 16'H0006) &(!rd_filter)&(!XZCS0_N);
cs_r[5] =(XA == BASE_AD_ZONE0 + 16'H0007) &(!rd_filter)&(!XZCS0_N);
cs_r[6] =(XA == BASE_AD_ZONE0 + 16'H0008) &(!rd_filter)&(!XZCS0_N);
cs_r[7] =(XA == BASE_AD_ZONE0 + 16'H0009) &(!rd_filter)&(!XZCS0_N);
cs_r[8] =(XA == BASE_AD_ZONE0 + 16'H000A) &(!rd_filter)&(!XZCS0_N);
cs_r[9] =(XA == BASE_AD_ZONE0 + 16'H000B) &(!rd_filter)&(!XZCS0_N);
end
always@(posedge SYS_10M_CLK)
case(cs_r)
15'b000_0000_0000_0100: begin dsp_dat_reg = 30; end
15'b000_0000_0000_1000: begin dsp_dat_reg = 40; end
15'b000_0000_0001_0000: begin dsp_dat_reg = 50; end
15'b000_0000_0010_0000: begin dsp_dat_reg = 60; end
15'b000_0000_0100_0000: begin dsp_dat_reg = 70; end
15'b000_0000_1000_0000: begin dsp_dat_reg = 80; end
15'b000_0001_0000_0000: begin dsp_dat_reg = 110; end
15'b000_0010_0000_0000: begin dsp_dat_reg = 120; end
default: begin dsp_dat_reg = dsp_dat_reg;end
endcase
测试发现DSP地址数据出现跳变错乱,可以判断是CPLD与DSP的xintf通信问题,当时单路测试时正确以为xintf通信已经没有问题,导致花费很多时间测试CPLD与AD之间时序。仔细观察,发现ADC通道1数据串扰到通道2地址上,并影响通道3,怀疑DSP与CPLD通信时序不匹配,DSP速度过快,CPLD速度过慢,通过改变xintf配置寄存器,将建立、有效、跟踪时间调整至最高和最低,如下。
XintfRegs.XTIMING0.bit.XWRLEAD = 1
XintfRegs.XTIMING0.bit.XWRACTIVE = 1
XintfRegs.XTIMING0.bit.XWRTRAIL = 1
// Zone read timing
XintfRegs.XTIMING0.bit.XRDLEAD = 1
XintfRegs.XTIMING0.bit.XRDACTIVE = 1
XintfRegs.XTIMING0.bit.XRDTRAIL = 1
// double all Zone read/write lead/active/trail timing
XintfRegs.XTIMING0.bit.X2TIMING = 0
发现差别明显,另外通过将DSP系统时钟设置进行降频,发现数据能达到一个比较稳定状态。
#define DSP28_DIVSEL 2 // Enable /2 for SYSCLKOUT
#define DSP28_PLLCR 10
void InitSysCtrl(void)
{
DisableDog();
InitPll(DSP28_PLLCR,DSP28_DIVSEL);
InitPeripheralClocks();
}
最后发现DSP晶振为30Mhz,CPLD晶振为10Mhz,导致CPLD数据线上数据变化过慢,当DSP地址改变时,CPLD数据线上的数据还是前一位数据,造成数据延迟,串扰到第一位地址。尝试将xintf接口速度减慢,CPLD芯片无PLL,采用上下沿触发,软件倍频,还是达不到匹配状态。最后只得将CPLD晶振替换为30MHz才正确匹配。