集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1595|回复: 2

状态机设计请教

[复制链接]
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[7:0] MP;
    reg DARST,SCL;
    reg [7:0] MP;
    reg[7:0] data_buf;   //配置数据暂存寄存器
   
    inout SDA;
   
    //计数器  
    reg[23:0]count;     //复位计数器
    reg[1:0]send_num;  //寄存器地址
    reg[7:0]CLK_div; //分频系数

    //状态变量声明
    reg[2:0] next_state;     //状态机状态变量
    reg[3:0] 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[7:0] slave_address=8'h88;  //默认为写SAA7126寄存器配置
    reg[7:0] sub_address[2:1];
    reg[7:0] data[2:1];                //配置寄存器列表
    reg[7:0] 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[2]=8'h6b;
                sub_address[1]=8'h3a;
                data[2]=8'h93;
                data[1]=8'h12;
                //**********************
        end
        else  begin
                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[7:0]<=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
    else  begin
             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[7];
                                                inner_state<=second;
                                         end
                                second:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[6];
                                                inner_state<=third;
                                         end
                                third:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[5];
                                                inner_state<=fourth;
                                         end
                                fourth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[4];
                                                inner_state<=fifth;
                                         end
                                fifth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[3];
                                                inner_state<=sixth;
                                         end
                                sixth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[2];
                                                inner_state<=seventh;
                                         end
                                seventh:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[1];
                                                inner_state<=eighth;
                                         end
                                eighth:
                                        if(phase3) begin
                                                SDA_buf<=slave_address[0];
                                                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[send_num];
                                         end
                                   end
                                 end
                         endcase
           //送子地址
    sub_addr:
        case(inner_state)
                                first:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[7];
                                                inner_state<=second;
                                         end
                                second:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[6];
                                                inner_state<=third;
                                         end
                                third:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[5];
                                                inner_state<=fourth;
                                         end
                                fourth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[4];
                                                inner_state<=fifth;
                                         end
                                fifth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[3];
                                                inner_state<=sixth;
                                         end
                                sixth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[2];
                                                inner_state<=seventh;
                                         end
                                seventh:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[1];
                                                inner_state<=eighth;
                                         end
                                eighth:
                                        if(phase3) begin
                                                SDA_buf<=byte_buffer[0];
                                                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[send_num];
                                                inner_state<=first;
                                         end
                                   end
                                 end
                         endcase
           //配置寄存器
    send_data:
                        case(inner_state)
                                                first:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[7];
                                                                inner_state<=second;
                                                         end
                                                second:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[6];
                                                                inner_state<=third;
                                                         end
                                                third:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[5];
                                                                inner_state<=fourth;
                                                         end
                                                fourth:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[4];
                                                                inner_state<=fifth;
                                                         end
                                                fifth:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[3];
                                                                inner_state<=sixth;
                                                         end
                                                sixth:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[2];
                                                                inner_state<=seventh;
                                                         end
                                                seventh:
                                                        if(phase3) begin
                                                                SDA_buf<=data_buf[1];
                                                                inner_state<=eighth;
                                                         end
                                                eighth:
                                                        if(phase3) begin
                                                        SDA_buf<=data_buf[0];
                                                        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

本帖子中包含更多资源

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

x
wangxia6112 发表于 2011-3-14 17:12:57 | 显示全部楼层
好大一片啊,这么长,还是自己仔细找找吧,我也经常会碰到这样的问题。最后还是自己解决。呵呵。
至芯苏老师 发表于 2011-3-17 23:25:07 | 显示全部楼层
软件在综合过程中,状态机的码映射软件会根据相应设置进行优化,有的是独热码有的是格雷码,你看看你给出的图中状态机的码,他们是格雷码,所以状态码中并没有出现你设置的那些状态码数,你看看综合设置里面的状态机的编码是不是给有相关设置
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|集成电路技术分享 ( 京ICP备20003123号-1 )

GMT+8, 2024-5-24 02:45 , Processed in 0.093689 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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