sepathy@163.com 发表于 2011-3-11 16:40:46

状态机设计请教

我写了个程序,反复修改,仍然有问题。但是,我已经找不出问题所在了。麻烦帮忙看下。程序的功能如下:
整个文件共有4个进程:一个进程用来实现软件复位;一个用来赋值数据端口;一个是用来产生I2C总线始终的控制信号;再有一个是用来实现芯片配置。
产生I2C总线的进程设计如下:
I2C数据率400Kbps,输入时钟10MHZ,分频系数25;当计数器计数到5、10、15、20时分别将phase0、phase1、phase2、phase3置1;然后在下一个SysClk10M时钟将其置0;如图

实现芯片配置进程工作如下:
在start_up信号为1时,启动状态机。传输方式:启动->传输从机地址->传输IC芯片子地址->传输配置数据(一个字节+Ack)->再次启动->传输从机地址->传输IC芯片子地址->传输配置数据(一个字节+Ack)->完成。
I2C时序模拟如下:


问题:
1、        next_state的运行状态与程序设定不符
2、        SignalTap中显示的状态编码出现了程序中为定义的状态(如101、110),为什么?



附件给出了SignalTap实时数据波形截图以及工程文件源码及TopFile。

恭请赐教
由于无法在文本中添加图片,详细的说明以附件形式给出。下面是源码:
//**************************************************
//SAA7126 initial configuration based on IIC bus .
//SysClk10M=10MHZ
//IIC bus data rate=400kb/s
//Clock used in program =25*400khz
//Clock_Div=25
//**************************************************

module SAA7126Control(
                      SysClk10M,    //10MHZ
                     //输出端口
                         SCL,//I2C时钟
                        MP,//VGA数据输出
                     DARST,//软件复位SAA7126复位管脚,Active Low
                     //双向端口
                        SDA);
   
   //输入端口声明
    input SysClk10M;   
   //输出端口声明
    output DARST,
         SCL;
    output MP;
    reg DARST,SCL;
    reg MP;
    reg data_buf;   //配置数据暂存寄存器
   
    inout SDA;
   
    //计数器
    regcount;   //复位计数器
    regsend_num;//寄存器地址
    regCLK_div; //分频系数

    //状态变量声明
    reg next_state;   //状态机状态变量
    reg inner_state;    //字节传输内部状态变量

    reg phase0,phase1,phase2,phase3;//SCL时钟的四个相位定义
   
    reg start_up;   //状态机启动信号
    reg SDA_buf;
    reg SDA_enable;   //SDA输入输出控制
    reg data_en;      //将相机数据送到MP口使能
                      
        //字节传输状态定义                  
    parameter   first=4'b0001,    //第1位
                                second= 4'b0010,    //第2位
                                third=4'b0011,    //第3位
                                fourth= 4'b0100,    //第4位
                                fifth=4'b0101,    //第5位
                                sixth=4'b0110,    //第6位
                                seventh=4'b0111,    //第7位
                                eighth= 4'b1000,    //第8位
                                ack=    4'b1001;    //第9位
                               
    parameter   start=   3'b000,    //开始位
                slave_addr=3'b001,
                sub_addr=3'b010,
                send_data= 3'b011,
                stop=      3'b100;//停止位
            

    //持续赋值;
    assign SDA=SDA_enable?SDA_buf:1'bZ;
   
   //寄存器配置表
    reg slave_address=8'h88;//默认为写SAA7126寄存器配置
    reg sub_address;
    reg data;                //配置寄存器列表
    reg byte_buffer;

   //复位操作(软件复位)
   //复位时间为1s
    always @ (posedge SysClk10M)
    begin
    if(count==24'd10000000)
        begin
                DARST<=1'b1;
                start_up<=1'b1;
                SDA_enable<=1'b1;
               
                //Initialization********
                sub_address=8'h6b;
                sub_address=8'h3a;
                data=8'h93;
                data=8'h12;
                //**********************
        end
        elsebegin
                count<=count+24'b1;
                start_up<=1'b0;
                SDA_enable<=1'b0;
                DARST<=1'b0;
                end
    end

    //图像数据送入到SAA7126
      always@(posedge SysClk10M)
      begin
              if(data_en==1'b1)
                   MP<=8'b0000_0000;
      end
      
   
   //相位定义
   always@(posedge SysClk10M)
   begin
      if(!start_up)begin
      phase0<=0;
      phase1<=0;
      phase2<=0;
      phase3<=0;
      CLK_div<=0;
      end
      else begin
      if(CLK_div==24)
         CLK_div<=0;
         else CLK_div<=CLK_div+8'b1;
      if(phase0)
                        phase0<=0;       
                else if(CLK_div==5)
                        phase0<=1;
                if(phase1)
                        phase1<=0;
                else if(CLK_div==10)
                        phase1<=1;
                if(phase2)
                        phase2<=0;
                else if(CLK_div==15)
                        phase2<=1;
                if(phase3)
                        phase3<=0;
                else if(CLK_div==20)
                        phase3<=1;
      end
   end
   
    //配置寄存器
    always@(posedge SysClk10M)
    begin
    if(!start_up)begin
    next_state<=start;
    inner_state<=first;
    SDA_buf<=1'b1;//总线上的器件都释放总线
        SCL<=1'b1;    //总线上的器件都释放总线
        //复位初始化
    data_en<=1'b0;
        send_num<=1;
    end
    elsebegin
           if(phase0)
                  SCL<=1;
                else if(phase2)
                  SCL<=0;
case(next_state)
          //启动信号*****************
       start:begin
      if(phase1) begin
                        SDA_buf<=0;
                        next_state<=slave_addr;
               end
   end
         
           //送从地址******************
       slave_addr:       
        case(inner_state)
                                first:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=second;
                                       end
                                second:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=third;
                                       end
                                third:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=fourth;
                                       end
                                fourth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=fifth;
                                       end
                                fifth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=sixth;
                                       end
                                sixth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=seventh;
                                       end
                                seventh:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=eighth;
                                       end
                                eighth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address;
                                                inner_state<=ack;
                                       end
                                ack: begin
                                        if(phase3)
                                                SDA_buf<=SDA;
                                  if(phase1)begin
                                     if(SDA_buf==1)begin
                                     next_state<=start;
                                     end
                                        else begin
                                                next_state<=sub_addr;
                                                inner_state<=first;
                                                byte_buffer<=sub_address;
                                       end
                                   end
                               end
                       endcase
           //送子地址
    sub_addr:
        case(inner_state)
                                first:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=second;
                                       end
                                second:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=third;
                                       end
                                third:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=fourth;
                                       end
                                fourth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=fifth;
                                       end
                                fifth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=sixth;
                                       end
                                sixth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=seventh;
                                       end
                                seventh:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=eighth;
                                       end
                                eighth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer;
                                                inner_state<=ack;
                                       end
                                ack: begin
                                        if(phase3)
                                                SDA_buf<=SDA;
                                  if(phase1)begin
                                     if(SDA_buf==1)begin
                                     next_state<=start;
                                     end
                                        else begin
                                                next_state<=send_data;
                                                data_buf<=data;
                                                inner_state<=first;
                                       end
                                   end
                               end
                       endcase
           //配置寄存器
    send_data:
                        case(inner_state)
                                                first:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=second;
                                                       end
                                                second:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=third;
                                                       end
                                                third:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=fourth;
                                                       end
                                                fourth:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=fifth;
                                                       end
                                                fifth:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=sixth;
                                                       end
                                                sixth:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=seventh;
                                                       end
                                                seventh:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf;
                                                                inner_state<=eighth;
                                                       end
                                                eighth:
                                                        if(phase3) begin
                                                        SDA_buf<=data_buf;
                                                        inner_state<=ack;
                                               end
                                        ack: begin
                                                        if(phase3)
                                                                SDA_buf<=SDA;
                                                        if(phase1)begin
                                                           if(SDA_buf==1)begin
                                                           next_state<=start;
                                                           end
                                                        else begin
                                                       send_num<=send_num+2'b1;
                                                       if(send_num==2)begin
                                                                next_state<=stop;
                                                                SDA_buf<=0;
                                                                end
                                                                else next_state<=start;
                                                       end
                                                end
                                       end
                        endcase

            //发送“停止”命令
        stop: begin
                if(phase1)
                        SDA_buf<=1;
                        next_state<=stop;
       end
              //缺省情况
   default:
                  next_state<=start;
   endcase
end
end
endmodule

wangxia6112 发表于 2011-3-14 17:12:57

好大一片啊,这么长,还是自己仔细找找吧,我也经常会碰到这样的问题。最后还是自己解决。呵呵。

至芯苏老师 发表于 2011-3-17 23:25:07

软件在综合过程中,状态机的码映射软件会根据相应设置进行优化,有的是独热码有的是格雷码,你看看你给出的图中状态机的码,他们是格雷码,所以状态码中并没有出现你设置的那些状态码数,你看看综合设置里面的状态机的编码是不是给有相关设置
页: [1]
查看完整版本: 状态机设计请教