xtx 发表于 2012-4-12 09:44:41

求助quartus 无法识别三段式状态机

    问题,如题,代码如下:

`define        DEBUG                1
module fifo_uart_tx(
                        CLK,
                        NRESET,
                        DATA,
                        WR,
                        FULL,
                        TX
);
parameter        IDLE        =0,
                                S                =1,
                                B0                =2,
                                B1                =3,
                                B2                =4,
                                B3                =5,
                                B4                =6,
                                B5                =7,
                                B6                =8,
                                B7                =9,
                                E                =10;
                       
input                CLK;//48Mhz系统时钟频率
input                NRESET;
input                DATA;
input                WR;

output        FULL;
output        TX;

reg        current_state;
reg next_state;
reg                baud_clk_r;
reg                rd_r;
reg                tx_r;
reg                clk_en_r;

wire                clk_en;
wire                baud_clk;
wire                rd;
wire                empty;
wire                q;
wire                pos_baud_clk;
//实例化一个时钟产生模块
baud_gen        baud_gen(
                                        .CLK(CLK),
                                        .NRESET(NRESET),
                                        .EN(clk_en),
                                        .BAUD_CLK(baud_clk)
                );
//实例化一个                                                                                                                                                                                                                                                                                                                                                                                                      FIFO               
fifo        fifo_inst (
                                        .aclr ( NRESET ),
                                        .clock ( CLK ),
                                        .data ( DATA ),
                                        .rdreq ( rd ),
                                        .wrreq ( WR ),
                                        .empty ( empty ),
                                        .full ( FULL ),
                                        .q ( q )
                );       
               
always@(posedge CLK,negedge NRESET)               
        if(!NRESET)
                baud_clk_r<=0;
        else
                baud_clk_r<=baud_clk;
always@(posedge CLK,negedge NRESET)               
        if(!NRESET)
                baud_clk_r<=0;
        else
                baud_clk_r<=baud_clk_r;
assign        pos_baud_clk=~baud_clk_r&baud_clk_r;//baud_clk的上升沿
       
always@(posedge CLK,negedge NRESET)       
        if(!NRESET)
                current_state<=IDLE;
        else
                current_state<=next_state;

always@(current_state,pos_baud_clk,empty)        begin
        case(current_state)
                IDLE:        if(!empty)
                                        next_state=S;
                S:                if(pos_baud_clk)
                                        next_state=B0;
                B0:        if(pos_baud_clk)
                                        next_state=B1;
                B1:        if(pos_baud_clk)
                                        next_state=B2;                               
                B2:        if(pos_baud_clk)
                                        next_state=B3;                                       
                B3:        if(pos_baud_clk)
                                        next_state=B4;                                       
                B4:        if(pos_baud_clk)
                                        next_state=B5;                                       
                B5:        if(pos_baud_clk)
                                        next_state=B6;                                               
                B6:        if(pos_baud_clk)
                                        next_state=B7;                                       
                B7:        if(pos_baud_clk)
                                        next_state=E        ;                               
                E:                if(pos_baud_clk)
                                        next_state=IDLE        ;                               
        endcase                       
end               

always@(posedge CLK,negedge NRESET) begin
        if(!NRESET) begin
                tx_r<=1;
                rd_r<=0;
                clk_en_r<=0;
        end
        else
                case(next_state)
                        IDLE:begin
                                        if(!empty)
                                                rd_r<=1;
                                        else
                                                rd_r<=0;
                                        tx_r<=1;
                                        clk_en_r<=0;
                                        end
                       S:begin
                                        clk_en_r<=1;
                                        tx_r<=0;
                                        rd_r<=0;
                                end
                        B0:tx_r<=q;
                        B1:tx_r<=q;
                        B2:tx_r<=q;
                        B3:tx_r<=q;                       
                        B4:tx_r<=q;
                        B5:tx_r<=q;
                        B6:tx_r<=q;
                        B7:tx_r<=q;       
                        E: tx_r<=1;
                endcase
end

assign TX=tx_r;
assign clk_en=clk_en_r;               
assign rd=rd_r;
               
endmodule

aammoo 发表于 2012-4-12 11:08:53

把报错贴上来

hy2515131 发表于 2012-4-12 11:45:44

注释很少,格式不太好,看起来挺麻烦的

xtx 发表于 2012-4-12 15:28:20

aammoo 发表于 2012-4-12 11:08 static/image/common/back.gif
把报错贴上来

没有报错,就是在 state machine viewer 中无法看到状态转移图,感觉纳闷。

xtx 发表于 2012-4-12 15:29:19

hy2515131 发表于 2012-4-12 11:45 static/image/common/back.gif
注释很少,格式不太好,看起来挺麻烦的

主要是一个串口发送模块,实例化了一个波特率产生模块和FIFO模块,然后就是3段式状态机。

xtx 发表于 2012-4-12 20:42:58

问题解决
always@(current_state or ena)
begin
next_state = current_state;//***************************sign1
case(current_state)
s1:
begin
if(ena==0)
next_state=s1;
else
next_state=s2;
end
s2:
next_state=s3;
s3:
next_state=s1;
endcase
end

就是要在组合逻辑中加入 :next_state = current_state;这样就能识别了

xtx 发表于 2012-5-3 22:38:46

Quartus II中状态机的编写规则 发布时间:2008-04-05 10:44:15   昨天写了个动态数码管显示,在MAX+PlusII下是可以的但在QuartusII下却发现状态好像不能转移,于是在网上查了查,并结合QuartusII帮助文档算是发现原因了。现将帮助文档中关于VHDL在QuartusII中编写状态机的条件翻译一下,水平有限,各位批评指正。



编译器识别状态机的条件:



1.表现状态机的信号或变量必须为枚举类型。



2.状态转移必须由clk触发,并且是用IF语句检测的上升沿进行转移。



3.状态转移到下一个状态由CASE语句判断



4.所有信号,变量赋值都要放在状态机进程里进行。



5.状态机的状态必须多于两个状态。



原文如下:



The Compiler recognizes state machines and reports them as such in the



State Machines section of the Report window only if all of the following



conditions are met:
1.The type of the signal or variable that represents the state machine



must be an enumerated type.
2.The Process Statement that describes the state machine must be



clocked, and must contain an If Statement that checks for a positive



edge of the clk control signal.
3.The state machine behavior, that is, the next-state logic, is defined



with Case Statements at the top level.
4.All assignments to the signal or variable that represents the state



machine are within the process.
5.The state machine must have more than two states.

xtx 发表于 2012-5-3 22:39:17

希望遇到同样问题的网友看看

xtx 发表于 2012-5-4 09:14:56

Quartus II中对状态机的设计有一些特别的规定,如果不了解这些规定在设计的时候常常使人产生困惑。
    对于Verilog HDL这些规定是:
    1.The Always Construct that describes the state machine is clocked.
    2.All assignments to the signal or variable that represents the state machine are within the Always Construct.
    3.The state machine has more than two states.
    4.The state register is not used as an output of the module.
    5.The state transition logic does not use arithmetic operators. For example, this condition is not met if the state transition logic uses the expression next_state <= state + 1;, which contains the arithmetic operator +.
    其中第5.条是一条很强的约束,从各种程序测试结果来看,状态变量(state和next_state)除了可以用于'case (state)'语句以及条件判别'(state==s1)'和状态参数赋值'next_state=s1'以外,不能用于其它的操作,这就是为什么常常不能综合成状态机的原因。我们可以这样来判断:将状态变量(state和next_state)和状态参数(s1,s2...)看成一些特殊的变量或者标识符,可以用状态参数或者状态变量对另外的状态变量赋值或者判别它们是否相等,但是它们不是'数',一旦将它们看成'数',例如state=s1+1或者state=1'b1(等数学操作)就不能综合成状态机。因此传统one-hot编码程序风格(位索引方式):
    case (1'b1) begin
      state:
      ...
      end
    不能综合成状态机。
    对于VHDL相应规定是:
    1.The type of the signal or variable that represents the state machine must be an enumerated type.
    2.The Process Statement that describes the state machine must be clocked, and must contain an If Statement that checks for a positive edge of the clk control signal.
    3.The state machine behavior, that is, the next-state logic, is defined with Case Statements at the top level.
    4.All assignments to the signal or variable that represents the state machine are within the process.
    5.The state machine must have more than two states.
    其中第1.条与Verilog HDL中的第5.条类似,也排除了传统one-hot编码程序风格(位索引方式)。

    Quartus II中状态机的编码风格是可选择的,通过状态机处理逻辑选项,可以选择四种方式:
    1.自动格式:编译程序自动选择最好的状态机编码格式(缺省格式);
    2.最少位格式:用最少位数的状态机编码格式;
    3.one-hot格式:one-hot一般译成一位热码格式,传统的格式是每种状态中只有一位是'1'其它位是'0',而Quartus II中与此不同,Quartus II的reset状态是全'0',其它状态有两位是'1'(其中最低位是'1'),其它位是'0',这样的效果与传统的格式是一样的,每一位可以定一种状态,好处是上电的时候自动设置成reset状态(全'0');
    4.用户编码格式:用用户写的状态机编码格式(可能编译程序还会修改其中的一些编码);

    Quartus II中还可以选择是否提取Verilog或者VHDL状态机:
    1.提取状态机:编译程序用特殊技术优化状态机减小面积和改进性能(缺省方式)。这时综合将报告状态机的状态数和状态机的编码结果,在RTL Viewer中可以看到状态机,这就是我们说的综合成了状态机;
    2.不提取状态机:编译程序用通常方式优化状态机。这时综合报告不报告状态机的状态数和编码结果,在RTL Viewer中看不到状态机,但是只要程序是正确的,实际还是综合成了状态机存,运行的结果也是正确的,传统one-hot编码程序风格(位索引方式)最好选择此选项。

    综上所述,Quartus II缺省设置时已经用特殊技术优化状态机减小面积和改进性能,它与具体状态编码格式关系不大,我们在设计状态时应该按照Quartus II的规则,应重点关注状态机的功能设计,编码格选一种能综合成状态机的既可,同时注意将reset状态设置为全'0'。
    下面是Quartus II的两个简单例子:
   
(The Verilog HDL state machine example.)

module state_machine (clk, in, reset, out);
   input   clk, in, reset;
   outputout;
   reg   out;
   reg   state;
            parameter S0 = 0, S1 = 1, S2 = 2;
   always @ (state) begin
      case (state)
         S0:
            out = 2'b01;
         S1:
            out = 2'b10;
         S2:
            out = 2'b11;
         default:
            out = 2'b00;
         endcase
   end
   always @ (posedge clk or posedge reset) begin
      if (reset)
         state <= S0;
      else
         case (state)
            S0:
               state <= S1;
            S1:
               if (in)
                  state <= S2;
               else
                  state <= S1;
            S2:
               if (in)
                  state <= S0;
               else
                  state <= S1;
         endcase
   end
endmodule


(The VHDL state machine example.)

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;

ENTITY state_machine IS
   PORT(
      clk      : IN   STD_LOGIC;
      input    : IN   STD_LOGIC;
      reset    : IN   STD_LOGIC;
      output   : OUTSTD_LOGIC_VECTOR(1 downto 0));
END state_machine;
ARCHITECTURE a OF state_machine IS
   TYPE STATE_TYPE IS (s0, s1, s2);
   SIGNAL state   : STATE_TYPE;
BEGIN
   PROCESS (clk, reset)
   BEGIN
      IF reset = '1' THEN
         state <= s0;
      ELSIF (clk'EVENT AND clk = '1') THEN
         CASE state IS
            WHEN s0=>
               IF input = '1' THEN
                  state <= s1;
               ELSE
                  state <= s0;
               END IF;
            WHEN s1=>
               IF input = '1' THEN
                  state <= s2;
               ELSE
                  state <= s1;
               END IF;
            WHEN s2=>
               IF input = '1' THEN
                  state <= s0;
               ELSE
                  state <= s2;
               END IF;
         END CASE;
      END IF;
   END PROCESS;
   PROCESS (state)
   BEGIN
      CASE state IS
         WHEN s0 =>
            output <= "00";
         WHEN s1 =>
            output <= "01";
         WHEN s2 =>
            output <= "10";
      END CASE;
   END PROCESS;
END a;

Chouc 发表于 2012-5-5 17:01:33

自己写的状态机么?Quartus ii里面自己写的one-hot状态机(位索引方式)是可以综合的。它自带的状态机代码生成器我没用过

xtx 发表于 2012-5-5 23:28:30

搞定了 ,采用三段式状态机写法就行,之前我的状态变量有点问题,所以如果软件不能识别状态机的话,看来以后还是要多检查检查的。

chunri 发表于 2012-5-13 09:20:39

xtx 发表于 2012-5-3 22:38 static/image/common/back.gif
Quartus II中状态机的编写规则 发布时间:2008-04-05 10:44:15   昨天写了个动态数码管显示, ...

学习了!!{:smile:}

shangdawei 发表于 2012-5-13 21:00:17

总结的很好, 学习了.

wodish 发表于 2012-5-14 09:50:42

这个非常的有用 谢谢

king10 发表于 2012-5-14 11:00:13

楼主分析的很详尽啊!学习了!

zhangyunbo 发表于 2013-5-2 17:58:48

mark一下

bdzhaojing 发表于 2014-9-17 10:28:17

xtx 发表于 2012-5-4 09:14
Quartus II中对状态机的设计有一些特别的规定,如果不了解这些规定在设计的时候常常使人产生困惑。
    对 ...

标记:三段式状态机
页: [1]
查看完整版本: 求助quartus 无法识别三段式状态机