|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
串口接收机,状态机出了奇怪问题!
我的串口接收机是以《verilog 高级程序设计》一书中实例为参考,加上自己的需要改进的;
接收数据格式固定,1起始位,8位数据位,1位停止位
并为下一级提供时钟;
一直使用良好,最近发现状态机出问题了,而且很怪;下面是我的程序,我尽量注释,希望不要浪费大家过多时间;
在程序之前我先陈述一下我的问题,:
1:再没加 红色代码以前,程序在我的机子,可以无误运行,起码在我测试的时间内,大概8个多小时吧!!但是换了太终端设备,就会出问题;
2:问题是,过一段不确定的时间后,写时钟 wirte_clock 不再存在,只是个低电平,需要重新复位,要不然无法正常工作;
3:于是我断定flag_clock 为零,因为我检测sample_clock正常有输出;
4:既然flag_clock为零,所以肯定没有在 idle态,因为serial_signal_in为1,要是在idle态,那肯定falg_clock不为零;
5:所以我家了这句 assign temp = !(idle^state); 发现temp在出问题后,temp = 0;说明不在idle态;
6:于是assign temp = !(starting^state); 奇怪出现了,wirte_clock 正常了,错误再也出现不了;
7:assign temp = !(sending^state); 也没问题;
8:于是我又回到assign temp = !(idle^state); ,问题又回来了;
9:所以我断定,肯定是状态机跑乱了,但我又不知道是怎么跑乱的,我程序中加的红色部分对状态机有什么影响??
module portkUARR9_6k(serial_signal_in,
sample_clock,
reset,
paraller_signal_out,
write_clock,
w_rst,
temp //测试口
);
parameter width_signal_out = 8; //接收机并行输出8为数据
parameter width_sample_count= 4; //控制采样时钟的寄存器宽度
parameter width_bit_count = 4; //控制输出位数的寄存器宽度
parameter all_ones =8'b11111111;
parameter idle =2'b00;
parameter starting =2'b01;
parameter receving =2'b10;
input serial_signal_in; //串行输入信号
input sample_clock; //采样时钟
input reset; //同步复位
output [width_signal_out-1:0] paraller_signal_out; //并行输出数据
output write_clock; //为下一级提供写时钟
output w_rst; //为下一级提供写标志
output temp; //测试端口
reg [width_signal_out-1:0] Rec_datareg; //数据寄存器,
reg [width_signal_out-1:0] Rec_shftreg; //移位寄存器
reg [width_sample_count-1:0]sample_counter; //采样计数器
reg [width_bit_count-1:0] Bit_counter; //输出位数计数器
reg clr_Sample_counter,inc_Sample_counter;
reg clr_Bit_counter,inc_Bit_counter;
reg shift,load;
reg flag_wclk;
reg w_rst,w_rst1;
reg write_clock;
reg [1:0]state,next_state;
assign paraller_signal_out = Rec_datareg; //把接收到的8位数据送出
assign temp = !(starting^state); //这一句是后来加的,
always @(state or serial_signal_in or sample_counter or Bit_counter) //为每一次数据的流动提供状态
begin //所有状态赋 0 值
clr_Sample_counter = 0;
shift = 0;
load = 0;
flag_wclk = 0;
//w_rst = 0;
inc_Sample_counter = 0;
clr_Bit_counter = 0;
inc_Bit_counter = 0;
w_rst1 = 0;
next_state = state;
case(state)
idle: if(serial_signal_in == 0)
begin
next_state = starting;
clr_Sample_counter = 1; //校正采样寄存器,找到一个合适的采样起始时刻
end else
begin
//next_state = idle;
if(sample_counter>7) //在没有数据输入的情况下,提供时钟,
begin
clr_Sample_counter = 1; //
flag_wclk = 1; //
w_rst1 = 1; //
end else
inc_Sample_counter = 1;// 以上几段其实相当于分频
end
starting:if(serial_signal_in == 1)begin
next_state = idle;
clr_Sample_counter = 1;
end else
begin
next_state = receving;
clr_Sample_counter = 1;
end
receving:if(sample_counter<7) //
inc_Sample_counter = 1;
else begin
clr_Sample_counter = 1;
//shift = 1;
if(Bit_counter!= 8)begin
inc_Bit_counter = 1;
shift = 1;
end else
begin
clr_Bit_counter = 1;
next_state = idle;
load = 1;
flag_wclk = 1;
end
end
default:next_state = idle;
endcase
end
always @(posedge load or posedge w_rst1) //当采集到数据,即load == 1;
if(w_rst1)w_rst = 0;
else w_rst = 1; //写标志使能
always @(posedge sample_clock)
begin
if(reset==0) //复位时完成的操作
begin
Rec_shftreg<=all_ones;
Rec_datareg<=all_ones;
sample_counter<=0;
Bit_counter <=0;
state<=idle;
write_clock <= 0;
end else
begin
state<=next_state;
if(clr_Sample_counter) sample_counter <= 0;
else if(inc_Sample_counter==1) sample_counter<=sample_counter+1; //采样时钟计数
if(clr_Bit_counter==1) Bit_counter <= 0;
else if(inc_Bit_counter == 1) Bit_counter <= Bit_counter+1; //采样到的数据 计数,
if(shift==1) Rec_shftreg <= {serial_signal_in,Rec_shftreg[width_signal_out-1:1]}; //采样
if(load ==1) Rec_datareg <= Rec_shftreg;//取数
if(flag_wclk ==1) write_clock <= 1; //时钟
else write_clock <= 0;
end
end
endmodule |
|