微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 状态机不稳定的问题。

状态机不稳定的问题。

时间:10-02 整理:3721RD 点击:
状态机不稳定,跑上几十次就卡在某个状态。
改成三段式后,在RTL viewer看综合后的电路,综合成了状态机(黄色那块)。
这时候程序运行几遍就会卡住。但是将CS赋值给led变量后,编译后用RTLviewer观察,没有综合出状态机,CS总合成了触发器,这时候程序反而能一直运行下去,不会卡住。
这到底是为什么。代码如下(两次编译的区别就在于最下边标红的部分,现在的代码编译没有综合出状态机,将下边那行代替这行,就会编译生成状态机):
module DO_backplane(
//global signals
input clk,
input nRST,
//DO_trigger module interface
//input      [7:0]  b_feedback,
//input      [13:0] working_status,
output reg [13:0] b_trigger,
output reg [13:0] led,
//backplane signals
input      [9:0]  b_addr,
inout      [7:0]  b_data,
input             b_rd,            //active low
input             b_wr,            //active low
//input             retry,           //active low
output reg        ready,           //active low
output reg [3:0]  oe,
output reg [3:0]  dir
);
//FSM is coded by one-hot
localparam Bus_Idle     =5'h00;
localparam Bus_RW       =5'h01;
localparam Bus_Ready    =5'h02;//set ready signal in read cycle
localparam Bus_Data     =5'h04;
localparam Bus_Ready_UN =5'h08;
localparam Bus_Finish   =5'h10;
/*
//FSM is coded by Gray Code
localparam Bus_Idle     =4'b0000;
localparam Bus_RW       =4'b0001;
localparam Bus_Ready    =4'b0011;//set ready signal in read cycle
localparam Bus_Data     =4'b0010;
localparam Bus_Ready_UN =4'b0110;
localparam Bus_Finish_a   =4'b0100;
localparam Bus_Finish_b   =4'b0101;
localparam Bus_Finish_c   =4'b0111;
localparam Bus_Finish_d   =4'b1111;
*/
//DO1A board base address
parameter DO_base_addr    =10'h180;
//backplane communication
reg [4:0]  CS;
reg [4:0]  NS;
reg [7:0]  data;
reg        read_flag;
reg [13:0] b_trigger_temp;
reg [7:0]  data_temp;
reg [25:0] count;
//tri-stated databus
assign b_data = (~read_flag)?data:8'hzz;
//output a variable data to CPU board to verify long-time communication
always@(posedge clk or negedge nRST)
begin
        if(~nRST)
        begin
                count <= 25'h0;
                data_temp  <= 8'h0;
        end
        else if(count == 25'h16e3200)
        begin
                count <= 25'h0;
                data_temp  <= data_temp + 1'b1;
        end
        else
                count <= count + 1'b1;
end
//backplane communication FSM
//1st always block,synchronously update currentstate with next state
always@(posedge clk or negedge nRST)
begin
        if(~nRST)
                CS <= Bus_Idle;
        else
                CS <= NS;
end
//2nd always block,combinational condition judgement
always@(b_addr or CS or b_rd or b_wr)
begin
        NS = CS;
        case(CS)
        Bus_Idle:
                begin
                        if(b_addr == DO_base_addr)  
                                NS = Bus_RW;
                end
        Bus_RW:
                begin
                        if((b_rd == 1'b1)&&(b_wr == 1'b0))//firstly write to DO,then read data from DO
                                NS = Bus_Ready;                               
                end
        Bus_Ready:
                begin
                        NS = Bus_Data;
                end
        Bus_Data:
                begin
                        if(b_addr[5:0] == 6'h5)
                                NS = Bus_Ready_UN;
                end
        Bus_Ready_UN:
                begin
                        NS = Bus_Finish;
                end
        Bus_Finish:
                begin
                        NS = Bus_Idle;
                end               
        default:
                begin
                        NS = Bus_Idle;
                end
        endcase
end
//3rd always block,synchronously output
always@(posedge clk or negedge nRST)
        begin
                if(~nRST)
                        begin
                                ready     <= 1'b1;
                                read_flag <= 1'b1;
                                data      <= 8'h0;
                                oe  <= 4'b0101;
                                dir <= 4'b1101;
                        end
                else
                        case(CS)
                                Bus_Idle:
                                        begin
                                                oe  <= 4'b0011;
                                                dir <= 4'b1101;
                                                ready <= 1'b1;
                                        end
                                Bus_RW:
                                        begin
                                                oe <= 4'b0000;
                                        end
                                Bus_Ready:
                                        begin
                                                ready <= 1'b0;                                               
                                        end
                                Bus_Data:
                                        begin
                                                if(b_addr[5:0] == 6'h0)
                                                        b_trigger_temp[13:8] <= b_data[5:0];                                                       
                                                else if(b_addr[5:0] == 6'h1)
                                                        b_trigger_temp[7:0] <= b_data;                                                       
                                                else if(b_addr[5:0] == 6'h2)
                                                        begin                                                       
                                                                read_flag <= 1'b0;
                                                                dir       <= 4'b1100;
                                                                b_trigger <= b_trigger_temp;
                                                        end                                                                                                               
                                                else if(b_addr[5:0] == 6'h3)
                                                        data <= data_temp;                                       
                                                else if(b_addr[5:0] == 6'h4)
                                                        data <= data_temp;                                               
                                                else
                                                        data <= 8'hcc;
                                        end
                                Bus_Ready_UN:
                                        begin
                                                read_flag <= 1'b1;
                                                ready <= 1'b1;
                                        end
                        endcase
        end                                                                       
always@(posedge clk or negedge nRST)
begin
        if(~nRST)
                begin
                        led <= 14'h2aaa;
                end
        else
                begin
                        led <={2'h0,CS, b_trigger_temp[7:0]};
//                        led <= b_trigger_temp;
                end
end
endmodule       

综合成状态机


没有综合成状态机


状态机的输入条件时序没有给出,很难去判断为何会状态异常,大多情况都是出现了你没有列出转移条件,从而导致的异常,就你列出的代码而言,个人感觉有两个问题,你可以作为参考:
1、NRST为低时,CS<=IDLE状态,同时 “oe  <= 4'b0101”,但在状态输出中,当CS==IDLE 状态,oe  <= 4'b0011,这两个输出是矛盾的,即NRST时,CS必然为IDLE ,也就是说在NRST为低时,oe可能有两个赋值。
2、data_temp的值可能溢出,不知道你关心这个不。希望对你有用

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top