I've got a trouble

J

JY

Guest
I made a verilog code for CPLD.
I'm using Altera's QuartusII web edition as a tool.
However, some statements are not working.
Such as, cnt = cnt + 1 and if (cnt < 24) ...
What's wrong?

Some of my verilog code is like this:

module control (clk, reset_l, strobe_l, in_data, out_data, sload,
clk_o, le_o);

// input signal
input clk, reset_l;
input strobe_l;
input [5:0] in_data;

// output signal
output sload, clk_o, le_o;
output [5:0] out_data;
//
reg sload, clk_o, le_o;
reg [5:0] out_data;
reg [4:0] cnt;
reg [3:0] state, next_state;
reg [2:0] init;

.....

initial begin
state = `F_LOAD;
next_state = `F_LOAD;
out_data = 0;
cnt = 0;
init = 0;
clk_o = 0;
le_o = 0;
sload = 0;
end

always @(posedge clk)
begin
state = next_state;
end

always @(state or reset_l or cnt or init or strobe_l)
begin
if (!reset_l) begin
next_state = `F_LOAD;
end
else
case (state)
`F_LOAD: begin
..
init = 0;
next_state = `START;
end
`R_LOAD: begin
...
init = 1;
next_state = `START;
end
`LOAD_00: begin
....
init = 2;
next_state = `START;
end
`N_LOAD: begin
....
init = 2;
next_state = `START;
end
`START: begin
cnt = 0; // clock counter
....
next_state = `CLK_H;
end
`CLK_H: begin
clk_o = 1; // clock high
next_state = `CLK_L;
end
`CLK_L: begin
clk_o = 0; // clock low
cnt = cnt + 1;
if (cnt > 24)
next_state = `LE_H;
else begin
next_state = `CLK_H;
end
`LE_H: begin
le_o = 1;
next_state = `LE_L;
end
`LE_L: begin
le_o = 0;
if (init == 0)
next_state = `R_LOAD;
else if (init == 1)
next_state = `LOAD_00;
else if (init == 2)
next_state = `STB_WAIT;
end
`STB_WAIT: begin
if (strobe_l)
next_state = `STB_WAIT;
else
next_state = `N_LOAD;
end
endcase
end
endmodule
 
JY wrote:
I made a verilog code for CPLD.
I'm using Altera's QuartusII web edition as a tool.
However, some statements are not working.
Such as, cnt = cnt + 1 and if (cnt < 24) ...
What's wrong?

Some of my verilog code is like this:

module control (clk, reset_l, strobe_l, in_data, out_data, sload,
clk_o, le_o);

// input signal
input clk, reset_l;
input strobe_l;
input [5:0] in_data;

// output signal
output sload, clk_o, le_o;
output [5:0] out_data;
//
reg sload, clk_o, le_o;
reg [5:0] out_data;
reg [4:0] cnt;
reg [3:0] state, next_state;
reg [2:0] init;

....

initial begin
state = `F_LOAD;
next_state = `F_LOAD;
out_data = 0;
cnt = 0;
init = 0;
clk_o = 0;
le_o = 0;
sload = 0;
end
Whooops -- you fell into the trap, thinking that initial statements are
the equivalent of a reset. This is bad.

always @(posedge clk)
begin
state = next_state;
end

always @(state or reset_l or cnt or init or strobe_l)
begin
if (!reset_l) begin
next_state = `F_LOAD;
end
else
case (state)
`F_LOAD: begin
..
init = 0;
next_state = `START;
end
`R_LOAD: begin
...
init = 1;
next_state = `START;
end
`LOAD_00: begin
....
init = 2;
next_state = `START;
end
`N_LOAD: begin
....
init = 2;
next_state = `START;
end
`START: begin
cnt = 0; // clock counter
....
next_state = `CLK_H;
end
`CLK_H: begin
clk_o = 1; // clock high
next_state = `CLK_L;
end
`CLK_L: begin
clk_o = 0; // clock low
cnt = cnt + 1;
if (cnt > 24)
next_state = `LE_H;
else begin
next_state = `CLK_H;
end
`LE_H: begin
le_o = 1;
next_state = `LE_L;
end
`LE_L: begin
le_o = 0;
if (init == 0)
next_state = `R_LOAD;
else if (init == 1)
next_state = `LOAD_00;
else if (init == 2)
next_state = `STB_WAIT;
end
`STB_WAIT: begin
if (strobe_l)
next_state = `STB_WAIT;
else
next_state = `N_LOAD;
end
endcase
end
endmodule
Looks like you fell into the trap of using two always blocks for your
state machine. Your counter is combinatorial and built with blocking
assignments. I'll bet this statement:

`CLK_L: begin
clk_o = 0; // clock low
cnt = cnt + 1;
if (cnt > 24)
next_state = `LE_H;
else begin
next_state = `CLK_H;
end

isn't working as you expect. Think about when the counter updates.
Think about how the comparison works.

Make the entire state machine a single, synchronous always block using
non-blocking assignments. Understand why this is better.

-a
 
Thank you for your comments.
However, I don't understand how I correct this problem.
Actually, I am a kind of beginner about verilog.
Could you tell me how to do?
So far, the variable cnt is not increased with cnt <= cnt + 1;
It displayed something wrong value or 0...

Thank you in advance.

Jae-Yang Park

Andy Peters wrote:
JY wrote:
I made a verilog code for CPLD.
I'm using Altera's QuartusII web edition as a tool.
However, some statements are not working.
Such as, cnt = cnt + 1 and if (cnt < 24) ...
What's wrong?

Some of my verilog code is like this:

module control (clk, reset_l, strobe_l, in_data, out_data, sload,
clk_o, le_o);

// input signal
input clk, reset_l;
input strobe_l;
input [5:0] in_data;

// output signal
output sload, clk_o, le_o;
output [5:0] out_data;
//
reg sload, clk_o, le_o;
reg [5:0] out_data;
reg [4:0] cnt;
reg [3:0] state, next_state;
reg [2:0] init;

....

initial begin
state = `F_LOAD;
next_state = `F_LOAD;
out_data = 0;
cnt = 0;
init = 0;
clk_o = 0;
le_o = 0;
sload = 0;
end

Whooops -- you fell into the trap, thinking that initial statements are
the equivalent of a reset. This is bad.

always @(posedge clk)
begin
state = next_state;
end

always @(state or reset_l or cnt or init or strobe_l)
begin
if (!reset_l) begin
next_state = `F_LOAD;
end
else
case (state)
`F_LOAD: begin
..
init = 0;
next_state = `START;
end
`R_LOAD: begin
...
init = 1;
next_state = `START;
end
`LOAD_00: begin
....
init = 2;
next_state = `START;
end
`N_LOAD: begin
....
init = 2;
next_state = `START;
end
`START: begin
cnt = 0; // clock counter
....
next_state = `CLK_H;
end
`CLK_H: begin
clk_o = 1; // clock high
next_state = `CLK_L;
end
`CLK_L: begin
clk_o = 0; // clock low
cnt = cnt + 1;
if (cnt > 24)
next_state = `LE_H;
else begin
next_state = `CLK_H;
end
`LE_H: begin
le_o = 1;
next_state = `LE_L;
end
`LE_L: begin
le_o = 0;
if (init == 0)
next_state = `R_LOAD;
else if (init == 1)
next_state = `LOAD_00;
else if (init == 2)
next_state = `STB_WAIT;
end
`STB_WAIT: begin
if (strobe_l)
next_state = `STB_WAIT;
else
next_state = `N_LOAD;
end
endcase
end
endmodule

Looks like you fell into the trap of using two always blocks for your
state machine. Your counter is combinatorial and built with blocking
assignments. I'll bet this statement:

`CLK_L: begin
clk_o = 0; // clock low
cnt = cnt + 1;
if (cnt > 24)
next_state = `LE_H;
else begin
next_state = `CLK_H;
end

isn't working as you expect. Think about when the counter updates.
Think about how the comparison works.

Make the entire state machine a single, synchronous always block using
non-blocking assignments. Understand why this is better.

-a
 
JY schrieb:

However, some statements are not working.
Such as, cnt = cnt + 1 ...
If you code has to be synthesizable, you can only increment a variable
(and assign the result back to this variable) in an edge-triggered
always-block - in other words: cnt has to be a flipflop.

//minimal example
always @(negedge reset OR posedge clk)
begin
if (reset==1'b0) begin
cnt<=0;
end /*if posedge clk*/ begin
cnt<=cnt+1;
end //if
end //always


If you write something like

assign cnt = cnt + 1; //ERROR

or this (which is equivalent)

always @(cnt)
begin
cnt = cnt + 1; //ERROR
end //always

then you will get an infinite loop.


Ralf
 

Welcome to EDABoard.com

Sponsor

Back
Top