# Delays and/or how to manually cycle clock in a loop when building Verilog testbench to test FSM for microcode/ROM conversion

I am working on a project wherein I need to convert a Finite State Machine coded in Verilog into a ROM. In order to do this I need to create a memory file for the ROM version of the FSM which stores the Next State and Output Values at Addresses comprised of the Current State and Input Values. My thought for how to build this file was to take the FSM in question and add "current_state" input, and "next_state" outputs, and then to make small modification to the fsm such that it uses those. However, I have had multiple issues with this tesbench that I can't seem to figure out so I figured I would throw together a smaller fsm to show what I am doing and hopefully get some insight as to what I am doing incorrectly. I believe my main issue is that the clock signal doesn't appear to be triggering at all (at least when I debug, the block which should be activiating at the posedge clock doesn't appear to ever trigger). The FSM in question I am attempting to model has something like 15 Current State and Input bits, and 76 Next State and Output bits, so rather than use any of the code from that I just threw together this smaller FSM (I get the same behavior so the issue isn't state machine specific and is likely more just due to my bad testbench).

So here is the FSM unit under test. It's a basic FSM I lifted from an old textbook:

    module mealy_traditional(input wire clk,
input wire reset,
input wire a,
input wire b,
output wire y);

//Symbollic State Definition
localparam [1:0]    state0 = 2'b00,
state1 = 2'b01,
state2 = 2'b10;
//signal declaration
reg [1:0]   stateCurrent,
stateNext;

//state register
always @(posedge clk, posedge reset)
if(reset)
stateCurrent <= state0;
else
stateCurrent <= stateNext;

//_______________________________________________________Next State Logic
always @* begin
stateNext = stateCurrent
//______________________________________________________START_CASE
case(stateCurrent)
//___________________________________________________state0
state0:
if(a)
if(b)
stateNext = state2;
else
stateNext = state1;
else
stateNext = state0;
//___________________________________________________state1
state1:
if(a)
stateNext = state0;
else
stateNext = state1;
//___________________________________________________state2
state2: stateNext = state0;
//__________________________________________________default
default: stateNext = state0;
endcase
end
//Mealy Output Logic, function of both current state and current inputs
assign y = (stateCurrent == state0) & a & b;
endmodule


And here is the same FSM modified (I believe) to accept the current state as an input and to assign the next state output to a wire output.

    module mealy_traditional(input wire clk,
input wire reset,
input wire [1:0] state_current,
input wire a,
input wire b,
output wire [1:0] state_next,
output wire y);

//Symbollic State Definition
localparam [1:0]    state0 = 2'b00,
state1 = 2'b01,
state2 = 2'b10;
//signal declaration
reg [1:0]   stateCurrent,
stateNext;

//state register
always @(posedge clk, posedge reset)
if(reset)
stateCurrent <= state0;
else
stateCurrent <= state_current;

//_______________________________________________________Next State Logic
always @* begin
stateNext = stateCurrent;
//______________________________________________________START_CASE
case(stateCurrent)
//___________________________________________________state0
state0:
if(a)
if(b)
stateNext = state2;
else
stateNext = state1;
else
stateNext = state0;
//___________________________________________________state1
state1:
if(a)
stateNext = state0;
else
stateNext = state1;
//___________________________________________________state2
state2: stateNext = state0;
//__________________________________________________default
default: stateNext = state0;
endcase
end
//Mealy Output Logic, function of both current state and current inputs
assign y = (stateCurrent == state0) & a & b;
assign state_next = stateNext;
endmodule


So here's where the issue almost certainly lies, the testbench. Now I know that given this FSM's limited inputs it would be very easy to just manually hit the fsm with each input combination and display the output, however, obviously with the other FSM that has close to 100 bits of IO, that's not really an option. Therefore I decided to create a for loop to just iterate through all possible input bit combinations and then generate the outputs to save into the memory file. The problem I run into is that it doesn't appear that the clock input cycles at all. Currently I am trying the following testbench code

timescale 1ns / 1ns
reg             clk = 1'b0;
reg             reset = 1'b0;
reg [3:0]       in;
wire [2:0]      out;
integer         i = 0;
integer         maxValue = 16;

//Instantiation
uut(.clk(clk),
.reset(reset),
.state_current(in[3:2]),
.a(in),
.b(in),
.state_next(out[2:1]),
.y(out));
initial begin

reset = 1;
#10
reset = 0;
#10
for(i = 0; i < maxValue; i = i + 1) begin
in = i;
clk = 1;
clk = 0;
clk = 1;
clk = 0;
$display("%b : %b", in, out); end$finish;
end
endmodule


initially I had tried to create a standalone clock cycle by using an

always #10 clk = ~clk;


And then putting delays inside the for loop, which verilog did NOT like (wouldn't even compile, threw syntax errors).

So as it stands right now, this testbench code does compile and the simulator fires up, however it's pretty clear that the else branch of the state register update in the FSM is not getting accessed as when I set break points in there they never trigger and the output of the state machine appears to be just the baseline state from a system reset. (as follows)

# 0000 : 00x
# 0001 : 00x
# 0010 : 00x
# 0011 : 00x
# 0100 : 00x
# 0101 : 00x
# 0110 : 00x
# 0111 : 00x
# 1000 : 00x
# 1001 : 00x
# 1010 : 00x
# 1011 : 00x
# 1100 : 00x
# 1101 : 00x
# 1110 : 00x
# 1111 : 00x


I would have thought manually forcing the clock cycle in the for loop would have cause the finite state machine to update but it appears to not have. Is there a way for me to ensure that the clock cycle fires in such a way?

Yes, the problem is in your testbench code. It is always a good idea to show the simulation time when you $display values as it helps to debug your problem. Doing so shows that all your output occurs at the same time (20ns):  20 0000 : 00x 20 0001 : 00x 20 0010 : 00x 20 0011 : 00x 20 0100 : 00x 20 0101 : 00x 20 0110 : 00x 20 0111 : 00x 20 1000 : 00x 20 1001 : 00x 20 1010 : 00x 20 1011 : 00x 20 1100 : 00x 20 1101 : 00x 20 1110 : 00x 20 1111 : 00x  The first column is the simulation time. The problem is that no time elapses inside the for loop. One way to fix that is to add # delays in the loop as follows: initial begin reset = 1; #10 reset = 0; #10 for(i = 0; i < maxValue; i = i + 1) begin in = i; #5 clk = 1; #5 clk = 0; #5 clk = 1; #5 clk = 0;$display($time,, "%b : %b", in, out); end$finish;
end


This prints:

          40 0000 : 000
60 0001 : 000
80 0010 : 010
100 0011 : 101
120 0100 : 010
140 0101 : 010
160 0110 : 000
180 0111 : 000
200 1000 : 000
220 1001 : 000
240 1010 : 000
260 1011 : 000
280 1100 : 000
300 1101 : 000
320 1110 : 000
340 1111 : 000


As you can see, the simulation time and out are changing value, and out no longer has unknowns (x).

Here is another way to write the testbench code. It uses the more traditional always block for the clock, which you were trying to get working. It also assures the input is synchronous with the clock.

initial begin
$monitor($time,, "%b : %b", in, out);
reset = 1;
#10
reset = 0;
#10
for (i = 0; i < maxValue; i = i + 1) begin
@(posedge clk) in <= i;
end
\$finish;
end

always #10 clk = ~clk;
`
{"ft_lang_label":"__label__en","ft_lang_prob":0.8136466,"math_prob":0.9345102,"size":5999,"snap":"2023-40-2023-50","text_gpt3_token_len":1540,"char_repetition_ratio":0.24553795,"word_repetition_ratio":0.22104144,"special_character_ratio":0.36322722,"punctuation_ratio":0.14272031,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.966652,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-10-04T01:21:31Z\",\"WARC-Record-ID\":\"<urn:uuid:73d8b46c-36af-40c2-a2f7-9a783c84d99f>\",\"Content-Length\":\"167148\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:d50e8d71-59e5-48a0-ab50-21f77410bf8f>\",\"WARC-Concurrent-To\":\"<urn:uuid:0e927e0b-061c-4f1e-aa24-932ddd5e6a81>\",\"WARC-IP-Address\":\"104.18.10.86\",\"WARC-Target-URI\":\"https://electronics.stackexchange.com/questions/592281/delays-and-or-how-to-manually-cycle-clock-in-a-loop-when-building-verilog-testbe\",\"WARC-Payload-Digest\":\"sha1:MMC2XDXC5MPLSDITNM2ZEGYBSEIP7SGV\",\"WARC-Block-Digest\":\"sha1:J3IR6MILJOXK6X5UR5HGCVMOYV7BK53U\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-40/CC-MAIN-2023-40_segments_1695233511284.37_warc_CC-MAIN-20231003224357-20231004014357-00637.warc.gz\"}"}