Verilog FSM stuck on one State forever - Verilog FSM stuck on one State forever
I am developing a fsm to latch on to incoming data and compute its average in verilog, but my fsm seems to be just stuck at one state. Although the simulation shows it did shifted perfectly in previous states, but it is stuck at "filter_data_64" state . See complete code below : `timescale 1ps/1ps module amf_ctrl #( parameter data_bits = 64, parameter average_cont = 16 ) ( input clk, input rst, input vld, input last, output rdy, input [7:0] data_flit, input [5:0] valid_bytes, output [7:0] filter_data_o, output done ); reg [7:0] data_buff [data_bits-1:0]; reg [data_bits-1:0] byte_cont; reg [7:0] avg_cont, byte_cont_64, filter_data; reg [3:0] state; reg [3:0] nextstate; reg [7:0] r0, r1, r2, r3, sum_reg; reg [5:0] valid_no; reg done_sig, rdy_sig, vld_dly, vld_pe, byte_64_en; assign done = done_sig; assign filter_data_o = filter_data; assign rdy = rdy_sig; //////////////////////////////////////// parameter idle = 4'b0000, buffer_data = 4'b0001, buffer_data_1 = 4'b0010, filter_data_state = 4'b0011; parameter Avg_cal = 4'b0100, Sum_data = 4'b0101, Shift_data = 4'b0110, Result_data = 4'b0111; parameter filter_data_64 = 4'b1000, Sum_data_64 = 4'b1001, Shift_data_64 = 4'b1010, Result_data_64 = 4'b1011; //////////////////////////// always @ (posedge clk) begin vld_dly <= vld; end //////////////////////////// // Detect no of valid Bytes // always @ (posedge clk or negedge rst) begin if (~rst) begin valid_no <= 5'b00000; byte_64_en <= 1'b0;end else if (last) begin valid_no <= valid_bytes; if(valid_bytes == 0) byte_64_en <= 1'b1;end else begin byte_64_en <= 1'b0; end end //////////////////////////// always @(posedge clk or negedge rst) if ((~rst)||(byte_cont==data_bits-1)) byte_cont <= 0; else if (!vld & vld_dly) begin byte_cont <= byte_cont + 1; data_buff[byte_cont] <= data_flit; end //////////////////////////////////// always @(posedge clk) begin if (~rst) begin done_sig <= 1'b0; rdy_sig <= 1'b0 ; sum_reg <= 8'h00; filter_data <= 8'h00; avg_cont <= 8'h00; state <= idle; end else begin case(state) idle:begin if(vld)begin rdy_sig <= 1'b1; nextstate <= buffer_data; end else if (last)begin rdy_sig <= 1'b0; nextstate <= filter_data_state;end else begin rdy_sig <= 1'b0; nextstate <= idle;end end //////////////////////////////////// buffer_data:begin rdy_sig <= 1'b0; nextstate <= idle; end ////////////////////////////////// filter_data_state:begin //if(byte_64_en)begin //rdy_sig <= 1'b0; //avg_cont <= average_cont; //byte_cont_64 <= data_bits - 1; //nextstate <= filter_data_64;end //else if (byte_64_en)begin //else begin //rdy_sig <= 1'b0; nextstate <= Avg_cal;//end end ////////////////////////////////// Avg_cal:begin if(valid_no == 0)begin done_sig <= 1'b0; nextstate = idle; end else begin done_sig <= 1'b0; r0 <= data_buff[valid_no]; r1 <= data_buff[valid_no - 1]; r2 <= data_buff[valid_no - 2]; r3 <= data_buff[valid_no - 3]; valid_no <= valid_no - 4; nextstate = Sum_data;end end ///////////////////////////////// Sum_data: begin sum_reg <= r0 + r1 + r2 +r3; nextstate <= Shift_data; end ///////////////////////////////// Shift_data: begin sum_reg <= sum_reg >> 2; nextstate <= Result_data; end ///////////////////////////////// Result_data: begin filter_data <= sum_reg; done_sig <= 1'b1; nextstate <= Avg_cal; end ////////////////////////////// filter_data_64:begin if(avg_cont == 0)begin done_sig <= 1'b0; nextstate <= idle; end else begin done_sig <= 1'b0; r0 <= data_buff[byte_cont_64]; r1 <= data_buff[byte_cont_64 - 1]; r2 <= data_buff[byte_cont_64 - 2]; r3 <= data_buff[byte_cont_64 - 3]; byte_cont_64 <= byte_cont_64 - 4; avg_cont <= avg_cont - 1; nextstate <= Sum_data_64;end end //////////////////////////////////// Sum_data_64: begin sum_reg <= r0 + r1 + r2 +r3; nextstate <= Shift_data_64; end /////////////////////////////////// Shift_data_64: begin sum_reg <= sum_reg >> 2; nextstate <= Result_data_64; end ///////////////////////////////// Result_data_64: begin filter_data <= sum_reg; done_sig <= 1'b1; nextstate <= filter_data_64; end endcase end end endmodule /////////////////////////////////////////// /* Verilog test bench : it simulates AXI slave as per document "AMBA® 4 AXI4-Stream Protocol Version: 1.0 Specification" */ ////////////////////////////////////////////////////////////////////////////// `timescale 1ps/1ps module tb_amf_ctrl(); reg tb_clk; // To drive input "d" of the DUT reg tb_rst; // To drive input "en" of the DUT reg tb_vld; // To drive input "rstn" of the DUT reg tb_last; // To ensure q has not changed when en=0 wire tb_rdy; // To tap output "q" from DUT wire tb_done; reg [7:0] tb_data_flit; reg [5:0] tb_vld_bytes; wire [7:0] tb_filter_data_o; amf_ctrl DUT ( .clk(tb_clk), .rst(tb_rst), .vld(tb_vld), .last(tb_last), .rdy(tb_rdy), .data_flit(tb_data_flit), .valid_bytes(tb_vld_bytes), .filter_data_o(tb_filter_data_o), .done(tb_done) ); // Clock // initial tb_clk = 0; always #5 tb_clk = ~tb_clk; ///////////////////////// ////////// initial begin tb_rst <= 1'b0; tb_vld <= 1'b0; tb_last <= 1'b0; tb_data_flit <= 8'h00; tb_vld_bytes <= 6'b000000; #30; tb_rst <= 1'b1; #10; //1st byte tb_vld <= 1'b1; tb_data_flit <= 8'h11; #20; tb_vld <= 1'b0; #20; //2nd byte tb_vld <= 1'b1; tb_data_flit <= 8'h02; #20; tb_vld <= 1'b0; #20; //3rd byte tb_vld <= 1'b1; tb_data_flit <= 8'h03; #20; tb_vld <= 1'b0; #20; //4th byte tb_vld <= 1'b1; tb_data_flit <= 8'h04; #20; tb_vld <= 1'b0; #20; //// Last //// #10; tb_last <= 1'b1; tb_vld_bytes <= 6'b000100; //tb_vld_bytes <= 6'b000000; #50; $finish(2); end endmodule
Replies:
Re: Verilog FSM stuck on one State forever
Thank you for acknowledging the solution provided. I'm pleased to know that your question has been addressed. Now, I will transitioning this thread to community support. If you have any further questions or concerns, please don't hesitate to reach out. Please login to https://supporttickets.intel.com/s/?language=en_US , view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you on your follow-up questions. Thank you and have a great day! Best Regards, Richard Tan
Replies:
Re: Verilog FSM stuck on one State forever
HI Richard, Yes changed the fsm to have two separate always block : //////////////////////////////////// always @ (posedge clk) begin if (~rst) begin state <= idle;end else begin state <= nextstate;end end //////////////////////////////////// always @(*) begin nextstate <= idle; case(state) idle:begin if(vld)begin rdy_sig <= 1'b1; nextstate <= buffer_data; end else if (last)begin rdy_sig <= 1'b0; valid_no_reg <= valid_no; nextstate <= filter_data_state;end
Replies:
Re: Verilog FSM stuck on one State forever
Dropping a note to ask if my last reply was helpful to you. Do you able to resolve the issue? Regards, Richard Tan
Replies:
Re: Verilog FSM stuck on one State forever
You have nextstate in your case statement, but state never updates to nextstate. Fix it by adding a sequential block to update state at every clock edge. always @(posedge clk) begin if (~rst) state <= idle; else state <= nextstate; end I would recommend to checkout ' Two Always Block FSM coding style ' from the article below. It uses two separate always blocks: State Register Block: A sequential (always_ff ) block that updates the current state (state_reg) on the clock edge. Next State & Output Logic Block: A combinational ( always_comb) block that determines the next state and the outputs based on the current state and inputs. http://www.sunburst-design.com/papers/CummingsSNUG2019SV_FSM1.pdf Regards, Richard Tan
Replies:
Re: Verilog FSM stuck on one State forever
Here is the simulation results - 2025-02-19
external_document