[FPGA] 求教大神!!读EEROM,程序会经常死在无法理解的状态机

[复制链接]
148|8
 楼主 | 2018-1-8 23:03 | 显示全部楼层 |阅读模式
本帖最后由 1273687647 于 2018-1-9 09:00 编辑

      先说一下老弟遇到的情况吧,用ACTEL的A3P250-1FG144芯片,在Libero11.1编译环境中编译的,其实是很简单的一个读取外置EEROM的SPI程序,每次上电时外部会恒定的给出mode=0(读模式)信号,芯片工作使能信号恒有效(EN_SPI=1),然后利用15.36MHZ的时钟,产生3.84MHZ的SCLK时钟,送给外部EEROM,片选信号SPI_CS每次低电平信号选片,并串转换的模块p2s、s2p没有写在帖子里(主要是和我遇到的问题没关系,就没写进来),即SPI_SI,SPI_SO不用考虑,遇到的问题和它们无关。     
          对于写的程序,在线的语法,仿真都没问题,可是什么我下载到Acte的A3P250-IFG144芯片上时,程序经常会莫名奇妙的死循环在状态机“DELAY_2>DELAY_3>DELAY_3>DELAY_3”,中间直接跳过CYC_3,而且一直不停的在“DELAY_2>DELAY_3>DELAY_3>DELAY_3”循环。
      FPGA的资源我只用了13%,在线仿真的逻辑和时序都是没问题的,到时为什么会一直在状态机“DELAY_2>DELAY_3>DELAY_3>DELAY_3”死循环呢??想尽了办法,困扰了几天,实在不知道小弟的程序哪里有问题,请各位大神帮我看看,指点一下,小弟万分感谢!!程序如下:


SPI_ctrl(clk,    //15.36MHZ
            rst,
            mode,
            EN_SPI,
            radd_ROM,
            SPI_Dout,
         
            SPI_CS,
            SPI_SCLK,
            op_code,
             D_fromROM,
             D_fromROM_ready
         );

input  clk,rst;
input  mode;
input  EN_SPI;
input[15:0]  radd_ROM;
input[7:0]  SPI_Dout;

output  SPI_SCLK;
output  SPI_CS;
output[23:0]  op_code;
output[7:0]  D_fromROM;
output  D_fromROM_ready;

parameter  READ_CNT=8’d32;

parameter  SPI_READ=8’b0000_0011;

parameter   IDLE=4’b0000,
                     Initial_1=4’b0001,
                     CYC_1=4’b0010,
                    DELAY_1=4’b0011,
                    CYC_2=4’b0100,
                    DELAY_2=4’b0101,
                   CYC_3=4’b0110,
                   DELAY_3=4’b0111,
                   JUDGE_1=4’b1000,
                   SPI_rdBack=4’b1001;

reg[3:0]  state;
reg[7:0]  SCLK_cnt;
Always@( posedge  rst  or  posedge  clk) begin
     if (rst)  begin
           SPI_SCLK<=1’b0;
           SPI_CS<=1’b1;
           op_code<=24’b0;
           D_fromROM<=8’b0;
           D_fromROM_ready<=1’b0;
           SCLK_cnt<=8’d0;
           state<=IDLE;
     end
     else  if ( EN_SPI==1‘b1’)  begin
            case(state)
                   IDLE: begin
                                 if(mode==1’b0) begin
                                        state<=Initial_1;
                                 end
                                 else begin
                                        state<=IDLE;
                                 end
                  end
                  Initial_1:begin
                                   op_code<={SPI_READ,radd_ROM};
                                   SCLK_cnt<=READ_CNT;
                                   state<=CYC_1;
                  end
                  CYC_1:begin
                                   SPI_CS<=1’b0;
                                   state<=DELAY_1;
                   end
                   DELAY_1:begin
                                   SPI_CS<=1’b0;
                                   state<=CYC_2;
                   end
                  CYC_2:begin
                                   SPI_SCLK<=1’b1;
                                   state<=DELAY_2;
                  end
                  DELAY_2:begin
                                  SPI_SCLK<=1’b1;
                                  SCLK_cnt<=SCLK_cnt-8’d1;
                                  state<=CYC_3;
                  end
                  CYC_3:begin
                                  SPI_SCLK<=1’b0;
                                  state<=DELAY_3;
                  end
                  DELAY_3:begin
                                  SPI_SCLK<=1’b0;
                                  if(SCLK_cnt==8’d0)  begin
                                           D_fromROM<=SPI_Dout;
                                           state<=JUDGE_1;
                                  end
                                  else  begin
                                           state<=CYC_2;
                                  end
                  end
                  JUDGE_1:begin
                                    SPI_CS<=1’b1;
                                     if(op_code[23:16]==SPI_READ)  begin
                                              D_fromROM_ready<=1’b1;
                                              state<=SPI_rdBack;
                                    end
                                    else  begin
                                              state<=IDLE;
                                    end
                   end
                   SPI_rdBack:begin
                                         D_fromROM_ready<=1’b0;
                                         state<=IDLE;
                   end
                   default:begin
                                  state<=IDLE;
                   end
              endcase
       end
       else  begin
                  SPI_SCLK<=1’b0;
                  SPI_CS<=1’b1;
                  op_code<=24’b0;
                  D_fromROM<=8’b0;
                  D_fromROM_ready<=1’b0;
                  SCLK_cnt<=8’d0;
                  state<=IDLE;
       end
end

 楼主 | 2018-1-8 23:03 | 显示全部楼层
自己顶一下
 楼主 | 2018-1-9 08:46 | 显示全部楼层
发现输出不正常时,我用示波器4个探头,同时测量状态机的4bit输出发现的,我是实在找不出原因,现在我都怀疑芯片是不是有问题了,可是换了个芯片,发现还是同样的问题,无语了!!!?希望大神指点一下,感兴趣了的坛友,也可以探讨一下,我会一直更新帖子的,直到问题解决
| 2018-1-9 17:04 | 显示全部楼层
     else  if ( EN_SPI==1‘b1’)  begin 可能问题在这
 楼主 | 2018-1-9 22:31 | 显示全部楼层
本帖最后由 1273687647 于 2018-1-10 08:23 编辑
xiachong 发表于 2018-1-9 17:04
else  if ( EN_SPI==1‘b1’)  begin 可能问题在这

    谢谢关注!
      我认为应该不是EN_SPI==1'b1的问题,因为如果是程序中间过程中出现了EN_SPI==1'b1的情况,那么状态机,应该回到IDLE==0000的状态,但是用示波器抓取的信号是连续的,而且状态机一直在“DELAY_2>DELAY_3>DELAY_3>DELAY_3”来回跳变,是不是就排除了EN_SPI==1'b0的可能行了。
      现在发现状态机在“DELAY_2>DELAY_3>DELAY_3>DELAY_3”,跳变,也就是说状态机的第2个bit,不稳定,一直在“0”“1”之间进行跳变,所以我今天怀疑了时钟clk的毛刺问题,所以又用ACTEL自带的锁相环IP核PLL对时钟分频(原来是用计数器对30.72MHZ的时钟分频),编译烧录进入芯片后,对其开关供电20 30 下发现,如果SCLK有输出的话(因为我又发现居然还有没有SCLK输出的情况,没有SCLK输出时!!!,SCLK恒为1 or 0)错误出现的概率明显变少了,同时又发现了一个新的问题,就是有时SCLK根本就没有输出,状态机一直保持在IDLE=0000,而且EN_SPI==1'b1!!(这又是什么鬼!!疯了)  
      哎!!有时候,我真的怀疑不是我的程序问题,而是这块,或者这个批次的芯片有问题!!!可是,我又拿不出有力的证据来证明!!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册 手机登录

x
| 2018-1-10 17:18 | 显示全部楼层
参考EEPROM驱动
http://blog.csdn.net/qq_20553613/article/details/78998617
 楼主 | 2018-1-12 21:51 | 显示全部楼层
Prry 发表于 2018-1-10 17:18
参考EEPROM驱动
http://blog.csdn.net/qq_20553613/article/details/78998617

谢谢你给的资料  我的这个问题不是驱动的问题
 楼主 | 2018-1-12 22:02 | 显示全部楼层
xiachong 发表于 2018-1-9 17:04
else  if ( EN_SPI==1‘b1’)  begin 可能问题在这

         问题解决了!!!
         对时钟优化完毕后,我又对复位rst进行了优化,对其进行了异步复位,同步释放处理,同时也加上了PLL的lock时钟锁定信号(其实加不加这个无所谓,程序也能正常运行),然后我进行了100次左右的上电,断电测试,每次程序都是正常运行的再也没有出现之前遇到的问题了!
         原来的复位是异步复位,可能由于外部复位信号的干扰,或者是芯片内部布线间的相互干扰,产生的毛刺干扰导致状态机进入了亚稳态,才导致完全不按逻辑跑的问题。
        同时,我也进行了同步复位的测试,效果虽然对比异步复位故障出现概率少点,但还是会有故障。
        哎!想想也可笑,居然是因为复位问题,我居然还查了那么久!!!以后遇到问题,首先就要查复位和时钟,先把这两个排除了,也算吃一堑长一智吧!
| 2018-1-14 20:41 | 显示全部楼层
最近在调I2C接口的EEPROM
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册 手机登录

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册 手机登录
高级模式

论坛热帖

关闭

热门推荐上一条 /4 下一条

分享 快速回复 返回顶部 返回列表