状态机设计请教
我写了个程序,反复修改,仍然有问题。但是,我已经找不出问题所在了。麻烦帮忙看下。程序的功能如下:整个文件共有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 好大一片啊,这么长,还是自己仔细找找吧,我也经常会碰到这样的问题。最后还是自己解决。呵呵。 软件在综合过程中,状态机的码映射软件会根据相应设置进行优化,有的是独热码有的是格雷码,你看看你给出的图中状态机的码,他们是格雷码,所以状态码中并没有出现你设置的那些状态码数,你看看综合设置里面的状态机的编码是不是给有相关设置
页:
[1]