4826|8

14

帖子

0

资源

一粒金砂(中级)

数据通过spi自stm32发送到cpld,cpld处理后发回出现问题,详细如下

10芯积分
我首先使用stm32通过spi发送数据到cpld,cpld处理数据后发回。问题的关键是,cpld中的程序的工作机制是这样的:我接受一切数据,甚至不区分什么帧头帧尾,什么位长。我cpld做的工作就是将收到的数据编码(收到的所有数据甚至空闲电平)都编码,经过低速光纤传输后在另一端把数据解码出来,包括什么空闲电平,帧头帧尾(当然,spi没用到帧头帧尾)。然后在通过spi传回给stm32。


可以看出,这种工作机制是很符合异步串行通信,但是spi是同步串行通信。所以stm32的spi预分频数只要超过了64,就无法接受到正确数据。通过示波器,我发现问题出在(看图)
搜狗截图20160922181734.png

从图上可以看出,在SCK(绿色波形,黄色波形是stm32的mosi发送数据)上升沿时,由于返回的数据和SCK不同步,导致SCK上升沿时不能每次都扫描到正确的电平。我认为解决的方法是:1、由于CPLD的时钟是50Mhz,而spi速度最高才是36/2=18M,只要将MISO(紫色波形)左移半个SCK,就可以保证SCK每次都扫描到正确的电平。
2、或者将收到的mosi的黄色波形数据收到后先不编码,左移半个SCK,然后再发送到编码。如图
搜狗截图20160922181803.png

但是,CPLD里的编码解码程序是别人写的,我不会改,我想单纯的在cpld的MoSi端,定义一个寄存器,然后在SCK的下降沿发送数据(stm32设置的是上升沿SCK检测电平)这样就能实现左移半个SCK。可是,写程序遇到了麻烦。
一个process中不能同时检测两个时钟沿。
可是我就是要在50Mhz的时钟下,检测spi的SCK的上升沿和下降沿啊。上升沿把数据存入寄存器。下降沿将数据发送到后面的编码器(别人的数据,我不会改,只能是保证它的不变,然后在前面加一个小模块,将小模块的输出当成它原来的输入给它)。


我写vhdl的思路是,第一个8bit数据,将数据存入a寄存器,第二个8bit数据传输周期,将数据存入b寄存器,同时在下降沿把a寄存器中数据发送到后面模块的输入,第三个8bit数据传输周期,将数据存入a寄存器,将b寄存器中数据发送到后面模块。这样不就同步了吗。

贴出来我写的那一些vhdl,帮忙告诉我怎么写,或者有解决上面问题的新思路。(我认为我上面的思路应该有逻辑错误,但我想了好久想不出来)谢谢了

signal TX:std_logic;
signal a:std_logic:='0';
signal b:std_logic:='0';
signal rx_shift_reg:std_logic_vector(7 downto 0):=(others=>'0');
signal rx_shift_reg_2:std_logic_vector(7 downto 0):=(others=>'0');
signal shift_cnt:std_logic_vector(3 downto 0):=(others=>'0');
signal shift_cnt_2:std_logic_vector(3 downto 0):=(others=>'0');
signal cnt:std_logic_vector(3 downto 0):=(others=>'0');
signal cnt_2:std_logic_vector(3 downto 0):=(others=>'0');


if rising_edge(spi_sck) then
        if(a='1')then
                rx_shift_reg<=rx_shift_reg(6 downto 0)& spi_din;
                shift_cnt<=shift_cnt+1;
                if(shift_cnt=x"07")then
                        b<='1';
                        a<=not a;
                end if;
        else
                rx_shift_reg_2<=rx_shift_reg_2(6 downto 0)& spi_din;
                shift_cnt_2<=shift_cnt_2+1;
                if(shift_cnt_2=x"07")then
                        b<='0';
                        a<=not a;
                end if;
        end if;
end if;
if(b='1')then
        if falling_edge(spi_sck) then
       
                cnt<=cnt+1;
                if(cnt=x"00")then
                        TX<=rx_shift_reg(7);
                else       
                        rx_shift_reg<=rx_shift_reg(6 downto 0)&'0';
                        TX<=rx_shift_reg(6);
                        if(cnt=x"07")then
                                cnt<=x"00";
                        end if;
                end if;
        end if;
else
        if falling_edge(spi_sck) then
                cnt_2<=cnt_2+1;
                if(cnt_2=x"00")then
                        TX<=rx_shift_reg_2(7);
                else       
                        rx_shift_reg_2<=rx_shift_reg_2(6 downto 0)&'0';
                        TX<=rx_shift_reg_2(6);
                        if(cnt_2=x"07")then
                                cnt_2<=x"00";
                        end if;
                end if;
        end if;
end if;



谢谢,头已炸

搜狗截图20160922181734.png

回复

14

帖子

0

资源

一粒金砂(中级)

原来这个CPLD就是配合stm32的uart使用的,一切正常没问题。我就是要看看用速度更高的spi怎么弄,怎么处理。

回复

299

帖子

0

资源

一粒金砂(中级)

为啥我感觉你这个是上升沿捕获呀?你让他下降沿捕获就可以了吧。还有用PLL提高CPLD的频率。然后、、、、、、。

点评

我这个是上升沿捕获,没错。但我想在cpld做这样的改动:mosi增加寄存器,使效果变成,下降沿捕获发送,miso还是上升沿发出  详情 回复 发表于 2016-9-23 09:31

回复

14

帖子

0

资源

一粒金砂(中级)

1399866558 发表于 2016-9-23 09:27
为啥我感觉你这个是上升沿捕获呀?你让他下降沿捕获就可以了吧。还有用PLL提高CPLD的频率。然后、、、、、 ...

我这个是上升沿捕获,没错。但我想在cpld做这样的改动:mosi增加寄存器,使效果变成,下降沿捕获发送,miso还是上升沿发出

点评

CPLD端,你写的是上升沿触发,才会造成紫色的线滞后其他颜色的线半个周期。你把它改成下降沿触发,波形就会和黄色的线一样的波形。  详情 回复 发表于 2016-9-23 09:49
CPLD端,你写的是上升沿触发,才会造成紫色的线滞后其他颜色的线半个周期。你把它改成下降沿触发,波形就会和黄色的线一样的波形。  详情 回复 发表于 2016-9-23 09:49

回复

299

帖子

0

资源

一粒金砂(中级)

amsams 发表于 2016-9-23 09:31
我这个是上升沿捕获,没错。但我想在cpld做这样的改动:mosi增加寄存器,使效果变成,下降沿捕获发送,mi ...

CPLD端,你写的是上升沿触发,才会造成紫色的线滞后其他颜色的线半个周期。你把它改成下降沿触发,波形就会和黄色的线一样的波形。

点评

上升沿触发的设置并不是在cpld中完成的,是stm32中的程序里的相性和极性设置的,这种设置使mosi和miso必须同时在上升沿和下降沿触发。但无论是哪种触发,最后一定后滞后半个SCK,所以我想在cpld中改一下这种效果,使  详情 回复 发表于 2016-9-23 09:54

回复

299

帖子

0

资源

一粒金砂(中级)

amsams 发表于 2016-9-23 09:31
我这个是上升沿捕获,没错。但我想在cpld做这样的改动:mosi增加寄存器,使效果变成,下降沿捕获发送,mi ...

CPLD端,你写的是上升沿触发,才会造成紫色的线滞后其他颜色的线半个周期。你把它改成下降沿触发,波形就会和黄色的线一样的波形。

回复

14

帖子

0

资源

一粒金砂(中级)

1399866558 发表于 2016-9-23 09:49
CPLD端,你写的是上升沿触发,才会造成紫色的线滞后其他颜色的线半个周期。你把它改成下降沿触发,波形就 ...

上升沿触发的设置并不是在cpld中完成的,是stm32中的程序里的相性和极性设置的,这种设置使mosi和miso必须同时在上升沿和下降沿触发。但无论是哪种触发,最后一定后滞后半个SCK,所以我想在cpld中改一下这种效果,使紫色波形和绿色波形同步,就是黄色左移半个SCK,那紫色就会出现在黄色原来的位置,就没问题了

回复

6

帖子

0

资源

一粒金砂(中级)

本帖最后由 axellaw 于 2017-3-6 00:38 编辑

如果CPLD的SPI用的是同步边沿检测的话,50M时钟实现18M的SPI通信是几乎不可能的,简单算一下就知道了
可靠的边沿检测需要两级寄存器来缓冲输入数据,也就是说,spi时钟到了CPLD中,被检测到后,至少也在2个时钟周期后了。

spi的工作模式是,主从机在相同的沿捕获和移出数据,比如时钟相位是0,则主机在上升沿捕获数据,在下降沿发送数据,从机也是这样,所以spi通信必须满足:从机在下降沿发送据后必须在下个上升沿之前到达主机,因为时钟是主机发出的,所以对主机没要求。

可以估算一下时序,主机在下降沿移出数据,布线延迟1.5cm就是1ns,算你3cm的布线2ns吧,到达cpld后,50M的主时钟,延迟2个时钟周期,就是40ns,加上CPLD的tco(从引脚进入信号)延迟,一般5ns是有的,这就47ns了,然后把数据打出寄存器,到达引脚,差不多8ns,这就55ns了,已经远远超过18M的半个时钟周期了,所以cpld在主机给出的时钟下降沿送出数据,是无论如何也无法在上升沿之前到达主机的

解决的办法只有:
1.提高cpld的工作时钟,降低边沿检测需要的时间
2.降低spi的发送速率,按照一般经验,cpld使用同步边沿检测实现spi从机,spi速度最好不要超过主时钟的1/5
3.cpld采用异步spi从机的设计,但异步电路设计需要小心的坑太多,自己看吧4.不使用标准的spi通信模式,即在上升沿捕获数据的同时,提前发送数据到主机,这样可以抢半个spi时钟周期的时间,但时序计算方式就不同了

回复

4

帖子

0

资源

一粒金砂(初级)

刚做完stm32通过SPI发送FPGA接收,预分频数从256到2都没问题。FPGA发送stm32接收暂时不用,还没测试,您说的“50M时钟实现18M的SPI通信是几乎不可能的”,我这用的25M时钟都没问题。

回复
您需要登录后才可以回帖 登录 | 注册

关闭
站长推荐上一条 1/6 下一条

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表