# Helo with Verilog FSM

Status
Not open for further replies.

#### Sink0

##### Full Member level 6
Hi, i have a very weird behavior on a Veriglog code and i need some help.

Just a fast exaplanation. It is a Wishbone master that should perform N reads, and the number N is defined by a number that i load on the r_counter.

The code is the following:

Code:
include "network_controller_constants.v"

module NETWORK_CONTROLLER_WB_MASTER
(
CLK_I,
RST_I,

MINT_O,
MDAT_O,
MDAT_I,
MSEL_O,
MCYC_O,
MSTB_O,
MWE_O,
MCAB_O,
MACK_I,
MRTY_I,
MERR_I,

tx_b1_offset,
tx_b2_offset,
rx_b1_offset,
rx_b2_offset,

r_cnt_reg,
r_cmnd_flag,

tx_b_1_int,
tx_b_2_int,
rx_b_1_int,
rx_b_2_int,

tx_b_1_over,
tx_b_2_over,
rx_b_1_over,
rx_b_2_over,

r_counter_empty,

r_bus_data_in,
data_sent,

leds,

MEMORY
);

input			   	CLK_I;
input             RST_I;

output				MINT_O;
input    [31:0]  	MDAT_I;
output   [31:0]  	MDAT_O;
output   [3:0]   	MSEL_O;
output            MCYC_O;
output            MSTB_O;
output            MWE_O;
output            MCAB_O;
input            	MACK_I;
input            	MRTY_I;
input            	MERR_I;

input		[31:0]	tx_b1_offset;
input		[31:0]	tx_b2_offset;
input		[31:0]	rx_b1_offset;
input		[31:0]	rx_b2_offset;

output				tx_b_1_over;
output				tx_b_2_over;
output				rx_b_1_over;
output				rx_b_2_over;

input		[31:0]	r_cnt_reg;
input					r_cmnd_flag;

input					tx_b_1_int;
input					tx_b_2_int;
input					rx_b_1_int;
input					rx_b_2_int;

output				r_counter_empty;

output	[31:0]	MEMORY;

input		[31:0]	r_bus_data_in;
output				data_sent;

output	[3:0]		leds;

parameter WB_IDLE	= 	  5'b00001;
parameter WB_WRITING	= 5'b00010;
parameter WB_INT_ACK	= 5'b01000;
parameter WB_W_WAIT	= 5'b10000;

reg		[31:0]	MDAT_O;
wire		[31:0]	MDAT_I;
wire		[3:0]		MSEL_O;
reg					MCYC_O;
reg					MSTB_O;
wire					MWE_O;
reg					MCAB_O;
wire					MACK_I;
wire					MRTY_I;
wire					MINT_O;

reg		[31:0]	r_counter = 0;
reg		[4:0]		state_machine = WB_IDLE;
reg		[4:0]		next_state = WB_IDLE;
reg					int_ack_done = 0;
reg					write_done = 0;
reg					r_counter_empty = 1'b1;
wire					wb_int_gen;

reg					tx_b_1_over = 0;
reg					tx_b_2_over = 0;
reg					rx_b_1_over = 0;
reg					rx_b_2_over = 0;

reg		[31:0]	MEMORY;
wire		[31:0]	r_bus_data_in;
reg					data_sent = 0;

//###########################################################

reg 		[3:0]		MRTY_C = 0;
reg		[3:0]		MACK_C = 0;
reg		[3:0]		leds;

//###########################################################

assign MSEL_O = 4'b1111;
assign MINT_O = wb_int_gen;

assign	wb_int_gen = 	tx_b_1_int|
tx_b_2_int|
rx_b_1_int|
rx_b_2_int;

/*##################################################################################
############################ state_machine CONTROL #################################
##################################################################################*/

always@(state_machine or r_counter or tx_b_1_int or tx_b_2_int or write_done or int_ack_done or DATA_READY)
begin
tx_b_1_over = 1'b0;
tx_b_2_over = 1'b0;
rx_b_1_over = 1'b0;
rx_b_2_over = 1'b0;
case (state_machine)
WB_IDLE :
begin
if(r_counter > 32'h00000000)
begin
end
end
begin
if(r_counter == 32'h00000000)
begin
//next_state = WB_INT_ACK;
next_state = WB_IDLE;
rx_b_1_over = 1'b1;
end
end
WB_WRITING :
begin
next_state = WB_W_WAIT;
end
WB_INT_ACK :
begin
if(int_ack_done)
next_state = WB_IDLE;
end
WB_W_WAIT :
begin
if(write_done)
begin
next_state = WB_INT_ACK;
tx_b_1_over = 1'b1;
end
end
default:begin
next_state = WB_IDLE ;
end
endcase
end

/*##################################################################################
############################ state_machine TIMING ##################################
##################################################################################*/

always@(posedge CLK_I)
begin
state_machine = next_state;
end

/*##################################################################################
############################ int_ack_done CONTROL ##################################
##################################################################################*/

always@(posedge CLK_I)
begin
int_ack_done = 1'b0;
if(state_machine == WB_INT_ACK)
begin
if(MCYC_O && MACK_I)
int_ack_done = 1'b1;
end
end

/*##################################################################################
############################# write_done CONTROL ###################################
##################################################################################*/

always@(posedge CLK_I)
begin
write_done = 1'b0;
if(state_machine == WB_W_WAIT)
begin
if(MCYC_O && MACK_I)
write_done = 1'b1;
end
end

always@(posedge CLK_I)
begin
case (next_state)
WB_IDLE : begin
if(r_cmnd_flag)
begin
r_counter <= r_cnt_reg;
end
end
if(MCYC_O && MACK_I)
begin
if(r_counter > 0)
begin
r_counter <= r_counter - 32'h1;
end
end
end
WB_WRITING : begin
if(MCYC_O && MACK_I)
begin
data_sent = ~data_sent;
end
end
endcase
//	end
end

always@(negedge CLK_I)
begin
case(next_state)
WB_IDLE: begin
MCAB_O <= 1;
end
MCAB_O <= 1;
end
WB_WRITING: begin
MCAB_O <= 1;
end
WB_INT_ACK: begin
MCAB_O <= 0;
end
WB_W_WAIT: begin
MADR_O[30:0] <= tx_b1_offset[30:0] + DUMMY_READ_ADDR;
MCAB_O <= 0;
end
default: begin
MCAB_O <= 1;
end
endcase
end

always@(negedge CLK_I)
begin
if(next_state == WB_IDLE)
begin
MSTB_O <= 1'b0;
MCYC_O <= 1'b0;
end
else
begin
MSTB_O <= 1'b1;
MCYC_O <= 1'b1;
end
end

always@(r_counter)
begin
r_counter_empty = (r_counter > 0)? 1'b0 : 1'b1;
end

(
.Trigger				(r_counter_empty),
.Clock				(CLK_I)
);

endmodule
The simulation works ok... but when i implement that on a Spartan III i got a wird behavior on my FSM. For some reason the state keeps jumping from IDLE to READING, and from READING to IDLE, but the r_counter is not moving... so if i write 5 on r_counter.. it stay on 5 but the states keep moving. Any idea of what could couse that? As i do not have chipscope i am using 4 seven seg. display and 3 leds to debug. On the display i am looking to the counter, and at the leds on the first 3 elements of the next_state array, so i can see if it stay at IDLE or READING, but the result is that i can see that the the first and third led are ON, but not wih full power... as it was being driven by a PWM signal, so i could supose that the FSM keeps jumping between both states...

I will not give any further detail now becouse they are irrelevant as all teh rest looks ok, and i can see the r_counter value...

Thank you!

#### permute

Code:
always@(posedge CLK_I)
begin
state_machine = next_state;
end`
You shouldn't do this, as it can break the simulation (but silently). notice that "state_machine" is in other processes also clocked by CLK_I. In this case there is no reason to believe these other blocks are using the correct value for "state_machine". the same goes for every other signal assigned within a clocked always block. you must use non-blocking logic if the signal is to be used outside of the always block. Remember, Verilog doesn't define an execution order for the always blocks -- the program might go from top to bottom, or might maintain a hash table, or might be multi-threaded. This means that the simulation might work once, but not after minor changes are made to the code. It's better to avoid this issue.

you should probably try to avoid making next_state a latch. currently, there are several cases where next_state isn't assigned and gets the default "next_state = next_state", instead of "next_state = state_machine" or "next_state = SOME_STATE".

You should take some time to build some better debug tools. eg, a basic FIFO+RS232. That way you can at least have better access to debugging information. failing that, an oscilloscope would be useful. I don't see any immediate things that would exactly explain your situation.

Sink0

### Sink0

Points: 2

#### Sink0

##### Full Member level 6
Damn you are a genious... i forgot to assign a latch on my state machine!! Yea that is the reason for sure... so it always goes to an unknown state and get back to IDLE...

Yea i really should save a time to make a simple serial debug block.. i just dont want to loose time making a simple software to take a look at the data.. any advice on free software that i could digital data from a simple text file?

Hmmm .. about the blocking assignment, thats weird... i would expect that a single statement inside an always block would behave the same if it is blocking or not.. actually, i as was expecting taht it would be treated independently from others blocks.. so it is just considered "blocking inside that specific block"

Any way.. i lost like 2 days on that stupid mistake.. i got a lot of work untill i achieve a good knowhow haha.. thank you!

Status
Not open for further replies.

Replies
20
Views
5K
Replies
7
Views
1K
Replies
3
Views
2K
Replies
13
Views
3K
Replies
10
Views
9K