微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 求助大虾,状态机为什么没有跳变

求助大虾,状态机为什么没有跳变

时间:10-02 整理:3721RD 点击:
今天写了一个spi的发送程序,是在发送信息之前发送4个字节的操作码,用的是状态机,但是为什么next_state就没有跳到第一个状态cmd_send里面去?请教大家
`timescale 1 ns / 1 ns
module spi(rst ,clk ,wr ,rd ,datain ,spics ,spido);
input rst;
input clk;
input wr;
input rd;
input [7:0]datain;
output spics;
output spido;
reg spics;
reg spido;
reg [8:0]spistate;
reg [8:0]next_state;
reg receive;
reg [7:0]dsend;
reg [3:0]cnt;
reg [8:0]state_cnt;
reg [7:0] send_cmd;
reg [7:0] receive_cmd;
reg [7:0] ad1, ad2, ad3;
reg [7:0] adr1, adr2, adr3;
parameter idle = 9'b000000001;
parameter cmd_send = 9'b000000010;
parameter a1 = 9'b000000100;
parameter a2 = 9'b000001000;
parameter a3 = 9'b000010000;
parameter cmd_receive = 9'b000100000;
parameter ar1 = 9'b001000000;
parameter ar2 = 9'b010000000;
parameter ar3 = 9'b100000000;
parameter send = 9'b100000001;
always@(posedge[/email] clk or negedge rst)
     if(wr == 1 && rd == 0)
        spics <= 0;
     else if(wr == 0 && rd == 1)
          begin
               receive <= 1;
               spics <= 0;
          end
     else spics <= 1;
         
always@(posedge[/email] clk or negedge rst)
begin
     if(!rst)
          spistate <= idle;
     else
          next_state <= spistate;
end
//always@(spistate or cnt or wr or rd)
always@(posedge[/email] clk or negedge rst)
begin
     next_state = idle;
     case(spistate)
         idle:     begin
                        if(wr == 1 && rd == 0) next_state = cmd_send;
                   else if(wr == 0 && rd == 1) next_state = cmd_receive;
                   else next_state = idle;
                   end
         cmd_send:   next_state = send;
         a1:         next_state = send;
         a2:         next_state = send;
         a3:         next_state = send;
         cmd_receive:next_state = send;
         ar1:        next_state = send;
         ar2:        next_state = send;
         ar3:        next_state = send;
         send:       if(cnt == 4'b0111) next_state = state_cnt;
         default:    next_state = idle;
    endcase
end
always@(posedge[/email] clk or negedge rst)
begin
     if(!rst)
     begin
          state_cnt <= 9'b0000000001;
          cnt <= 0;
          dsend <= 0;
          spics <= 0;
          spido <= 0;
     end
     else case(next_state)
               idle:      if(wr == 1 && rd == 0)  dsend <= 8'h82;
                          else if(wr == 0 && rd == 1) dsend <= 0;
               cmd_send:  begin
                               //send_cmd <= 8'h82;
                               state_cnt <= state_cnt<<1;
                          end
               a1:        begin
                               ad1 <= 8'h2c;
                               state_cnt <= state_cnt<<1;
                          end
               a2:        begin
                               ad2 <= 8'h00;
                               state_cnt <= state_cnt + 1;
                          end
               a3:        begin
                               ad3 <= 8'h03;
                               state_cnt <= state_cnt + 1;
                          end
            cmd_receive:  begin
                               receive_cmd <= 8'h0B;
                               state_cnt <= state_cnt + 1;
                          end
               ar1:       begin
                               adr1 <= 8'h2c;
                               state_cnt <= state_cnt + 1;
                          end
               ar2:       begin
                               adr2 <= 8'h00;
                               state_cnt <= state_cnt + 1;
                          end
               ar3:       begin
                               adr3 <= 8'h03;
                               state_cnt <= state_cnt + 1;
                          end
               send:      if(cnt == 4'b0111)
                             cnt <= 0;
                          else
                              begin
                                   spido <= dsend[7];
                                   dsend <= dsend<<1;
                                   cnt <= cnt + 1;
                              end
         endcase
end                           
endmodule

把begin
     if(!rst)
          spistate <= idle;
     else
          next_state <= spistate;
end
改为
begin
     if(!rst)
          spistate <= idle;
     else
           spistate<= next_state;
end

把begin
     if(!rst)
          spistate <= idle;
     else
          next_state <= spistate;
end
改为
begin
     if(!rst)
          spistate <= idle;
     else
           spistate<= next_state;
end

2# allenyey
这样啊,但是一般教材上的三段式状态机,就是把现状态赋给下一状态,这是为什么呢?

看不懂

理解不够,你得和下一段程序-状态跳转那个合起来理解

你的状态机写错了哦,用边沿触发需要用<=赋值,并且case语句需要用default,否则就是latch

好,谢谢!

学习了。

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

网站地图

Top