0
\$\begingroup\$

I have the following Verilog code to implement

module washing_machine(
    input clk, 
    input reset, 
    input start, 
    input full, 
    input cold, 
    input empty, 
    output ready, 
    output water_in, 
    output wash, 
    output drain, 
    output speed, 
    output heat_r
    ); 

    //declaracao simbolica de cada estado
    localparam [2:0] s_ready=3'b000, s_water_in=3'b001, s_wash=3'b010, s_drain=3'b011, s_speed=3'b100; 

    //declaracao dos sinais (variaveis internas)
    reg [2:0] state_reg;
    reg [2:0] next_state;
    wire count_en, sec_2, sec_4;

    //Condition for reset

    always @(posedge clk, posedge reset)
    begin
    if(reset) 
        state_reg <= s_ready;
    else 
        state_reg <= next_state;
    end

    always @*
    begin

    //next state procedural logic block and output logic
    next_state<=state_reg;
    case(state_reg)
        s_ready:
        begin
            if(start)
                next_state<=s_water_in;
        end
        s_water_in:
        begin
            if(full)
                next_state<=s_wash;
        end
        s_wash:
        begin
            if(sec_4)
                next_state<=s_drain;
        end
        s_drain:
        begin
            if(empty)
                next_state<=s_speed;
        end
        s_speed:
        begin
            if(sec_2)
                next_state<=s_ready;
        end
        default:
            next_state<=s_ready;
    endcase
    end

    //Moore output combinational logic
    assign ready=(state_reg==s_ready);
    assign water_in=(state_reg==s_water_in);
    assign wash=(state_reg==s_wash);
    assign drain=(state_reg==s_drain);
    assign speed=(state_reg==s_speed);
    assign count_en=(state_reg==s_wash)||(state_reg==s_speed);

    // Mealy combinational output logic
    assign heat_r=cold; //(state_reg==s_water_in && cold);


    timer time_end(clk,count_en,sec_4,sec_2);


    endmodule


module timer(
    input clk,
    input start,
    output sec_4,
    output sec_2
    );

    //Clock behaviour: freq 50MHz -> period 20 ns
    // Therefore: 2s => 100M periods and 4s=> 200 M periods
    // In binary: 100M=> 101111101011110000100000000 (27 bits)
    //        200M=> 1011111010111100001000000000 (28 bits)
    // 160 ns=> 8 periods (1000) ; 80 ns => 4 periods (100)
    localparam N=4;//N=28;
    reg[N-1:0] q_reg; 
    assign sec_2 = q_reg[N-2];
    assign sec_4 = q_reg[N-1];
    always@(posedge clk)
    begin
      if(start==1'b0)
        q_reg<=4'b0;
      else
        q_reg<=q_reg+1;
    end
endmodule

And I also have the respective testbench:

`timescale 1 ns / 1 ns

module testbench;

    // Inputs
    reg reset;
    reg clk;
    reg start;
    reg full;
    reg empty;
    reg cold;

    // Outputs
    wire ready;
    wire water_in;
    wire heat_r;
    wire wash;
    wire drain;
    wire speed;

    // Instantiate the Unit Under Test (UUT)
    washing_machine uut (
        .reset(reset), 
        .clk(clk), 
        .start(start), 
        .full(full), 
        .empty(empty), 
        .cold(cold), 
        .ready(ready), 
        .water_in(water_in), 
        .heat_r(heat_r), 
        .wash(wash), 
        .drain(drain), 
        .speed(speed)
    );

   always
   #10.0 clk = ~clk;

   initial begin
      // Initialize Inputs
        reset = 1;
        clk = 1;
        start = 0;
        full = 0;
        empty = 0;
        cold = 0;

      // Display initial message
      $display("Washing Machine FSM - TestBench 1.0");
        // Add stimulus here
      @(negedge clk)
         reset = 0;
      @(negedge clk)
         start = 1;
      $display("Time = %t ns, start assigned '1'", $time*10);
      @(negedge clk)
         full = 1;
      $display("Time = %t ns, full assigned '1'", $time*10);
      @(negedge clk)
         cold = 1;
      $display("Time = %t ns, cold assigned '1'", $time*10);
      @(negedge clk)
         cold = 0;
      $display("Time = %t ns, cold assigned '0'", $time*10);
      while(drain != 1) begin #10; end
      @(negedge clk)
         empty = 1;
      $display("Time = %t ns, empty assigned '0'", $time*10);
      while(ready != 1) begin #10; end
      $stop;
      end

      always @(posedge ready)
         $display("Time = %t ns, entering Ready state", $time*10);
      always @(posedge water_in)
         $display("Time = %t ns, entering Water In state", $time*10);
      always @(posedge wash)
         $display("Time = %t ns, entering Wash state", $time*10);
      always @(posedge drain)
         $display("Time = %t ns, entering Drain state", $time*10);
      always @(posedge speed)
         $display("Time = %t ns, entering Speed state", $time*10);
      always @(posedge heat_r)
         $display("Time = %t ns, heat_r asserted", $time*10);
      always @(negedge heat_r)
         $display("Time = %t ns, heat_r de-asserted", $time*10);

endmodule

Now, when I run this code I get the following output

Time resolution is 1 ps
Simulator is doing circuit initialization process.
Washing Machine FSM - TestBench 1.0
Time =                    0 ns, heat_r de-asserted
Finished circuit initialization process.
Time =                    0 ns, entering Ready state
Time =               300000 ns, start assigned '1'
Time =               400000 ns, entering Water In state
Time =               500000 ns, full assigned '1'
Time =               600000 ns, entering Wash state
Time =               700000 ns, cold assigned '1'
Time =               700000 ns, heat_r asserted
Time =               900000 ns, cold assigned '0'
Time =               900000 ns, heat_r de-asserted
Time =              2400000 ns, entering Drain state
Time =              2700000 ns, empty assigned '0'
Time =              2800000 ns, entering Speed state
Time =              3800000 ns, entering Ready state

Now this tells me that the transitions are done correctly, excepted the timed ones that are being timed off and that is because the state transitions are not made instantaneously. Basically, what I want to know is how do I make my state transitions instantaneous, to have something like:

Time = 300000 ns, start assigned '1' Time = 300000 ns, entering Water In state

Thanks in advance!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think (although I've not checked) this could be addressed by using "=" instead of "<=" in "next_state<=s_water_in;" etc \$\endgroup\$ – pjc50 Dec 20 '19 at 13:13
  • \$\begingroup\$ @pjc50 hey! just tested and no it doesn't solve the problem, unfortunately :/ \$\endgroup\$ – Granger Obliviate Dec 20 '19 at 13:20
0
\$\begingroup\$

You are changing the stimulus on the falling edge of the clock, such as "start assigned '1'". The state changes on the next rising edge of the clock, such as "entering Water in state". The way your code is written makes it impossible for them to happen simultaneously.

However, your inputs should not change at the same time as the clock edge that changes the state. This can cause unpredictable behavior in simulation and metastability in real life.

\$\endgroup\$
4
  • \$\begingroup\$ I realized that: a synchronous machine has to have the state changes synchronous to the rising edge (in my case) of the clock). The counting problem is solved by making counting_enable one when next_state is assigned. That way, in the next rising edge the timer starts counting immediately. \$\endgroup\$ – Granger Obliviate Dec 20 '19 at 14:55
  • \$\begingroup\$ I'm now, however with a problem, which is: how do I make heat_r only activate on the positive edge of the clock (after pressing cold)? \$\endgroup\$ – Granger Obliviate Dec 20 '19 at 15:06
  • \$\begingroup\$ heat_r is just a combinational copy of cold, so heat_r will change at precisely the same time as cold. If you want something to change on a clock edge you must register it with a flip-flop. But why you even have both heat_r and cold is a mystery to me. \$\endgroup\$ – Elliot Alderson Dec 20 '19 at 15:30
  • \$\begingroup\$ Thanks. It's mandatory for the work: cold is a pressing button, while heat_r is an output \$\endgroup\$ – Granger Obliviate Dec 21 '19 at 0:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.