打印

自己写的三段式状态机程序,有点问题,请教

[复制链接]
2853|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jlgcumt|  楼主 | 2013-3-12 23:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 jlgcumt 于 2013-3-12 23:56 编辑
//////////////////////////////////FSM///////////////////////////////////////
// 状态转换
always @ (posedge sys_clk or negedge rst_n)
begin
        if(!rst_n)
                cstate_ad <= 0;
        else
                cstate_ad <= nstate_ad;        
end

// 下一状态生成
always @ (*)
begin
        if(!rst_n)
                begin
                nstate_ad = 0;               
                end
        else
                begin
                case(cstate_ad)
                4'd0:                                // 判断当前ad是否使能,使能的话进入下一状态开始启动采集
                        begin
                        if(ADEn)
                                nstate_ad = 4'd1;
                        else
                                nstate_ad = 4'd0;                        
                        end
                4'd1:           // 此状态和下一状态用于AD7606采集的转换启动信号
                        begin
                        nstate_ad = 4'd2;                        
                        end
                4'd2:                                
                        begin
                        nstate_ad = 4'd3;                                
                        end
                4'd3:                                 // 等待125ns,在启动信号和Busy信号有效之间延时最大为40ns(手册要求)
                        begin
                        nstate_ad = 4'd4;                        
                        end
                4'd4:
                        begin
                        nstate_ad = 4'd5;                        
                        end
                4'd5:
                        if(ad_busy)  // 转换正在进行中  
                                begin
                                        nstate_ad = 4'd5;
                                end                        
                        else                         // 转换完成
                                begin
                                        nstate_ad = 4'd6;
                                end
                4'd6:           // 开始采集
                        begin
                        if(ADSampNum < 4 )   // 当前8个通道采集值都已经读出来,进行下一次的采集
                                begin                                       
                                nstate_ad = 4'd7;        
                                end
                        else              // 当前正在读取采集结果
                                begin                                       
                                nstate_ad = 4'd0;                                
                                end                        
                        end
                4'd7:                                                        // 启动SPI读取时钟
                        begin
                        nstate_ad = 4'd8;                                
                        end
                4'd8:
                        begin
                        nstate_ad = 4'd9;        
                        end
                4'd9:                                                        // 多延时一次确保延时计数器已经开始工作
                        begin
                        nstate_ad = 4'd10;
                        end
                4'd10:
                        begin
                        if(ADDelay_Cnt > 10)    //  延时时间到
                                begin
                                nstate_ad = 4'd11;
                                end
                        else                                                        //  延时时间还没到,等待中
                                begin
                                nstate_ad = 4'd10;
                                end                        
                        end
                4'd11:
                        begin
                        if(AD_FSM_State)        //
                                begin
                                nstate_ad = 4'd11;   
                                end                        
                        else
                                begin
                                nstate_ad = 4'd12;   //
                                end
                        end
                4'd12:                                                        // 将读到的数据记录下来
                        begin
                        nstate_ad = 4'd13;
                        end
                4'd13:                     // 读取通道索引值加1,读取下一通道值
                        begin
                        nstate_ad = 4'd6;
                        end
//                default:nstate_ad = 4'd0;
                default: nstate_ad = 4'd0;
                endcase        
               
                end
end


// 输出值实现
always @(posedge sys_clk or negedge rst_n)
begin
        if(!rst_n)
                begin               
                ADStart <= 0;
                ad_convsta <= 1;
                ADSampNum <= 0;
                ad_samp_value[0][15:0] <= 0;
                ad_samp_value[1][15:0] <= 0;
                ad_samp_value[2][15:0] <= 0;
                ad_samp_value[3][15:0] <= 0;
                ad_samp_value[4][15:0] <= 0;
                ad_samp_value[5][15:0] <= 0;
                ad_samp_value[6][15:0] <= 0;
                ad_samp_value[7][15:0] <= 0;               
                end
        else
                begin
                case(cstate_ad)
                4'd0:
                        begin
                        ad_convsta <= 1;
                        ADSampNum <= 0;
                        end
                4'd1:                   // ad_convsta拉低62.5ns,大于手册要求的最小25ns的要求
                        begin
                        ad_convsta <= 0;
                        end
                4'd2:
                        begin
                        ad_convsta <= 1;
                        end
                4'd3:
                        begin
                        ;
                        end
                4'd4:
                        begin                        
                        ;
                        end
                4'd5:
                        begin
                        ;
                        end
                4'd6:
                        begin
                        ;
                        end
                4'd7:                   //  启动SPI时钟
                        begin
                        ADStart <= 1;
                        end
                4'd8:
                        begin
                        ADStart <= 0;
                        end               
                4'd9:
                        begin
                        ;
                        end               
                4'd10:
                        begin
                        ;
                        end
                4'd11:
                        begin
                        ;
                        end
                4'd12:
                        begin
                        ad_samp_value[ADSampNum][15:0] <= ad_samp_value_current_a[15:0];
                        ad_samp_value[ADSampNum+4][15:0] <= ad_samp_value_current_b[15:0];
                        
                        end
                4'd13:
                        begin
                        ADSampNum <= ADSampNum +1;
                        end
                default:  ;               
               
               
                endcase
                end
end


// 延时计数器
reg [4:0] ADDelay_Cnt;
always @(posedge sys_clk or negedge rst_n)
begin
        if(!rst_n)
                begin               
                ADDelay_Cnt <= 0;
                end
        else
                begin               
                if(ADStart)
                        ADDelay_Cnt <= 0;
                else
                        begin                        
                        if( ADDelay_Cnt < 5'd21)
                                ADDelay_Cnt <= ADDelay_Cnt + 1;
                        else
                                ADDelay_Cnt <= ADDelay_Cnt;                        
                        end                        
                end

end

//读取采样结果例化
ADSPI_RX ADRX(.clk_div(clk_div),.rst_n(rst_n),.spi_clk(ad_sclk),.ad_start(ADStart),.spi_en(ADEn),.spi_miso_a(ad_miso_a),.spi_miso_b(ad_miso_b),.spi_ncs(ad_cs_n),
                                  .rx_value_a(ad_samp_value_current_a[15:0]),.rx_value_b(ad_samp_value_current_b[15:0]),.spi_state(AD_FSM_State));

相关帖子

沙发
jlgcumt|  楼主 | 2013-3-12 23:54 | 只看该作者
程序比较简单,是一个AD的采集控制程序,现在有个问题是,在状态6的时候跳变不对,本来跑到6的时候,判断ADSampNum这个值进行状态切换,当把程序烧到板子上时发现ADSampNum值倒是增加了,就是在6的时候老跑到0,虽然我写的是ADSampNum<4要跑到7,请问是怎么回事?

使用特权

评论回复
板凳
jlgcumt|  楼主 | 2013-3-13 10:12 | 只看该作者
今天早上一醒来,发现问题的原因,解决,结贴了!

使用特权

评论回复
地板
zhangxq4633| | 2013-3-13 11:13 | 只看该作者
接分啦...

使用特权

评论回复
5
duoduo1989| | 2013-3-13 11:24 | 只看该作者
楼主这是睡一觉就豁然开朗了咩

使用特权

评论回复
6
jlgcumt|  楼主 | 2013-3-13 14:25 | 只看该作者
等人多了散分!

使用特权

评论回复
7
mmhhkk| | 2013-3-13 14:34 | 只看该作者
怎么解决的分享一下啊

使用特权

评论回复
8
magic_yuan| | 2013-3-13 14:37 | 只看该作者
楼主牛X啊,这么长的程序。。。。

使用特权

评论回复
9
GoldSunMonkey| | 2013-3-13 15:50 | 只看该作者
magic_yuan 发表于 2013-3-13 14:37
楼主牛X啊,这么长的程序。。。。

必须的

使用特权

评论回复
10
jlgcumt|  楼主 | 2013-3-13 21:01 | 只看该作者
mmhhkk 发表于 2013-3-13 14:34
怎么解决的分享一下啊

是跟下面例化的模块有一个信号没配合好(子模块没捕捉到这个信号),两个用不同的时钟在工作,刚开始没注意到!

使用特权

评论回复
11
jlgcumt|  楼主 | 2013-3-13 21:03 | 只看该作者
magic_yuan 发表于 2013-3-13 14:37
楼主牛X啊,这么长的程序。。。。

我也是初学者,三段式状态机还是第一次写,哈哈,modelsim还没学会呢,要不然仿真一下估计就能找出问题了,现在全是我自己的脑子在做仿真!

使用特权

评论回复
12
qin552011373| | 2013-3-13 21:51 | 只看该作者
好牛啊

使用特权

评论回复
13
GoldSunMonkey| | 2013-3-13 22:32 | 只看该作者
qin552011373 发表于 2013-3-13 21:51
好牛啊

你更牛啊

使用特权

评论回复
14
lark100| | 2013-3-14 00:29 | 只看该作者
有软件天赋!!!

使用特权

评论回复
15
magic_yuan| | 2013-3-14 10:28 | 只看该作者
jlgcumt 发表于 2013-3-13 21:03
我也是初学者,三段式状态机还是第一次写,哈哈,modelsim还没学会呢,要不然仿真一下估计就能找出问题了 ...

我在搞modelsim。简单仿真。呵呵,多像你学习了。

使用特权

评论回复
16
GoldSunMonkey| | 2013-3-14 19:36 | 只看该作者
magic_yuan 发表于 2013-3-14 10:28
我在搞modelsim。简单仿真。呵呵,多像你学习了。

欢迎常来啊

使用特权

评论回复
17
xjsxjtu| | 2013-3-14 20:01 | 只看该作者
嗯,不错啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:善攻者,动于九天之上,善守者,藏于九地之下!

183

主题

733

帖子

4

粉丝